Skip to content

Sessions vs API keys

Two different credentials reach the same API, and mixing them up is a common first stumble.

An API key is what an integration uses. It is a pk_live_ secret sent in an Authorization: Bearer header on every request, with no token exchange and no refresh step. Everything it can reach is bounded by its scopes.

A browser session is what the portal uses. POST /api/v1/session exchanges a portal token for a session cookie, and DELETE /api/v1/session signs out.

Signing out or switching accounts clears the previous account’s in-memory query cache and resets its open pages and unsaved form state. The portal waits for the new account’s session to be verified before showing private pages; data from the previous account is not used as a loading placeholder.

Private portal requests also identify the expected account and company. If a session cookie from another tab belongs to a different account, the server rejects the request before returning data or applying a change, and the portal attempts to refresh its session.

Save any edits before signing out. A sign-out received from another tab also closes the current tab’s private view. This does not remove files you have already downloaded to your computer.

The opportunity routes take an API key. Key management does not: GET, POST and DELETE on /api/v1/api-keys are performed from a signed-in browser session.

That is a deliberate boundary. An API key can never mint another API key, so a leaked key cannot create successors for itself ahead of your revoking it.

One more asymmetry worth knowing. The membership-related error codes (no_membership, membership_disabled, unverified_email and identity_conflict) surface on browser sessions, not on key auth. If a key-authenticated request returns one of those, something other than scopes is wrong.

GET /api/v1/scopes sits outside both. It is public, so you can read the scope vocabulary before you have any credential at all.