Skip to content
Elara One docs

Customer accounts

Register and sign in shoppers with bearer tokens, verify email, reset passwords, manage the address book, show order history and delete an account.

Shoppers can create an account with the store to save addresses and see their orders. Accounts belong to one store: the same email can have separate accounts at two stores. The API uses bearer tokens, never cookies, so your storefront server keeps the token and sends it as Authorization: Bearer ….

Endpoints

EndpointDoes
POST /v1/auth/registerCreates an account and returns a token
POST /v1/auth/loginSigns in and returns a token
POST /v1/auth/logoutRevokes the current token
GET /v1/auth/meThe signed-in account
PATCH /v1/auth/meChanges the name or email
POST /v1/auth/verifyConfirms an email address from the verification link
POST /v1/auth/verify/resendSends the verification email again
POST /v1/auth/password/forgotEmails a password reset link
POST /v1/auth/password/resetSets a new password with the token from that link
POST /v1/auth/passwordChanges the password of a signed-in account
GET, POST /v1/account/addressesLists or adds saved addresses
PATCH, DELETE /v1/account/addresses/{id}Changes or deletes a saved address
GET /v1/orders, GET /v1/orders/{reference}Order history
DELETE /v1/accountErases the account

Register and sign in

curl -X POST https://api.elaraone.app/api/v1/auth/register \
  -H "X-Tenant-Key: $ELARAONE_TENANT_KEY" \
  -H "X-Tenant-Secret: $ELARAONE_TENANT_SECRET" \
  -H "X-Cart-Token: $CART_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Katherine Johnson",
    "email": "[email protected]",
    "password": "correct-horse-battery",
    "password_confirmation": "correct-horse-battery"
  }'
Response
{
  "data": {
    "user": {
      "id": 77,
      "name": "Katherine Johnson",
      "email": "[email protected]",
      "email_verified_at": null,
      "customer_id": 204
    },
    "token": "12|q8V…",
    "expires_at": "2026-11-23T10:12:31+00:00"
  }
}
  • Registration returns 201 and login returns 200, both with the same shape.
  • Passwords need at least 8 characters, and password_confirmation must match.
  • Wrong credentials, or an email already registered, return 422 VALIDATION_FAILED with the field in details.
  • The token can be used straight away, before the email is verified. expires_at says when it stops working.
  • Send the guest's X-Cart-Token with login or registration to merge their basket into the customer's cart. An unknown or expired cart token is ignored; it never stops the sign-in.
  • Register, login, password reset, profile changes and password changes share a tight rate limit: 10 a minute per store and IP. See rate limits.

Keep the token on your server

Treat the bearer token like a password. Keep it in an httpOnly, secure cookie on your storefront's domain, and have your server add it to API calls. Never put it in localStorage.

Send the token on every call made for that customer, together with the store key and secret:

curl https://api.elaraone.app/api/v1/auth/me \
  -H "X-Tenant-Key: $ELARAONE_TENANT_KEY" \
  -H "X-Tenant-Secret: $ELARAONE_TENANT_SECRET" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN"

A missing, expired or revoked token returns 401 UNAUTHENTICATED. POST /v1/auth/logout revokes the token it was sent with.

Change the name or email

PATCH /v1/auth/me takes name, email or both. Changing the email also needs current_password.

Verify the email address

When an account is created, the store sends a verification email, if the store has set its storefront's verify-email page in Store settings. The link opens that page on your storefront with a signed query string.

Your page sends that query string to the API exactly as it arrived, as the query string of POST /v1/auth/verify:

On your verify-email page (server-side)
// incomingUrl is the URL the shopper opened, e.g. https://hearthandoak.example/verify?expires=…&hash=…&id=…&signature=…
const query = new URL(incomingUrl).search // keep it byte for byte: same order, same encoding

const res = await fetch(`https://api.elaraone.app/api/v1/auth/verify${query}`, {
  method: 'POST',
  headers: {
    'X-Tenant-Key': process.env.ELARAONE_TENANT_KEY!,
    'X-Tenant-Secret': process.env.ELARAONE_TENANT_SECRET!,
  },
})
// 200 { "data": { "status": "verified" } }, or 403 when the link is invalid or has expired

The signature is checked against the exact query string, so do not re-encode, reorder or add parameters. POST /v1/auth/verify/resend (signed in) sends a fresh link, or answers already-verified.

Reset a forgotten password

  1. POST /v1/auth/password/forgot with { "email": "…" }. It always answers 200 with reset-link-sent, whether or not the address has an account, so it cannot be used to find out who shops at the store.
  2. The store emails a link to the reset page you set in Store settings, with the token and email filled in. The token works once, for 60 minutes. If the store has not set a reset page, no email is sent.
  3. Your reset page sends POST /v1/auth/password/reset with token, email, password and password_confirmation. A bad or expired token returns 422 VALIDATION_FAILED on token.

Change the password

POST /v1/auth/password (signed in) takes current_password, password and password_confirmation. The token that made the request keeps working; every other token on the account is revoked, and revoked_tokens says how many.

The address book

GET /v1/account/addresses
{
  "data": [
    {
      "id": 42,
      "label": "Home",
      "title": null,
      "first_name": "Ada",
      "last_name": "Lovelace",
      "company_name": null,
      "line_one": "221B Baker Street",
      "line_two": null,
      "line_three": null,
      "city": "London",
      "state": null,
      "postcode": "NW1 6XE",
      "country_id": 235,
      "delivery_instructions": null,
      "contact_email": null,
      "contact_phone": "+447700900123",
      "shipping_default": true,
      "billing_default": true
    }
  ]
}
  • GET lists the customer's addresses, newest first.
  • POST creates one (201). first_name, last_name, line_one and city are required.
  • PATCH /v1/account/addresses/{id} changes any field. DELETE removes the address.
  • label is an optional nickname such as "Home" or "Work", up to 50 characters. title is the salutation.
  • Setting shipping_default or billing_default to true moves that default to this address, so only one address holds each. Deleting a default moves it to the newest remaining address.
  • Another customer's address id returns 404 NOT_FOUND.

At checkout, a signed-in customer can use a saved address with address_id, or save a new one with save_to_account. See carts.

Order history

GET /v1/orders lists the signed-in customer's orders, newest first, with page and perPage (1 to 100, default 24). GET /v1/orders/{reference} returns one order in the same shape checkout returns. See checkout.

When a customer verifies their email, orders they placed earlier as a guest with that address become part of their account.

Delete the account

DELETE /v1/account lets a shopper erase their own account. It needs the bearer token and the account password as current_password:

curl -X DELETE "https://api.elaraone.app/api/v1/account?current_password=correct-horse-battery" \
  -H "X-Tenant-Key: $ELARAONE_TENANT_KEY" \
  -H "X-Tenant-Secret: $ELARAONE_TENANT_SECRET" \
  -H "Authorization: Bearer $CUSTOMER_TOKEN"

On success it answers { "data": { "status": "erased" } }, and:

  • the account can never sign in again, and every token on it is revoked, including the one that made the request;
  • saved addresses and open carts are deleted;
  • orders are kept as the store's records, with names, street, email and phone removed;
  • guest orders, carts and form submissions made with the account's verified email are anonymised the same way;
  • the verified email and phone numbers are kept only as one-way hashes on the store's do-not-contact list, so automated messages never reach them again.

A missing or wrong password returns 422 VALIDATION_FAILED. 409 ACCOUNT_SHARED means the account shares its customer record with other accounts (the store linked them), so only the store can erase it; nothing is changed. Deletion is rate limited to 3 a minute and 10 an hour per account, and 20 an hour per IP.