Skip to content

Batch Commerce API ​

The Batch Commerce API is the customer-facing API of the Batch customer backend: the calls a storefront website makes on a shopper's behalf. These pages explain it by feature: sign-up and login, loyalty, shopping, payments, collectibles, content, and supporting services. Each operation lists its exact URLs, access requirements, request fields, an example, and response behavior. Examples use the first URL when several are listed; replace IDs and angle-bracket values with real data.

Every endpoint listed here takes the brand key. The same backend also serves the mobile app — documented separately in the Mobile API — and the Shopify plugin; those mounts, and routes with no brand-key check (provider webhooks, internal and event routes), are not listed. Six routes without a brand-key check stay because the web flows need them; each is marked No brand key on this route.

Prepared from the customer backend (batchsys-customer-backend) on 22 October 2026. This is a source-based reference; examples use fictional values and have not been sent to a running server. Database records, enabled integrations, and upstream services determine the available data. No production hostname is assumed.

Start here ​

  1. Obtain the server URL and credentials for your environment from the backend team. The local server listens on PORT, defaulting to 3000.
  2. For a website, call POST /api/v1/tenant with its registered Origin to load tenant details. A tenant is the brand/site context for the request. The returned site configuration includes the brand API key. A hub is a shop or fulfillment location; select it with PUT /api/v1/set-hub when needed, and use the returned result.apiKey for hub-specific calls.
  3. Register or sign in using the sign-up and login section. Save result.token from a successful login and send it as Authorization: Bearer <CUSTOMER_TOKEN> on customer-protected routes.
  4. Find the feature in the feature index and send the headers shown in its row. Prefix the path with your server URL.
  5. Check both the HTTP status and the JSON body. Many application errors return HTTP 200 with success: false.
bash
export BASE_URL='http://localhost:3000'
export ORIGIN='your-registered-site.example'
export API_KEY='<BRAND_OR_SELECTED_HUB_API_KEY>'
export CUSTOMER_TOKEN='<TOKEN_RETURNED_BY_LOGIN>'

Use the origin registered for your site. The server normalizes Origin to its hostname plus optional port before validating the website API key; a browser can send a full origin such as https://your-registered-site.example. For local scripts, the hostname form above is also accepted by that middleware.

How to read request fields ​

TermMeaning
PathPart of the URL. Replace :productId with an actual product ID, for example 123.
QueryAdded after ?, for example ?limit=10&offset=0. URL-encode text and special characters.
BodyJSON sent with Content-Type: application/json. Most routes expect { "payload": { ... } }; exceptions are listed.
body.payload.items[].idThe id property on each object in the items array inside payload.
Required: yesSupply this field whenever its containing object/array is supplied. An optional parent does not become required because one of its children is required.
Required: conditionalA rule depends on another field or server context. Read the rule and operation notes.
OptionalThe controller's Joi schema permits omission. Business logic can still require related data.
No controller schemaThe field is read by the handler but is not type-validated there. Its upstream or database contract still applies.

