ShopEazydevelopers
Authentication

Shoppers

Sign shoppers in, keep them signed in for 14 days, and read an order back as a guest.

A store key says which store is calling. A shopper credential says which customer. You need one for the operations that touch a customer's own data: their membership, their orders and bookings, applying for membership, and placing an order on a members-only store.

Shoppers sign in with Firebase Auth, in the store's own tenant. ShopEazy verifies the token. You own the sign-in screens.

Three credentials

CredentialHeaderLastsUse it for
Shopper sessionX-Shopper-Session14 daysA server-rendered site. Keep it in your own httpOnly cookie
Shopper tokenX-Shopper-Token1 hourA browser that already has the Firebase client SDK open
Order tokenX-Order-Token30 daysA guest reading back one order they placed

Send a shopper session or a shopper token together with the store key. If you send both shopper credentials, the session is checked first.

Sign a shopper in

The store tells you which Firebase tenant its shoppers live in. Read it from GET /v1/store:

{ "data": { "auth": { "tenantId": "<tenant id>" } } }

auth.tenantId is null for a store on the shared pool. It is not a secret.

Set the tenant on the browser's Firebase Auth before you sign the shopper in:

import { getAuth } from 'firebase/auth';

const auth = getAuth();
auth.tenantId = store.auth.tenantId; // before signInWith...

A uid is only unique within one tenant, so a token from the wrong pool is refused. That is isolation working, not a bug.

Create a shopper session

Send a fresh Firebase ID token to ShopEazy. Your key needs the members:write scope.

curl https://api.shopeazy.co/v1/store/shopper/session \
  -H "Authorization: Bearer sez_pub_..." \
  -H "Content-Type: application/json" \
  -d '{ "idToken": "<firebase id token>" }'
{
  "data": {
    "sessionToken": "<session token>",
    "expiresAt": 1793846400000,
    "shopper": {
      "uid": "shopper_123",
      "email": "sipho@example.co.za",
      "name": "Sipho Dlamini",
      "phone": null
    }
  }
}

The answer is 201. The session lasts 14 days. Put sessionToken in your own httpOnly cookie and send it as X-Shopper-Session on later calls. ShopEazy also saves the shopper's profile for the store, so your site does not have to.

The shopper's email must be verified. If it is not, the call is 403 email_unverified.

With the typed client:

import { shopperCookie, readShopperToken } from '@shopeazy/storefront-client/session';

const { sessionToken } = await shopeazy.shopper.createSession(idToken);
headers.set('Set-Cookie', shopperCookie(sessionToken, { maxAgeSeconds: 60 * 60 * 24 * 14 }));

// On a later request:
const token = readShopperToken(request.headers.get('cookie'));
const me = token ? await shopeazy.asShopperSession(token).me() : null;

Use the session

curl https://api.shopeazy.co/v1/store/me \
  -H "Authorization: Bearer sez_pub_..." \
  -H "X-Shopper-Session: <session token>"
{
  "data": {
    "shopper": { "uid": "shopper_123", "email": "sipho@example.co.za", "name": "Sipho Dlamini", "phone": null },
    "membership": null,
    "canCheckout": true
  }
}

You always get the caller's own record. canCheckout is true on an open store, or for an active member of a members-only store.

Sign out

curl -X DELETE https://api.shopeazy.co/v1/store/shopper/session \
  -H "Authorization: Bearer sez_pub_..." \
  -H "X-Shopper-Session: <session token>"

This revokes the shopper's refresh tokens. It is best effort: an already invalid session is not an error. Clear your cookie either way.

Use a shopper token instead

A browser that already holds a Firebase ID token can send it directly as X-Shopper-Token. It lasts one hour, so a server-rendered page goes signed out every hour unless the browser refreshes it. For a server, prefer a session.

const me = await shopeazy.asShopper(idToken).me();

Guests: the order token

A shopper does not have to sign in to buy. POST /v1/store/orders returns an accessToken for that one order. It is valid for 30 days and is bound to that order in that store.

To read the order back, or to confirm payment, send it as X-Order-Token:

curl https://api.shopeazy.co/v1/store/orders/order_789 \
  -H "Authorization: Bearer sez_pub_..." \
  -H "X-Order-Token: <order access token>"

The shopper who placed the order may use their shopper credential instead. If you send neither, the call is 401 order_access_required. A credential for a different order, or an expired token, is 404 not_found: the same answer as an order that does not exist.

Errors

StatusCodeMeaning
401shopper_requiredThe call needs a signed-in shopper and none was sent
401invalid_shopper_tokenThe session or token is not valid or has expired. Sign the shopper in again
401order_access_requiredNo order token or shopper credential was sent for this order
403email_unverifiedThe shopper has not verified their email
403not_a_memberA members-only store, and this shopper is not an active member

Coming soon

Email verification codes, password reset, an address book, a profile update and claiming guest orders for shoppers are coming soon. The API does not offer them yet.

On this page