What you store
Public or browser clients can start a connection session. They must not hold
client_secret.
Discovery
authorization_endpoint, token_endpoint, introspection_endpoint, revocation_endpoint, supported grants, and S256 as the only code-challenge method.
Authorization-code + PKCE
1
Create a code verifier and S256 challenge
The verifier is 43–128 characters of unreserved URL-safe text. The challenge is the Base64URL SHA-256 of that verifier, without padding.
2
Request an authorization code
POST /oauth/authorize with response_type=code, exact redirect_uri, customer_id, space-separated scope, and code_challenge_method=S256.3
Exchange the code
POST /oauth/token with grant_type=authorization_code, code_verifier, client_id, client_secret, and the same redirect_uri.4
Call the API
Send
Authorization: Bearer <access_token>. Access tokens last about 15 minutes. Authorization codes last about 5 minutes and are single-use.Introspect and revoke
tokens:introspect. Revoke does not send a Bearer header. Tokens are hashed at rest.
Redirect URIs
- Must be HTTPS in production (localhost is acceptable in sandbox)
- Must match a registered URI exactly — no wildcards, no trailing-slash drift
- Browser/public clients also need allowed origins if they call from a web SDK
Scope templates
Start from a template. Add scopes only when a call needs them.scope on authorize is a space-separated string. It must be a subset of the app’s allowed scopes.
Common errors
Security rules the API enforces
- PKCE
S256only (plainis rejected) - Short-lived access tokens
- Hashed secrets and tokens at rest
- Exact redirect match
- Purpose-checked ingest and reads after you have a token
- Authorization failures stay generic and never include secrets