API Key Scopes
6 minute read
Introduction
Every Marketplacer API key carries a scope set — a list of tokens that declares exactly which parts of the API the key can reach. A key issued for “publish adverts” should not be able to reach into refunds, payouts, or admin role management; scopes make that boundary explicit on the key itself rather than leaving it to be enforced by your own code.
Scopes apply to both the GraphQL API and the REST API. Newly-issued keys carry exactly the scopes you ticked when creating them, and nothing else.
Scope token shape
A scope token is two colon-separated parts: a resource and a level.
adverts:read
orders:write
refunds:manage
A key’s scope set is the space-delimited list of these tokens, e.g. "adverts:read orders:read sellers:read". The empty string means “no scopes” — the key can only reach surfaces that are intentionally scope-free (login, the public catalogue, etc.).
Levels are hierarchical
The three levels are nested:
| Level | Includes | Used for |
|---|---|---|
read | reads only | Listing, searching, fetching detail records |
write | implies read | Creating and updating records |
manage | implies write & read | Destructive operations — deletes, irreversible state transitions |
So a key holding orders:write can also satisfy any field that requires orders:read. You only ever need to grant the highest level the key actually needs; the create-key form records one token per resource.
Resources
Each resource groups a slice of the API surface that a single scope token grants access to. The following list is the full catalogue:
| Resource | Levels available | Covers |
|---|---|---|
| Adverts | read/write/manage | Adverts, variants, attachments, images, mappings, advert metadata, category suggestions, AI transformations |
| Golden Products | read/write/manage | The operator-curated master product catalogue and its variant/option metadata |
| Orders | read/write/manage | Orders, invoices, line items, shipments, return shipments, invoice amendments, invoice annotations |
| Refunds | read/write/manage | Refund requests and their line-item flow, including approve/deny/refund/return |
| Shipping Settings | read/write/manage | Shipping options/profiles/rates/zones, Shippit credentials and shipment booking |
| Payments | read/write/manage | Payment events, payment methods, billing, Adyen/Braintree settings |
| Remittances | read/write/manage | Seller remittances, remittance advices, remittance events |
| MPay | read/write/manage | Marketplacer Pay deposits, payout details, deposit reconciliations |
| Sellers | read/write/manage | Seller records, multi-store memberships, commission packages, onboarding processes, seller stats |
| Users | read/write/manage | Seller-side user accounts under your seller record |
| Admins | read/write/manage | Operator admin identities, admin roles, permission catalog, Rithum API keys |
| Webhooks | read/write/manage | Webhook subscriptions and webhook event delivery records |
| Imports and Exports | read/write/manage | Spreadsheet import/export jobs across every domain (orders, sellers, commission packages, …) |
| Audit | read only | Activity logs, change logs, contextual history of records you can already see |
| Messaging | read/write/manage | In-app chat |
| Catalog Rules | read/write/manage | Catalog rules engine |
| Promotions | read/write/manage | Promotion records |
| Inquiries | read/write/manage | Customer inquiries directed at sellers |
| API Keys | read/write/manage | Listing, creating, and revoking other API keys you own |
| Site Config | write/manage | Operator-only — write side of the per-vertical site configuration. Reads are intentionally scope-free. |
| Taxonomy | write/manage | Operator-only — write side of taxons, option types/values, tax codes, custom fields, prototypes, measurement units. Reads are intentionally scope-free. |
Site Config and Taxonomy have no
readlevel because the corresponding read-side surfaces (the catalogue, the per-vertical config) are designed to be reachable without an API key scope at all — every integration needs them.
What needs no scope
Some surfaces are intentionally scope-free regardless of the key’s scope set. They fall into five categories:
- Public catalogue — taxons, brands, models, countries, option types/values, refund reasons, prototypes, custom-field templates, etc. These describe the marketplace itself, not any seller’s records.
- Public config — the site config tree (
SiteConfigand its sub-settings), feature flags, branding, health checks, translations. - Auth primitives — login mutations, MFA enrolment/verification, session token operations. Requiring a scope here would be a chicken-and-egg failure — you don’t have a key yet.
- Self lookup — the
userquery that resolves “who am I” from the calling credential. - Derived data — value-shaped types such as
Money,Address,KeyValue, error/validation messages. These never carry resource data of their own; the parent object’s scope already gated them.
You don’t need to do anything to reach these — even a key with an empty scope set works.
Choosing scopes for an integration
The create-key form lets you tick exactly the scopes your integration needs. As a rule of thumb:
- Start from your integration’s job description. “Sync adverts and inventory each night” maps to
adverts:writeand probablyimports_exports:writefor spreadsheet uploads. A reporting integration that just pulls order data isorders:read. - Use
readunless you actually mutate. Most integrations are predominantly read-side. Grantingwriteormanageyou don’t need expands the blast radius if the key leaks. - Skip
manageunless you actually delete or destructively transition records.writecovers create/update for almost every domain. - Don’t tick resources you don’t touch. A separate, tightly-scoped key per integration is easier to revoke if one of those integrations is compromised.
A typical advert-sync integration ends up with three or four scopes. A back-office reporting integration ends up with one or two. Ticking a higher level visually checks the lower ones — that’s just the hierarchy showing through. Only the highest-level token per resource is recorded on the key.
Pre-existing keys without scopes
Keys created before scopes existed carry no scope set at all. By default these legacy keys keep working as they always did — they’re treated as fully-trusted so existing integrations don’t break the day scopes ship.
Operators can disable this grandfathering on a per-vertical basis once the key fleet has been audited and re-issued with explicit scopes. The vertical-level setting is Authentication Settings → Legacy unscoped API keys grant full access; setting it to false means any remaining scope-less key is rejected. Set it once you’re confident every legacy integration has been migrated to a scoped key.
Keys created from the create-key form always have a real scope set, so this grandfathering doesn’t apply to them.
What happens when a scope is missing
A request that lacks a required scope is denied rather than ignored:
GraphQL — the field returns
nulland a structured error is included in theerrorsarray:{ "errors": [ { "message": "Missing required scope: orders:write", "extensions": { "code": "MISSING_SCOPE", "scope": "orders:write" }, "path": ["orderCreate"] } ], "data": { "orderCreate": null } }The
extensions.codevalue is alwaysMISSING_SCOPE, andextensions.scopeis the scope you’d need to add. Other GraphQL fields in the same query that the key does have access to still resolve normally.REST (v2) — the response is HTTP
403with a JSON:API error body:{ "errors": [ { "status": "403", "code": "MISSING_SCOPE", "title": "Missing required scope", "detail": "This endpoint requires the 'adverts:write' scope.", "meta": { "scope": "adverts:write" } } ] }
In both cases the fix is the same: re-issue the key with the missing scope ticked. (You cannot edit an existing key’s scopes; create a new key with the right set, deploy it, then revoke the old one.)
Scope descriptions in the schema
The auto-generated GraphQL schema documentation calls out the required scope for every field. Hovering over a field in GraphQL Voyager or browsing the text schema shows trailers like:
Requires API key scope adverts:write.
Requires API key scopes orders:read and imports_exports:write.
No API key scope required.
If you’re unsure what scope a particular query or mutation needs, that’s the authoritative source.
Rotating scoped keys
Scopes are part of the credential, so any time you rotate a key per the API Key Rotation playbook you can also re-evaluate its scopes. Two common reasons to re-issue with different scopes:
- The integration’s job has narrowed (e.g. dropped a write surface) — issue the rotated key with fewer scopes.
- The integration grew (e.g. now also processes refunds) — issue the rotated key with the additional scopes ticked.
Because you can’t edit an existing key, rotation is the natural moment to right-size scope grants.