Prebit Developer Docs

Authentication

Bearer tokens, scopes, capabilities, and the Platform Kernel.

Every Partner API v1 request authenticates the same way:

Authorization: Bearer <access_token>

There is no API-key mode and no query-string token mode — bearer header only. The access token identifies one installation (one app, installed on one store), never a whole developer org or a whole app across every store it's installed on.

Where the token comes from

Access tokens are minted by the OAuth token endpoint. There is no other way to obtain one — Partner API v1 has no separate API-key concept distinct from OAuth tokens.

Not the same as a CLI login token

prebit login's personal access token (prcli_...) authenticates you (a developer) to the Developer Portal's own management routes (submitting releases, reading health). It is a completely different credential from the per-installation OAuth access_token your app uses to call Partner API v1 on a merchant's behalf. See CLI.

What a request is authorized against

Every request is checked against two independent things, both drawn from your specific installation's granted state — never from what your app merely requested at manifest-submission time:

  • Scopes gate data access — e.g. read_products, write_products, read_orders, read_customers, read_customer_pii, read_collections, write_collections, read_store.

  • Capabilities gate runtime privileges, independent of data access:

    CapabilityGrants
    can_register_background_jobRegister an app-triggered ("sync now") background job
    can_schedule_jobRegister a cron-scheduled job
    can_use_event_subscribeSubscribe to webhook topics
    can_write_extension_storageRead/write Extension Storage
    can_use_billing_apiUse billing = "prebit"

A merchant can grant your app fewer scopes/capabilities than you requested in your manifest — always check the granted set (returned as scope on the token response), never assume you have everything you asked for.

Every request passes through one authorization layer

Internally, every Partner API v1 route calls a single function — the Platform Kernel — before doing anything else. This is what actually enforces the rules above, and it's also what:

  • Rate-limits your installation: a flat 100 requests / 60-second rolling window per installation today (deliberately simple for a handful of curated partners; a per-endpoint cost-weighted budget is the planned evolution). Exceeding it returns 429. There is currently no X-RateLimit-* response header — build your own backoff on 429 rather than polling a quota header that doesn't exist.
  • Rejects a non-active installation — if the merchant uninstalled your app or it was suspended, every call returns 403, even with an otherwise-valid token.
  • Logs every call, which is what powers App Health (uptime/error-rate visible to the merchant) and what drives automatic capability revocation if your app's error rate breaches a threshold.

Error responses

StatusBodyCause
401{"error":"Missing bearer token"}No Authorization header
401{"error":"Invalid or expired access token"}Token doesn't verify, or is expired/revoked
403{"error":"This installation was not granted the \"<scope>\" scope"}Missing scope
403{"error":"Installation is not active"}Uninstalled/suspended
403{"error":"This installation was not granted the \"<capability>\" capability"}Missing capability
429{"error":"Rate limit exceeded — retry after a short backoff"}Over the rolling-window limit

Token modes: offline vs. online

Every installation's tokens are one of two modes, chosen at install time:

  • Offline — a service-account-style token for background jobs, scheduled jobs, and webhook-driven writes with no live staff session behind them. Audit entries attribute these to "{AppName} (automated)".
  • Online — represents a specific staff member's in-app action. Audit entries attribute to "{AppName}" without the "(automated)" suffix.

Most backend integrations only need offline tokens.

On this page