Sign-up and sign-in
Create customer accounts with an email code, sign customers in, and let them reset or change their login method
You build the sign-up and sign-in screens. Your server calls the Auth API with the storefront credentials. Refer to Call conventions.
Sign-up
Sign-up uses a one-time code sent by email. The customer does not set a password during sign-up. The customer can add a password later. Refer to Change the login method.
Step 1: send the code
POST /customer/signup/otp/send
{ "store": "your-store-name", "email": "jane@example.com", "requestedLocale": "en" }requestedLocale is optional. It sets the language of the email.
Response 200: { "sent": true }. The customer receives a 7-digit code. The code is valid for 5 minutes. A new code replaces the old code.
| Status | Meaning |
|---|---|
400 | store is empty, or email is not a valid email address |
404 | The store is unknown, or the credentials are not for this store |
409 | A customer with this email already exists for this store. Send the customer to sign-in. |
429 | Too many codes requested |
Step 2: create the account
POST /customer/sign-up
{
"store": "your-store-name",
"email": "jane@example.com",
"otp": "1234567",
"firstName": "Jane",
"lastName": "Doe",
"companyName": "Example Ltd",
"language": "EN",
"notificationPreference": "EMAIL"
}- Only
store,emailandotpare mandatory. - Do not send a
passwordfield. The API rejects it with400. - If
companyNameis empty, the organisation name becomes"<firstName> <lastName>". - The default
languageisEN. The defaultnotificationPreferenceisEMAIL.
Response: customer approved
The customer is now signed in.
{
"approved": true,
"scope": "CUSTOMER",
"access_token": "<JWT>",
"refresh_token": "",
"token_type": "Bearer",
"expires_in": 32400
}Response: approval necessary
Your store requires approval of new customers.
{ "approved": false, "result": ["WAIT_FOR_APPROVAL"] }The account exists, but there is no token. Show a "wait for approval" message.
Errors
| Status | Meaning |
|---|---|
400 | A password field was sent |
401 | The code is incorrect or expired |
404 | The store is unknown, or the credentials are not for this store |
409 | A customer with this email already exists |
409 with "code": "CUSTOMER_ORGANISATION_DUPLICATE_NAME" | An organisation with this name already exists. The code is used up. Ask for a different company name and send a new code. |
429 | Too many attempts. Request a new code. |
After sign-up
If the visitor had a guest session, claim the guest cart. Refer to Claim the guest cart.
Sign-in
Sign-in has three steps. The first step tells you which factors the customer must give.
Step 1: find the factors
POST /customer/login/pre-auth
{ "username": "jane@example.com", "storeName": "your-store-name" }The field names are username and storeName on this endpoint only. All other endpoints use email and store.
Response 200:
result | Meaning |
|---|---|
["OTP"] | Sign in with a one-time code |
["PASSWORD"] | Sign in with a password |
["PASSWORD", "OTP"] | Both a password and a one-time code are necessary |
| Status | Meaning |
|---|---|
400 | username or storeName is empty |
404 | No account found. Offer sign-up. |
429 | Too many requests |
This call does not tell you if the customer is approved.
Step 2: send a code (if necessary)
POST /customer/otp/send
{ "store": "your-store-name", "email": "jane@example.com" }Response: always 200 { "sent": true }, also when the customer does not exist. The code has 7 digits, is valid for 5 minutes, and works one time.
| Status | Meaning |
|---|---|
429 | Too many codes requested |
Step 3: sign in
POST /customer/sign-in
{ "store": "your-store-name", "email": "jane@example.com", "password": "…", "otp": "1234567" }Send password, otp, or the two together, as the pre-auth result tells you.
Response 200: a token response with "scope": "CUSTOMER", or { "result": ["WAIT_FOR_APPROVAL"] } if the customer is not approved yet.
| Status | Meaning |
|---|---|
400 | No factor was sent, or the account needs two factors and one is missing |
401 | Incorrect credentials, or an incorrect, expired, or used code |
429 | Too many attempts |
If the visitor had a guest session, claim the guest cart next. Refer to Claim the guest cart.
Forgotten password
There is no separate "forgot password" endpoint. Use a one-time code:
- Call
POST /customer/otp/send. - Call
POST /customer/sign-inwith theotponly. - Optional: let the customer set a new password with
PATCH /customer/login/reset. This step needs a second, new code.
This procedure does not apply to accounts that require a password and a code.
Change the login method
PATCH /customer/login/reset
A signed-in customer uses this call to set a password, to change a password, or to remove a password.
This endpoint uses the customer access token, not the storefront credentials:
Authorization: Bearer <customer access token>
Content-Type: application/jsonCall it from your server. Browsers cannot call the Auth API.
{
"newLoginMethod": "PASSWORD",
"newPassword": "a-new-password",
"passwordGuess": "the-current-password",
"otpGuess": null
}| Field | Meaning |
|---|---|
newLoginMethod | PASSWORD, OTP, or OTP_AND_PASSWORD |
newPassword | Mandatory for PASSWORD and OTP_AND_PASSWORD. Minimum 8 characters. |
passwordGuess | The current password |
otpGuess | A new code from POST /customer/otp/send |
The customer must prove identity again with passwordGuess or otpGuess. The access token alone is not sufficient.
Response 200: { "status": true }.
| Status | Meaning |
|---|---|
400 | No proof was sent, the new password is too short, or the method is not supported |
401 | The token is missing, invalid, or a guest token; or the password or code is incorrect |
429 | Too many attempts |
Last updated on