Custom Storefronts

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.

StatusMeaning
400store is empty, or email is not a valid email address
404The store is unknown, or the credentials are not for this store
409A customer with this email already exists for this store. Send the customer to sign-in.
429Too 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, email and otp are mandatory.
  • Do not send a password field. The API rejects it with 400.
  • If companyName is empty, the organisation name becomes "<firstName> <lastName>".
  • The default language is EN. The default notificationPreference is EMAIL.

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

StatusMeaning
400A password field was sent
401The code is incorrect or expired
404The store is unknown, or the credentials are not for this store
409A 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.
429Too 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:

resultMeaning
["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
StatusMeaning
400username or storeName is empty
404No account found. Offer sign-up.
429Too 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.

StatusMeaning
429Too 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.

StatusMeaning
400No factor was sent, or the account needs two factors and one is missing
401Incorrect credentials, or an incorrect, expired, or used code
429Too 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:

  1. Call POST /customer/otp/send.
  2. Call POST /customer/sign-in with the otp only.
  3. 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/json

Call it from your server. Browsers cannot call the Auth API.

{
  "newLoginMethod": "PASSWORD",
  "newPassword": "a-new-password",
  "passwordGuess": "the-current-password",
  "otpGuess": null
}
FieldMeaning
newLoginMethodPASSWORD, OTP, or OTP_AND_PASSWORD
newPasswordMandatory for PASSWORD and OTP_AND_PASSWORD. Minimum 8 characters.
passwordGuessThe current password
otpGuessA 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 }.

StatusMeaning
400No proof was sent, the new password is too short, or the method is not supported
401The token is missing, invalid, or a guest token; or the password or code is incorrect
429Too many attempts

Last updated on

On this page