Customer Authentication
Configure customer authentication — SMS code, email/password, Apple, Google, and Facebook sign-in. The full registration, verification, and login flow with API examples, and the limits on endpoints that send a text.
Customer Authentication
Storefront provides a complete authentication system for your customers. On successful authentication, the API returns a Sanctum personal access token. Your customer-facing app stores this token and includes it on every authenticated request via the Customer-Token header (the storefront key still goes in Authorization: Bearer).

GET /storefront/v1/customers/me
Authorization: Bearer store_your_store_key
Customer-Token: 1|VlKK7lZ...Authentication Methods
SMS Code (default)
The most common method for on-demand delivery apps. No password required — a one-time code is sent to the customer's phone.
Email / Phone + Password
Traditional credentials login. The login endpoint accepts an identity field that can be either an email or a phone number, plus a password.
Social Sign-In
Storefront supports:
- Apple Sign-In — required by Apple for iOS apps that offer other social logins
- Google Sign-In
- Facebook Sign-In
Each social provider has its own login endpoint and required parameters — see Social Login below.
Registration Flow
Registration is a two-step flow. The customer first requests a verification code, then submits their details along with the code.
1. Request a verification code
POST /storefront/v1/customers/request-creation-code
Authorization: Bearer store_your_store_key
{
"mode": "sms",
"identity": "+15551234567"
}mode is sms or email (the default is email); identity is the phone number or email address the code goes to. The code expires after ten minutes and can be used once.
The request is refused with 422 when an account already exists for the identity (the response says so; send the customer to sign in instead) or when the phone number is invalid or cannot receive a text message. Asking again for the same identity inside a minute answers ok without sending a second message, so a retry button is safe to offer.
2. Create the customer
POST /storefront/v1/customers
Authorization: Bearer store_your_store_key
{
"name": "Jane Doe",
"email": "customer@example.com",
"phone": "+15551234567",
"password": "securepassword",
"code": "123456"
}Phone numbers must include the international prefix (e.g. +1, +44). The API normalizes the value and prepends + automatically if missing.
A wrong code counts against the one that was sent; after five wrong guesses the code locks and a new one must be requested. After ten wrong codes for the same identity, whatever the address they came from, the identity is locked out of code checks for fifteen minutes and the endpoint answers 429.
Login
SMS Code Login
POST /storefront/v1/customers/login-with-sms
Authorization: Bearer store_your_store_key
{
"phone": "+15551234567"
}Verify the code that was sent:
POST /storefront/v1/customers/verify-code
Authorization: Bearer store_your_store_key
{
"identity": "+15551234567",
"code": "123456"
}The login response carries "method": "sms". When the text cannot be sent (the store has no SMS provider configured, or the SMS Guard refused it) and the customer has an email address on file, the code is emailed instead and the response carries "method": "email". Verify it with the same verify-code call.
Email / Phone + Password Login
POST /storefront/v1/customers/login
Authorization: Bearer store_your_store_key
{
"identity": "customer@example.com",
"password": "securepassword"
}The identity field can be either an email address or a phone number.
Limits on endpoints that send a text
Every endpoint that sends an SMS (request-creation-code, login-with-sms, request-phone-verification, account-closure) is limited to 5 requests a minute per storefront key and client address, on top of the general storefront throttle, and every message passes the platform's SMS Guard. Handle these statuses in your app:
| Status | Meaning | What to do |
|---|---|---|
422 | The number is invalid or cannot receive a text, or an account already exists for the identity. | Show the message; do not retry. |
429 | Too many requests, a cooldown on that number, or the store's message budget. | Wait for the Retry-After header before retrying. |
423 | Text messages are paused for this store. | Offer email login or password login; retry later. |
Response
All login endpoints return the same structure on success:
{
"token": "1|VlKK7lZ...",
"customer": {
"id": "customer_abc123",
"name": "Jane Doe",
"email": "customer@example.com",
"phone": "+15551234567"
}
}Store the token securely (e.g. iOS Keychain, Android Keystore, or expo-secure-store). Pass it on every authenticated request:
Customer-Token: 1|VlKK7lZ...Social Login
Apple
POST /storefront/v1/customers/login-with-apple
Authorization: Bearer store_your_store_key
{
"identityToken": "...",
"authorizationCode": "...",
"appleUserId": "...",
"name": "Jane Doe"
}Apple does not always return name/email — pass them along the first time, since they're omitted on subsequent sign-ins.
POST /storefront/v1/customers/login-with-google
Authorization: Bearer store_your_store_key
{
"idToken": "...",
"clientId": "..."
}POST /storefront/v1/customers/login-with-facebook
Authorization: Bearer store_your_store_key
{
"facebookUserId": "...",
"email": "customer@example.com",
"name": "Jane Doe"
}Phone Verification (post-registration)
To verify a customer's phone after they've signed up (e.g. when they update it):
POST /storefront/v1/customers/request-phone-verification
POST /storefront/v1/customers/verify-phone-numberThe first call takes phone and texts the code to that number. It goes to the new number, not the one on file, so it also works for a customer who has no number yet. It answers 422 when the number is invalid, cannot receive a text, or already belongs to another account. The second call takes the code and only then saves the number on the customer. The code expires after ten minutes and verifies once. This needs fleetbase/core-api 1.6.70 or later; earlier versions texted the number on file.
Account Closure
For App Store and Play Store compliance, expose an in-app account closure flow:
POST /storefront/v1/customers/account-closure
POST /storefront/v1/customers/confirm-account-closureThe first endpoint sends a confirmation code to the customer's phone, or to their email when the text cannot be sent; the second takes the code and closes the account. The code expires after ten minutes and verifies once.
Device Registration (push)
For push notifications to reach the customer, register their device token after authentication:
POST /storefront/v1/customers/register-device
Authorization: Bearer store_your_store_key
Customer-Token: 1|VlKK7lZ...
{
"platform": "ios",
"token": "<APNs or FCM device token>"
}See Notifications for setting up the underlying APNs / FCM channels.
Stripe Helpers
If you use Stripe, two endpoints support saved-card / PaymentSheet flows:
POST /storefront/v1/customers/stripe-ephemeral-key
POST /storefront/v1/customers/stripe-setup-intentRealtime Socket Token
To receive realtime updates for their own orders, a signed-in customer mints a short-lived socket token:
POST /storefront/v1/customers/socket-token
Authorization: Bearer store_your_store_key
Customer-Token: 1|VlKK7lZ...{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_in": 900,
"expires_at": "2026-01-01T12:15:00+00:00"
}Connect to the socket server with socketcluster-client, present the token in the handshake (an in-memory authEngine) or with socket.authenticate(token), and refresh it about 60 seconds before expires_in elapses. The token only allows the customer's own channels — their orders (order.{order id}) and the driver and vehicle serving an active order. Keep it in memory only. Instances without socket authentication answer 404; connect without a token in that case. In @fleetbase/storefront the call is customer.socketToken().
Token Sessions
Tokens issued via these endpoints are Laravel Sanctum personal access tokens. Handle 401 Unauthorized by re-authenticating. Tokens can be revoked server-side by an admin.
If you are using the Storefront App, sign-in is already built in: phone number and texted code, plus Sign in with Apple and Sign in with Google once they are set up. The app doesn't offer Facebook sign-in; the endpoint above remains for your own clients. See Storefront App → Sign-in for the Apple and Google setup.