The API enforces three separate credentials. Which one an endpoint wants is shown in its reference
page under Authorizations.
Bearer tokens
Both token types are JWTs and behave identically apart from which accounts they represent.
When the Authorization header is absent, the API falls back to a cookie — accessToken for staff
and customerAccessToken for customers. That fallback exists for the first-party web apps. A
server-side integration should always send the header.
Revocation
Tokens carry a tokenVersion. Logging out and resetting a password both bump it, which invalidates
every outstanding token for that account at once. Treat a 401 on a previously working token as a
signal to re-authenticate rather than to retry.
Logging in
Use POST /api/v1/auth/refresh-token to exchange a refresh credential for a new access token, and
GET /api/v1/auth/me to read the authenticated profile.
Behaviour worth knowing
POST /auth/logout does not reliably end other sessions. It bumps tokenVersion only when
the request carries a token that still verifies. With an expired access token, or with only the
refresh cookie, the cookies are cleared but other live sessions survive. Do not present this
endpoint as “log out of all devices”.
POST /auth/forgot-password always returns 200, including for an address with no account.
This is deliberate: a 404 would let the endpoint be used to discover which addresses are
registered. Do not branch on 404, and do not report “email sent” as a fact.
- It is rate limited per IP and per email address at 5 per hour, so a user retrying one address
hits
429 sooner than the IP limit alone would suggest.
POST /auth/reset-password revokes every session and does not log the user in. Send them to
the login screen afterwards.
GET /auth/verify-reset-password-token does not consume the token, so a form can safely check
it before collecting the new password.