Authentication
Every request needs an API key in the Authorization header:
Authorization: Bearer pak_...
The word Bearer is not case-sensitive. Keys are read only from this header, never from query parameters or cookies; the API doesn't use your portal session.
Permissions
Each key has a list of permissions chosen when you create it. A call without the permission it needs returns 403 insufficient_scope. GET /v1/me works with any valid key and lists the key's permissions.
| Permission | What it allows | In "Read only" | In "Read and create orders" | Endpoints |
|---|---|---|---|---|
wallet:read |
View wallet balance and transactions | Yes | Yes | GET /v1/wallet, GET /v1/wallet/ledger, GET /v1/wallet/top-ups |
catalog:read |
View products and inventory | Yes | Yes | GET /v1/products, GET /v1/products/{id}, GET /v1/inventory |
orders:read |
View orders | Yes | Yes | GET /v1/orders, GET /v1/orders/{id}, POST /v1/orders/preview |
purchase_orders:read |
View purchase orders | Yes | Yes | GET /v1/purchase-orders, GET /v1/purchase-orders/{id} |
shipments:read |
View shipments | Yes | Yes | GET /v1/shipments, GET /v1/shipments/{id}, POST /v1/shipments/estimate |
requests:read |
View sourcing requests | Yes | Yes | GET /v1/requests, GET /v1/requests/{id} |
quotes:read |
View quotes | Yes | Yes | GET /v1/quotes, GET /v1/quotes/{id} |
catalog:write |
Map your SKUs to products | No | No | POST /v1/sku-mappings |
orders:write |
Create, change and cancel orders | No | Yes | POST /v1/orders, PATCH /v1/orders/{id}, POST /v1/orders/{id}/cancel |
shipments:write |
Request, cancel and confirm shipments | No | No | POST /v1/shipments, POST /v1/shipments/{id}/cancel, POST /v1/shipments/{id}/confirm |
requests:write |
Submit sourcing and reorder requests | No | No | POST /v1/requests/sourcing, POST /v1/requests/reorder |
The access levels you can choose when you create a key:
| Access level | Permissions |
|---|---|
| Read only | wallet:read, catalog:read, orders:read, purchase_orders:read, shipments:read, requests:read, quotes:read |
| Read and create orders | wallet:read, catalog:read, orders:read, purchase_orders:read, shipments:read, requests:read, quotes:read, orders:write |
| Custom | The ones you tick |
Give each integration the smallest set it needs. Permissions can't be changed later: create a new key and revoke the old one.
Why a key is refused
Keys are checked on every request, so revoking a key or turning API access off takes effect at once.
| Situation | Status | Code |
|---|---|---|
No Authorization header, not a Bearer value, or a malformed, unknown or revoked key |
401 | invalid_api_key |
| The portal user who created the key was deactivated or no longer belongs to your account | 401 | invalid_api_key |
| API access is turned off for your account | 403 | api_not_enabled |
| The user who created the key must change a temporary password: sign in to the portal and finish that step | 403 | account_action_required |
| The key lacks the permission the endpoint needs | 403 | insufficient_scope |
| Your account is on hold: writes are refused, reads keep working | 403 | account_on_hold |
Keys don't expire. Changing your portal password doesn't revoke them. When API access is turned off your keys are kept, and they work again when it is turned back on.
Failed attempts are rate limited
Requests with a malformed, unknown, revoked or no longer valid key (its creator was deactivated or left the account) count as failed attempts for the network (IP address) they come from: 30 an hour and 200 a day. After that, failed attempts get 429 rate_limited with Retry-After. A request without a Bearer Authorization header doesn't count, and a valid key is never blocked by this, even from the same network. See Rate limits.
Managing keys
Settings → API access lists each key with its name, the start of the key, its permissions, when it was created and when it was last used (updated every few minutes at most). Revoke keys there. We email your account when a key is created. Keys and webhook endpoints can only be managed in the portal, so a program that has a key can't create more keys or add webhook endpoints.
Keep keys out of browsers
The API sends no CORS headers: calls from a web page fail, and a key in a web page or app is visible to anyone who opens it. Call the API from your server.