Skip to main content
Sign in with your store to see only the help that applies to you.

Developer API Overview

Admin

The Brother POS Developer API lets external systems read and write data from your store using simple REST endpoints. Use it to build custom dashboards, sync inventory with other platforms, automate loyalty workflows, or receive event notifications via webhooks.


What You Can Do​

CapabilityDescription
Read productsFetch your catalog with prices, stock levels, categories, and images
Read customersAccess customer profiles, loyalty points, and visit counts
Read salesPull transactions with line items and the payment method
Read inventoryCheck stock levels, and read back the full stock adjustment ledger
Read purchasingPull purchase orders and receiving — what was ordered, invoiced, and what actually arrived
Read costLanded cost, average cost and wholesale price, behind their own scope
Write customersCreate and update customer records from external systems
Write productsCreate products, bulk upsert a catalogue by SKU, bulk-update prices and stock
Adjust inventoryPush stock corrections from warehouse or external systems
Receive webhooksGet notified when sales change status, products or customers change, inventory moves, or a delivery is received

How It Works​

  1. Create an API key from Settings → Developer API (the button is shown to admins once the Developer API is enabled for your store).
  2. Send requests to /api/v1/* endpoints with your key in the X-API-Key header.
  3. Receive JSON responses wrapped in a standard envelope with pagination and metadata.
  4. Subscribe to webhooks to get push notifications instead of polling.
Quick test
curl -H "X-API-Key: bpos_your_key_here" \
https://yourstore.brotherpos.ca/api/v1/products

Base URL​

All API requests go to your store's subdomain:

https://{your-store}.brotherpos.ca/api/v1/

The store is determined by the API key, not the subdomain.


Response Format​

Successful (2xx) JSON responses to API-key requests are wrapped in a standard envelope:

{
"data": [ ... ],
"pagination": {
"current_page": 1,
"per_page": 25,
"total_count": 142,
"total_pages": 6
},
"meta": {
"request_id": "a1b2c3d4-...",
"timestamp": "2026-03-22T12:00:00Z"
}
}

How data is built:

  • If the endpoint's response has a single top-level key (for example products or customer), data is that key's value — an array for lists, an object for a single resource.
  • If the response has several top-level keys, data is the whole object (for example GET /api/v1/webhook_subscriptions/:id returns data.webhook_subscription and data.recent_deliveries).
  • pagination is present only on paginated endpoints.

Error responses (4xx/5xx) are not wrapped — see Error Handling.


Rate Limits​

Each API key has a rate limit in requests per minute (default: 60), counted in fixed one-minute windows. The key's own limit takes effect once it has completed a request within the last five minutes; before that, the default of 60 applies.

When the limit is exceeded, the API returns 429 Too Many Requests with these headers:

HeaderValue
X-RateLimit-LimitRequests allowed per minute
X-RateLimit-RemainingAlways 0 on a 429
X-RateLimit-ResetWhen the current window ends, as a Unix timestamp in seconds (e.g. 1774180860)
Retry-AfterSeconds left until the current window ends

Rate-limit headers are only sent on 429 responses.


Do not choose between webhooks and polling — run both. They fail in different ways, and together they cover each other.

1. Webhooks for latency​

Subscribe to the events you care about so your system reacts soon after something happens in the store, instead of waiting for the next poll. See Webhooks.

Webhook delivery can repeat. A retried delivery carries the same id / X-BrotherPOS-Delivery value as the first attempt, so record the IDs you have processed and skip repeats. Upserting the record by resource_id keeps your handler safe even if a duplicate slips through.

2. A scheduled reconciliation pull for correctness​

Webhooks can be missed. Several event types do not fire in every case you might expect (see Available Events), and after 5 failed deliveries (each one having used up its retries) the subscription is automatically disabled — at which point you stop receiving events entirely and, without a second channel, silently drift out of sync.

So run a scheduled pull as well — hourly or nightly is usually enough — using the incremental cursors:

# Store the timestamp you last completed a successful pull, then:
curl -H "X-API-Key: bpos_..." \
"https://yourstore.brotherpos.ca/api/v1/products?updated_since=2026-08-19T02:00:00Z&per_page=100"

Endpoints supporting an incremental cursor:

EndpointCursor parameterInvalid value
GET /api/v1/productsupdated_sinceSilently ignored (returns unfiltered results)
GET /api/v1/customersupdated_sinceSilently ignored (returns unfiltered results)
GET /api/v1/purchase_ordersupdated_since422 Unprocessable Entity
GET /api/v1/stock_adjustmentssince and until (on creation time)422 Unprocessable Entity
Overlap your cursor

Set your cursor slightly behind the last run — for example, last run minus five minutes — rather than exactly at it. Records written while the previous pull was in flight are otherwise easy to skip. Because your write path is already idempotent for webhooks, reprocessing the overlap costs nothing.

3. Reconcile, do not just re-import​

The pull's job is to correct the webhook stream, so treat it as a comparison: for each changed record, upsert on your side and log where your stored copy disagreed with the API. Persistent disagreement is your signal that a subscription got disabled or a handler is dropping events.


What's Next?​