api reference
API reference
The Phosphor API is REST-shaped, JSON in and out, versioned by date. Everything below is live against your current sandbox, so the example key in each snippet is the one sitting in your environment right now.
Authentication
Send your secret key as a bearer token on every request. Keys prefixed sk-live- move real money; sk-test- keys hit the sandbox. Never ship a secret key to a browser or a mobile client — exchange it server-side for a short-lived access token instead.
POST /v1/tokens
Authorization: Bearer sk-live-9f4K…
Content-Type: application/json
# → 201 Created · { "access_token": "at_8Jf2…", "expires_in": 900 }
Keys are shown in full exactly once at creation. If you lose one, revoke it and generate a replacement — support cannot recover it.
Endpoints
All list endpoints take limit (default 20, max 100) and return a cursor in next_cursor. Numeric columns are right-aligned in every client we ship; latency below is p50 measured over the last 24 hours.
Charges
- GET/v1/chargesList charges with cursor pagination.82ms
Customers
- GET/v1/customersList customers in your workspace.77ms
Webhooks
- GET/v1/webhooksList configured webhook endpoints.58ms
Eventsbeta
- GET/v1/eventsStream recent API events.71ms
Core
- GET/v1/balanceRetrieve current ledger balance.49ms
Auth
- POST/v1/tokensExchange credentials for an access token.143ms
In practice: create a charge
A full request/response pair, exactly as it leaves your shell and comes back. The Idempotency-Key header makes the call safe to retry on any network failure.
$ curl -X POST https://api.phosphor.dev/v1/charges
-H 'Authorization: Bearer sk-live-9f4K…'
-H 'Idempotency-Key: 7f3a9c2e-orders-4471'
-d amount=2400 -d currency=usd
-d customer=cu_9Vt4mX1pQe
{
"id": "ch_3Ln9xQ2mKw",
"amount": 2400,
"currency": "usd",
"status": "succeeded",
"idempotency_replayed": false
}
Errors
Errors return a machine-readable code plus a human sentence. 4xx means fix your request; 5xx means it's on us and the request is safe to retry with the same idempotency key.
| http | code | what it means |
|---|---|---|
| 400 | invalid_request | A parameter failed validation; the message names the field. |
| 401 | unauthenticated | Missing or revoked key. Check the Authorization header. |
| 403 | forbidden | The key is valid but lacks the scope this endpoint requires. |
| 404 | not_found | No object with that ID in this environment — check live vs test. |
| 409 | idempotency_conflict | Same idempotency key, different payload. Pick a new key. |
| 429 | rate_limited | Back off for the number of seconds in the Retry-After header. |
| 500 | internal | Our fault. Retry with the same idempotency key; alert us if it persists. |
Rate limits
Limits apply per key, per minute, with a token bucket that refills continuously. Every response carries X-RateLimit-Remaining so you can shed load before you hit the wall.
| environment | requests / min | burst |
|---|---|---|
| test | 100 | 200 |
| live | 600 | 1,200 |
| live · enterprise | 3,000 | 6,000 |
Batch imports need a heads-up
Planning to backfill more than 50k objects? Tell us 24 hours ahead via the support channel and we'll lift your burst ceiling — surprise migrations get throttled to keep the fleet honest.