Skip to content

Mobile API overview ​

The mobile APIs are the routes the Batch mobile apps call — every route in the customer backend whose endPoint contains mobile/: 166 unique method + path pairs across 150 handlers. The web storefront calls the non-mobile twins of most of them.

Routes are declared in routes/v1/ and routes/v2/ of the customer backend and mounted at boot by engine/engineHelper.js; the prefixes come from routePrefixV1 in configServer.ts. Several handlers are mounted at both a guest and an authenticated path — see Duplicates, aliases and quirks.

Base URL & prefixes ​

routePrefix keyPrefix
openRoute/api/v1
userRoute/api/v1/user
brandRoute/api/v1/brand
brandRouteV2/api/v2/brand

/api/v2/ is not a second, different API. It marks the routes the customer backend serves by calling out to a standalone service — the content service behind CMS content, the points ledger behind points and mini-games. The request and response conventions below apply to them too, with one exception noted there: a proxied body comes back unenveloped.

The prefix is not an auth boundary on mobile routes — auth is decided purely by the middleware list. /api/v1/mobile/..., /api/v1/user/mobile/... and /api/v1/brand/mobile/... all exist, and some authenticated endpoints live under /api/v1/mobile/. Always use the exact path given on the endpoint pages.

Headers ​

HeaderWhenValue
x-auth-tokenEvery mobile routeBearer <brand mobile key JWT>
authorizationRoutes marked CustomerBearer <customer JWT>
Content-TypeRequests with a JSON bodyapplication/json
  • x-auth-token is verified by isValidMobileKey against BRAND_MOBILE_KEY. The JWT payload must contain both brandId and hubId or the request is rejected with 401. The middleware then loads the brand and puts { brandId, hubId, org_id, type, loyaltyBrandId, isMobileSource: true } on req.tenant.
  • authorization is verified by isCustomer against JSON_CUSTOMER, and puts { userId, level_id, ... } on req.meta.
  • Mobile routes use noCorsMiddleware — no origin header is required (unlike the web routes). Docstrings in the source that say "requires api-key and origin" are copy-paste leftovers from the web route; ignore them.
  • brandId and hubId always come from the token, never from the client — except where a hubId/roomId query param is explicitly listed on an endpoint page as an override.

Request body shape ​

Almost every POST/PUT wraps its body in a payload key:

json
{ "payload": { "field": "value" } }

If payload is missing, most handlers return { success: false, error: { message: "payload is required" } }.

Exactly three endpoints take an unwrapped body: loyalty/milestone/redeem (sends collectibles), campaigns/almost-completed (sends event_item) and user/mobile/preference (sends a bare array). Everything else wraps — including trade replies and every /api/v2/ route, mini-games included.

Response shape ​

Success:

json
{ "success": true, "result": { } }

Failure (see handleCatch):

json
{ "success": false, "error": "email must be a valid email" }

⚠️ handleCatch defaults to HTTP 200. A failed request usually still returns 200 OK with success: false. Clients must branch on the success field, not the status code. Exceptions: auth middleware returns 401, and GET /api/v2/brand/mobile/cms returns 404 when the brand has no published content.

Joi validation failures surface as the first failing message only, with error: "INVALID PAYLOAD: Check Payload Arguments" in some paths.

Conventions used in these tables ​

  • req — ✅ required, — optional.
  • Comma-separated query params (tags, category, group_by, sortItem, sortType) are split on , server-side; send a,b,c.
  • limit/offset are offset pagination. Where both must be supplied together it is noted (.and("limit","offset")).
  • Unknown keys are rejected by Joi (.keys() is strict by default) — don't send extra fields.
  • Phone numbers: phoneNumber is stripped to digits server-side, and phone_prefix becomes required whenever phoneNumber is present.
  • Emails containing + are rejected on all customer-identity endpoints.

Try an endpoint from the docs ​

Every endpoint on these pages carries a console: a collapsed bar under the endpoint's description that opens into a request editor, five copy-ready code snippets (cURL, JavaScript, Python, Swift, Kotlin) and a Send button whose response renders in the same block.

Fill the two tokens in once below and every console on every page picks them up — they are stored in this browser's localStorage and are never sent anywhere but the host you set. Use test-account tokens.

API console settings
Extra headers
Use this when the browser blocks the call with a CORS error. npm run dev proxies /__api/* to BATCH_API_ORIGIN. Copied code snippets always keep the real host.

Each console sends x-auth-token on every request, adds authorization on the endpoints marked Customer, and shows the exact header list before you send. Path parameters, query parameters and the JSON body are editable, and the code snippets regenerate from whatever is in the editor.

The browser may block the call

A Send from this page is a cross-origin request, so it only completes if the customer backend returns CORS headers to the docs origin. If it fails with "Request failed", the call was blocked before the server answered — copy the cURL tab and run it from a terminal, or run the docs locally with a relay:

bash
BATCH_API_ORIGIN=https://your-customer-backend npm run dev

then tick send through a local proxy path in the settings above. The dev server relays /__api/* server-side, where CORS does not apply. A built static site has no relay.

Endpoint reference ​

PageCovers
Auth, account and addressesregister, login, OTP, OAuth, password reset, profile, merge, deactivate, addresses
Product authenticationauthcode/NFC verify, claim points and collectibles, hold/release, OCR
Loyalty and campaignspoints, transactions, scans, referrals, the points ledger service, campaigns and progress, mini-games
Collectibles, trades and ownershipowned and catalogue collectibles, leaderboards, trades, product ownership transfer
Catalog, search and productstag/related/filter catalogues, Typesense search, product and strain lookup, master data
Cart, discounts, orders and paymentsbag sync, discounts, guest and customer orders, order history, payment gateways
Reviews, wishlist and receiptsproduct reviews (two systems), wishlist, receipt upload and status counts
Content, forms and contactCMS content, blogs, events and leads, forms, store locator, contact-us, newsletter
Gift cards, notifications and uploadsShopify gift cards, Tremendous rewards, push tokens, consent flags, notifications, image upload
Enum referenceevery accepted enum value, and whether to send the key or the value
Duplicates, aliases and quirksshared handlers, duplicate declarations, route-ordering hazards, gotchas

Legend for the Auth column used throughout: Brand = x-auth-token only · Customer = x-auth-token + authorization.

Batch platform, Shopify app and API documentation