Amba

Token reference

All five Amba token types — developer PAT, internal token, client key, server key, and end-user session JWT — with the exact header, endpoint group, lifetime, and what each cannot do.

Amba uses five distinct token types. They are not interchangeable: using the wrong token on an endpoint returns a specific error code that identifies the mismatch.

At a glance

TokenPrefixHeaderEndpoint groupLifetime
Developer PATamb_dpat_Authorization: BearerAll /v1/admin/*Until rotated
Developer JWTeyJ… (HS256)Authorization: BearerAll /v1/admin/*24 h
Internal tokenamb_int_Authorization: BearerProject-scoped /v1/admin/projects/:id/* onlyUntil rotated
Client API keyamb_dev_ck_ / amb_live_ck_X-Api-KeyAll /v1/client/*Until revoked
Server API keyamb_dev_sk_ / amb_live_sk_X-Api-Key or Authorization: BearerProject-scoped /v1/admin/projects/:id/* + server-side client callsUntil revoked
End-user session JWTeyJ… (HS256)Authorization: BearerUser-scoped /v1/client/*30 days

Developer PAT

Prefix: amb_dpat_ (followed by 32 base64url characters)

The recommended credential for every developer-authenticated call. The developer PAT is long-lived, doesn't require a refresh dance, and is the credential the MCP server and CLI use by default.

How to obtain:

  • Returned as data.pat in the POST /auth/developer/signup response (one-time — the plaintext is shown once).
  • Rotate at any time: POST /auth/developer/pat/rotate (authenticated with the current PAT or a fresh session JWT). The old PAT becomes invalid within 30 seconds (cache TTL). Rotating also disconnects every app connected through OAuth (the console's Connected apps page lists them); the response's oauth_grants_revoked counts them.
  • Via MCP: amba_developer_rotate_pat.

Usage:

curl https://api.amba.dev/v1/admin/projects \
  -H "Authorization: Bearer amb_dpat_…"

What it authenticates: All /v1/admin/* routes — project list/create, developer profile, API key management, every project-scoped admin operation.

What it cannot do:

  • Authenticate /v1/client/* routes (those require an API key in X-Api-Key).
  • Authenticate webhook endpoints (those use provider-specific HMAC signatures).

Storage: One PAT per developer account, stored as a sha256 hash in the control database — the plaintext is never persisted.


Developer JWT

Format: HS256 JWT (eyJ…) with claims type=developer, iss=amba, sub=<developerId>

The developer access JWT is issued alongside a refresh token by POST /auth/developer/signup and POST /auth/developer/login. The console uses it for browser-session auth; the MCP server mints a short-lived (5-minute) internal variant when converting an OAuth token to a downstream API call.

What it authenticates: Same /v1/admin/* surface as the developer PAT.

What it cannot do: Same restrictions as the developer PAT above. Additionally, it expires after 24 hours, and stops working as soon as its session ends (POST /auth/developer/logout, or a refresh token presented twice) — use the developer PAT for long-running agent or server contexts where a refresh loop is impractical. See Sessions.

How to obtain: The access_token field in the POST /auth/developer/signup, POST /auth/developer/login, or POST /auth/developer/otp/verify response (the last is the passwordless path: request a 6-digit code with POST /auth/developer/otp/request, then redeem it). Refresh via POST /auth/developer/refresh using the accompanying refresh_token (valid 30 days, rotating on use).


Internal token

Prefix: amb_int_ (followed by 32 base64url characters)

The internal token is a project-scoped credential. It authenticates a single project's subset of admin routes and is injected automatically into the Amba functions runtime as env.AMBA_INTERNAL_TOKEN. You never create or rotate it manually — Amba provisions it when your project is created and rotates it transparently with a 120-second overlap window.

What it authenticates: /v1/admin/projects/:projectId/* — but only for the project the token belongs to. Using a token from project A on a URL containing project B's ID returns 403 WRONG_PROJECT. Using an invalid or revoked token returns 401 INVALID_INTERNAL_TOKEN.

What it cannot do (and this is the common confusion):

  • It does NOT authenticate global admin routes. Routes like GET /v1/admin/projects (list all projects) or POST /v1/admin/projects (create a project) require a developer PAT or JWT — they reject amb_int_* with 401 INVALID_DEVELOPER_TOKEN. If you see INVALID_DEVELOPER_TOKEN when making admin calls, you are using an internal token where a developer PAT is required.
  • It does NOT authenticate /v1/client/* routes.
  • It does NOT authenticate another project's admin routes.

Usage inside a function:

// env.AMBA_INTERNAL_TOKEN is injected at deploy — no setup needed.
const res = await fetch(
  `${env.AMBA_API_URL}/v1/admin/projects/${env.AMBA_PROJECT_ID}/collections/configs/rows?key=launch_config`,
  { headers: { Authorization: `Bearer ${env.AMBA_INTERNAL_TOKEN}` } },
);

The token is also used by Amba internal routing (the platform's own infrastructure components calling back into the API). That surface is not customer-accessible and is handled automatically — you only ever interact with this token through env.AMBA_INTERNAL_TOKEN in your functions.


Client API key

Prefixes: amb_dev_ck_ (development) / amb_live_ck_ (production)

The client API key is the project-identifying credential for all end-user-facing SDK and HTTP calls. It is not secret — it ships inside mobile apps and browser bundles by design.

How to obtain: The full key appears once, in the response that creates it: signup, POST /v1/admin/projects, or POST /v1/admin/projects/:projectId/api-keys (the amba_api_keys_create MCP tool). GET /v1/admin/projects/:projectId lists each key's key_prefix only, so store the key when you create it and mint a new one if it's lost.

Usage:

curl https://api.amba.dev/v1/client/auth/anonymous \
  -H "X-Api-Key: amb_dev_ck_…" \
  -H "Content-Type: application/json" \
  -d '{}'

What it authenticates: All /v1/client/* routes when passed as X-Api-Key. User-scoped routes additionally require the end-user session JWT in Authorization: Bearer.

What it cannot do:

  • Authenticate /v1/admin/* routes.
  • Act on behalf of a specific user without a session token (use a server key + X-On-Behalf-Of for server-side user operations).

Server API key

Prefixes: amb_dev_sk_ (development) / amb_live_sk_ (production)

The server API key is the server-side counterpart to the client key. It is secret — never embed it in a mobile app or browser bundle.

How to obtain: Same as client keys — returned in the project key set at signup, or created via POST /v1/admin/projects/:projectId/api-keys.

What it authenticates:

  1. Project-scoped admin routes (/v1/admin/projects/:projectId/*) — pass as Authorization: Bearer:

    curl https://api.amba.dev/v1/admin/projects/$PROJECT_ID/users \
      -H "Authorization: Bearer amb_dev_sk_…"

    The server key is validated against the project it was created for; using it on a different project's URL returns 403 WRONG_PROJECT.

  2. Server-side client operations (/v1/client/* on behalf of a user) — pass as X-Api-Key alongside X-On-Behalf-Of: <userId>:

    curl https://api.amba.dev/v1/client/users/me \
      -H "X-Api-Key: amb_dev_sk_…" \
      -H "X-On-Behalf-Of: <userId>"

    This is the mechanism the Node SDK's asUser() method uses. The server key must belong to the project; the userId must be a user in that project's database.

What it cannot do:

  • Global admin routes (project list/create, developer auth) — those require a developer PAT.
  • Replace the developer PAT for non-project-scoped operations.

End-user session JWT

Format: HS256 JWT (eyJ…) with claims type=session, sub=<userId>, pid=<projectId>

End-user session JWTs authenticate individual users on client-plane routes. The SDK acquires and rotates them automatically via the auth flow; you rarely handle them directly.

How to obtain: Returned as session_token by any /v1/client/auth/* sign-in endpoint. Refreshed automatically by the SDK; manually via POST /v1/client/auth/refresh.

Usage: Always paired with the client API key:

curl https://api.amba.dev/v1/client/users/me \
  -H "X-Api-Key: amb_dev_ck_…" \
  -H "Authorization: Bearer <session_token>"

The pid claim inside the JWT must match the project that owns the X-Api-Key — the API rejects cross-project replays with 403 SESSION_PROJECT_MISMATCH.

Lifetime: 30 days. The refresh token that can renew it is valid for 90 days and rotates on use. A refresh token can be presented again within 30 seconds of its first use and returns a new pair, as long as the session it was exchanged for is still active; after that a replayed refresh token is detected and rejected.

Anonymous → identified is in place. When an anonymous user signs in via POST /v1/client/auth/link, Amba attaches the new credential to the same user — the user_id is unchanged and all of that user's data (collections, currency, inventory, streaks, XP, entitlements) is preserved. A link that adds an identity gives the user a new anonymous_id (returned in user.anonymous_id), and the old one no longer signs in to the user. The OTP / email-password link paths keep the existing session valid unless the call sends rotate_session: true. You never have to migrate anonymous data into a "real" account — there's only one account. See Account linking.

What it cannot do:

  • Authenticate any /v1/admin/* route.
  • Stand in for the X-Api-Key header — both must be present on user-scoped client routes.

Quick-reference: error codes

Error codeMeaning
MISSING_AUTH_HEADERNo Authorization header where one is required
INVALID_AUTH_SCHEMEAuthorization header present but not Bearer
MISSING_API_KEYNo X-Api-Key where one is required
INVALID_API_KEYAPI key hash not found or revoked
INVALID_PATDeveloper PAT hash not found or revoked
INVALID_DEVELOPER_TOKENDeveloper JWT failed signature or expiry check
INVALID_INTERNAL_TOKENInternal token (amb_int_*) not found or revoked
INVALID_SESSION_TOKENEnd-user session JWT failed signature or expiry
SESSION_PROJECT_MISMATCHSession JWT pid doesn't match the request's API key project
WRONG_PROJECTServer key or internal token used on a different project's URL
PROJECT_NOT_FOUNDProject id malformed, or a project your token doesn't manage
MISSING_ON_BEHALF_OFServer key used on a user-scoped route without X-On-Behalf-Of

On this page