Authentication and scopes
Sessions, access tokens, API keys and the scopes each operation needs.
Who can call
| Caller | Sends | May do |
|---|---|---|
| The web app | its session cookie | everything the signed-in person can do |
| The native app | Authorization: Bearer <access token> (a signed-in session’s token) | the same |
| An integration | Authorization: Bearer ck_live_… (an API key) | only what the key’s scopes allow, as the key’s owner |
API keys are coming soon
Keys arrive with the next release (ENGIN-45). Until then, routes that need sign-in take a signed-in session only: the web app’s cookie or the native app’s access token. The key details below describe how they’ll work.
What each route requires
Each operation in the reference says who may call it:
- Public: anyone. A session or key is used when present. Signed-out callers are rate limited per network on some routes.
- Signed in: a signed-in person. Without credentials the answer is
401 unauthorized, before anything is read. - Store member: a member of the store named in the path.
- Admin and Moderator: anyone else gets the same
404 not_foundas a route that doesn’t exist.
API keys
| Kind | Made in | Acts as | Notes |
|---|---|---|---|
| Personal | Settings → API keys | you | Your own scripts, spreadsheets and tools. |
| Store | the store’s dashboard → API keys (owners and admins) | the manager who made it, for that store only | For a point of sale or inventory system. It stops working if its maker leaves the store or becomes staff. Store owners are emailed when someone makes one. |
| Admin | Admin → API keys (admins and moderators) | you, while you’re on staff (checked on every request) | Must expire within 90 days, can be limited to IP addresses, and needs a recent sign-in to make. Every write it makes is in the audit log. Moderators’ keys get moderation scopes only. |
A key looks like ck_live_abcd1234_… in production and ck_test_… elsewhere. The abcd1234 part is its public prefix, shown in key lists and the audit log. The whole key is shown once, when it’s made; only an HMAC of the secret is stored. Send it as a bearer token:
curl 'https://collection.id/api/v1/holds' \
-H "Authorization: Bearer $COLLECTOR_TOKEN"import { createCollectorClient } from '@collector/sdk';
// Called before every request, so it can hand over a refreshed token.
const collector = createCollectorClient({
token: async () => process.env.COLLECTOR_TOKEN,
});
const { data, requestId } = await collector.withResponse.listMyHolds();
console.log(`${data.holds.length} holds (request ${requestId})`);Scopes
A key holds one or more scopes, such as collection:read or store:inventory:write. Every operation keys may call lists the scopes it needs: in the reference (“Key scopes”) and in the OpenAPI document (x-scopes). A key needs every listed scope its kind of key can hold. Routes a buyer and a shop share list both sides’ scopes, and each side’s key needs only its own: a hold’s messages list holds:write for the buyer and store:holds:write for the shop.
- Public routes accept any valid key.
- Personal keys reach collectors’ routes; store keys their own store’s; admin keys admin and moderation.
- Operations that list no scopes aren’t available to keys at all, including managing keys.
account:deletecan’t be held by any key: deleting an account takes the person, signed in.
Key errors
| Status | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | Unknown, revoked or expired key, a test key in production (or the reverse), or an owner who can no longer use it. |
| 403 | insufficient_scope | The key lacks a scope the operation needs. |
| 403 | key_not_allowed | The operation isn’t available to keys, or not to this kind of key. |
| 403 | ip_not_allowed | An admin key used from outside its allowed addresses. |
| 404 | not_found | A store key calling another store’s routes (answered as if they didn’t exist). |
Keeping keys safe
- Treat a key like a password: keep it in a secret manager, never in code or a public repository.
- Give each integration its own key, with the fewest scopes it needs, and an expiry.
- Rotate keys on a schedule. Rotating can keep the old key working for 24 hours so integrations switch over without an outage. Revoke a key at once if it might have leaked.
- Limit admin keys to your servers’ addresses, and keep them short-lived.
OAuth for third-party apps, so people can connect your app without handing you a key, comes later (ENGIN-52).