Who this is for. The developer connecting a front end or an app that the platform does not serve. After this page you can choose a credential for each kind of client and explain to a stakeholder why the browser cannot call the API directly. The full reference, with every header and error, is Authentication and authorisation in Guide 6.

Choosing by client

ClientCredentialWhy
Your headless front end's serverOAuth, authorisation code, signed in once as a backend user made for the front end; keep its refresh tokenThe token is limited to that user's permissions and expires after four hours. An API key on the same user is the older option and still works
A mobile or desktop app used by staffOAuth, authorisation code with PKCEThe person signs in on the site; the app never sees a password
A third-party service the client connects to the siteOAuth, with a client registered for itEach person grants access, and can take it back
A one-off scriptAn API key, deleted afterwardsQuick to issue, and nothing outlives the job
JavaScript on the site's own pagesThe visitor's session, with the CSRF token on writesNothing to store in the page. This is the hybrid shape, not headless (One client module)
JavaScript on a page of another originNone worksThe platform sends no cross-origin headers, below

Tokens and keys

Both are sent the same way, as Authorization: Bearer …. An OAuth access token starts with CDNA-A-, and that prefix is how the platform tells the two apart: anything after Bearer that does not start with it is looked up as an API key. API keys have no prefix of their own.

An API key belongs to one backend user and can do what that user can do, no more. It can be limited to a list of IP addresses, which is worth doing for any key used from a server with a fixed address. Create a user for each integration rather than issuing keys on a person's account: removing the integration is then deleting one user. OAuth clients in Guide 6 walks through the authorisation-code flow and refreshing a token.

Why a separate front end cannot use the site's session

A headless front end usually runs on a hostname of its own, and from there the site's session is out of reach for two reasons. The platform sends no cross-origin (CORS) headers, so a browser running a page from another origin cannot read any API response, whatever it sends. And the session cookie belongs to the site's hostname, set when someone signs in there. The front end's own server makes the calls and holds the credential; the visitor's browser talks only to that server.

A member's sign-in is not an API credential

Site members (the visitors who sign in on the site, as opposed to the backend users who work in the admin) reach only the routes a visitor needs: the cart, checkout, payment methods, form submission, sign-in, registration and password reset. Everything else answers a member as if it did not exist, with a 404 on a default site, and an OAuth token issued to a member meets the same refusal. Design a headless member area around those routes, with the front end's server reading anything else on the member's behalf. Guide 7 covers member accounts.

No CSRF token on server calls

A request that carries an Authorization header is never checked for a CSRF token. The check applies only to writes made with a signed-in session cookie, which is the hybrid case (Carrying the CSRF token).