Client setup
Customer login & tokens
Login (POST /auth/login) returns an access_token (30 minutes) and a refresh_token
(7 days). Send the access token as Authorization: Bearer on account-area calls and renew it
with POST /auth/refresh.
The refresh rotates: every refresh returns a new refresh token and supersedes the one
you presented. Rules for the app:
- Store the new pair on every refresh, in the system’s secure storage: Keychain on iOS,
a value encrypted with an Android Keystore key on Android,
flutter_secure_storagein Flutter. Write both tokens before using the new access token. - One refresh at a time: requests that get a 401 together wait for the same refresh instead of each starting their own.
- Reuse: if the app is killed between the response and the save, on restart it presents the old token. Within 60 seconds the API returns the same current token; later, for a customer account, it still returns the session’s current token. No forced logout, as long as you store what you receive.
- End of session: a 401 from
/auth/refresh(auth.session_revoked,auth.refresh_token_reused,auth.refresh_token_invalid) or a 403auth.tenant_unavailableends the session: clear the tokens and show the login screen. - No network or 5xx: don’t clear anything, try again later.
Flutter
Logout
- Sign out: if you registered the device for notifications, first call
DELETE /devices/{device_id}with the access token (a device linked to the account can only be removed by its owner). ThenPOST /auth/logoutwith{"refresh_token": "..."}in the body closes this device’s session on the server. Finally clear the tokens. - Sign out everywhere:
POST /auth/logout?all=truewith the access token (or the refresh token in the body). From then on every token issued before answers 401auth.session_revoked.
Two-factor authentication (2FA)
If the customer has enabled 2FA, login takes two steps:POST /auth/loginanswers 401auth.totp_required: show the code field.- Repeat the same call with
totp_code. The same field accepts a recovery codexxxxx-xxxxx: offer a “Lost your phone? Use a recovery code” link. Each code is valid only once (401auth.totp_invalidif reused).
POST /auth/2fa/setupwith the current password returnssecretandqr_uri; on mobile, also offer a button that opensqr_uriin the authenticator app.POST /auth/2fa/verifywithcodeandcurrent_passwordenables 2FA and answers with new tokens (the other sessions are closed: store them) and with 10recovery_codes. Show them only once, with “Copy” and “Share”, and ask the customer to confirm they saved them.GET /auth/meexposesrecovery_codes_remaining: when it gets close to 0, offer to regenerate them withPOST /auth/2fa/recovery-codes(the current password is required).POST /auth/2fa/disableaccepts the app code or a recovery code and also returns new tokens to store.
POST /users/me/change-password doesn’t close sessions unless the app sends the
X-Session-Rotation: 1 header: in that case the response carries new tokens, to store right
away in place of the old ones.Push notifications
Register the customer’s device token for transactional notifications (order shipped, etc.) through the Storefront API’s device-push endpoints — see the API Reference.Images and payments work the same as on the web: image URLs must be prefixed with the
origin, and the payment flow returned by
POST /checkout must be completed with the
gateway’s native SDK (Stripe/PayPal/…) when required. Prices and totals arrive as decimal
strings: see Build a storefront.