Fields and constraints below come from the controllers that actually execute. Files under app/*/validator mainly describe Swagger requests; the route engine does not run those files as validation middleware. Unknown keys are generally rejected by Joi object schemas unless .unknown(true) is used. Do not send fields from another operation's schema.

Headers and access ​

The endpoint tables use the following labels. Combine all labels in a row; for example, Origin + Brand key + Customer means all three are needed. JSON requests also need Content-Type: application/json. The labels describe the registered middleware, regardless of words such as user, brand, or open in a URL.

LabelWhat to send / what it checks
OriginOrigin: <REGISTERED_SITE_ORIGIN>. Applied automatically to route-file endpoints unless they declare noCorsMiddleware or isInternal. The site must be on the server's whitelist.
Brand keyapi-key: <BRAND_API_KEY>. The key's origin must match the normalized request origin; identifies the brand and organization.
Hub selectedUse the API key returned by hub selection. validHubApiKey checks that the existing tenant contains hubId; it does not read another header.
CustomerAuthorization: Bearer <CUSTOMER_TOKEN>. Validates the customer JWT and loads customer context.

Combinations seen on this site: Origin + Brand key, Origin + Brand key + Customer, the same two with Hub selected, and on the six flow routes Origin or Origin + Customer alone.

Responses, errors, and limits ​

Most v1 handlers return:

json
{
  "success": true,
  "result": { "message": "Operation completed" }
}

result can be an object, array, scalar, or data from another service. Example response values in this guide illustrate the shape; they are not captured responses. Fields listed for a result are selected implementation details, not a promise that every response has the same fields.

The shared error handler usually returns HTTP 200:

json
{ "success": false, "error": "The reason the request failed" }

Some early validation branches instead use status: false, message, or an error object such as { "message": "payload is required", "error": "Bad Request" }. Cloudinary uploads use status: true on success. Loyalty v2, mini-games v2, and several NFT endpoints forward another service's JSON directly. Do not add an assumed extra result wrapper.

HTTP statusMeaning in this repository
200Successful calls and many validation/business failures; inspect the body.
400Some missing or invalid context, such as an unselected hub.
401Authentication middleware rejected a credential.
403Missing, unrecognized, or blocked origin: { "error": "Blocked by CORS" }.
409Wallet ownership conflict; includes extra result data for the account-switch flow.
413A file exceeds the upload limit.
429Global rate limit exceeded.

The global limit defaults to 15 requests per second per rate-limit key (IP by default), configurable with REQUEST_PER_SECOND. Rate-limit headers are enabled. File uploads use multipart form data with a 10 MiB limit per file. Use curl -F; let curl set the multipart boundary.

Pagination is operation-specific. limit generally controls page size and offset skips records; only use them where listed. Some controllers add pagination only when both values are truthy, so offset=0 may be ignored. Shopify order history uses limit and an opaque cursor instead. Array query values often use comma-separated strings; the operation notes identify conversions.

Common flows ​

The storefront's main journeys are playable step by step, each with a state diagram, on the web flows pages:

JourneyWeb flow
Every way in, and every way outAuthentication states
Register, then verify by OTPSign up
Password, OTP, magic link or GoogleLog in
Recovery link, then a new passwordReset a password
Tenant, hub, catalogue, bag, order, paymentShop to order
Verify a code, then claim or hold its rewardScan to claim
Campaign progress, claim, spend at checkoutEarn and spend
Request, approve and transfer a scanned productOwnership transfer

Two shorter sequences have no flow page:

  • Wallet switching: linking a wallet can return 409; send the wallet-switch OTP and verify it. Verification returns a customer token for the account that owns the wallet; use that token for subsequent requests. See Wallet linking.
  • Mini-games: create a session using mini_game_id, submit a score using the returned session_id, then convert that session's score. Consuming points for lives is a separate operation. See Mini-games.

In the backend, the server entry is app.ts, the route loader engine/engineHelper.js, prefix configuration configServer.ts, the error handler app/v1/helpers/errorReporter.js, and the Swagger generator app/v1/helpers/generateSwaggerPathHelper.js. The running server exposes Swagger at /doc after initialization; these pages note the places where behavior differs from it.

Try the API from these pages ​

Every endpoint on these pages ends in a Try it bar. Open it for an editable request, copyable cURL / JavaScript / Python / Swift / Kotlin snippets, and a Send button that renders the response in place. The values below are shared with every console on the site and kept in this browser only. Use test-environment keys and 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 only the headers its access label calls for. Origin is the exception: browsers do not let a page set it, so a live call goes out with the docs site's own origin and the server's whitelist rejects it with 403. Either copy the cURL snippet, or run the docs with BATCH_API_ORIGIN=<host> npm run dev and tick the proxy option; the dev proxy then replaces Origin with the site origin entered above.

Feature index ​

Pages are grouped by what an endpoint does, matching the sidebar. Each operation is documented on exactly one page; where a route is served by a controller from another area — trending collectibles from the campaign controller — it is filed with the feature it returns, not the controller that serves it.

GroupSectionDistinct endpointsOperations
Accounts & identitySign-up and login1010
Customer profiles and accounts1414
Government ID and age verification88
Notifications and preferences33
Wallet linking55
Catalogue & storesSites, shops, and locations88
Products, catalogues, and search2623
Batches and master data11
Cart, orders & paymentsCart and wishlist87
Discounts and coupons97
Orders and checkout99
Payments and gateways1111
Shopify rewards and gift cards55
Loyalty programmeLoyalty points, levels, and rewards1817
Loyalty campaigns1111
Referrals33
Mini-games77
Authenticity & collectiblesProduct scanning and authenticity98
Receipts33
Collectibles55
Product ownership44
NFTs and reward fulfillment1010
Content & engagementBanners and magazines44
Reviews and ratings1615
Forms and events85
Newsletters22
Platform servicesUploads and analytics53

The section pages cover 222 endpoints in 208 controller operations.

Duplicate registrations, commented-out routes and other implementation gaps are on Implementation notes.

Batch platform, Shopify app and API documentation