# API reference, version 2026-10

Read a merchant's loyalty programme — stores, members, the ledger, reports, usage and the audit log — and change a member's points or cancel a reward code.

Every call goes to this base address:

```text
https://app.matrixrewards.co.uk/api/2026-10
```

The whole API is one [OpenAPI 3.1.0 file, version 2026-10](https://app.matrixrewards.co.uk/api/openapi/2026-10.json), at `https://app.matrixrewards.co.uk/api/openapi/2026-10.json`. These pages are made from it. The newest version's file is also served at `/api/openapi/latest.json`.

## Versions

The version is the first part of every address after `/api`. A call to a version this platform does not serve is answered with [unsupported_version](https://matrixrewards.co.uk/docs/errors/unsupported_version.md), which lists the versions that are. [Every version served](https://matrixrewards.co.uk/docs/api.md).

## About this version

The account-scoped API behind Matrix Rewards. Every call is authenticated by an account API key (`mrk_live_...`), and the key alone decides whose data is served: no path, query or header names an account. The first writes are here — changing a member's points and cancelling a reward code — and so are webhooks: an https endpoint the merchant registers is sent every points movement, signed the Standard Webhooks way. The CLI follows. A points change and a code cancel each take an `Idempotency-Key` and can be previewed with `?dry_run=true`, and every write is written to the account's audit log before it is answered; a key the merchant tagged for an AI assistant must preview a change and send back that preview's confirmation before anything changes.

Conventions: `snake_case` fields; lists are `{data, has_more, next_cursor}` with opaque keyset cursors; failures are RFC 9457 `application/problem+json` carrying a machine-readable `code` and the `request_id` also returned in the `Request-Id` header. The programme documents (`config`, `effective`, `appearance`) and the settlement report keep the engine's own field names, because they are the same documents the app writes and the write API will accept back.

Every read that carries shopper data is written to the account's audit log before it is returned, and the call fails with 503 `access_not_recorded` rather than return data it could not record.

No answer carries a whole reward code. An unused code is a live discount, and API answers end up in logs, scripts and assistant transcripts, so a code is named by its last four characters (`code_ending`, null for a code too short to show any of) and by its `ref`, which is what a cancel takes. The shopper holds the code itself.

## Authentication

An account API key, created in the app. Scopes are held by the key, and a key can hold only the scopes listed in `Scope`: the ones some operation here checks, each named in that operation's `security`. `write_members` also covers `read_members`: a key that may change members' points may read them. A scope a key was given that is not on that list grants nothing, not even a read it might seem to cover, and is left out of what `/me` and `/keys` report. A key made for an AI assistant can never hold `write_webhooks`.

A key looks like `mrk_live_<key id>.<secret><checksum>`. [How to make and send one](https://matrixrewards.co.uk/docs/authentication.md).

## Lists and cursors

- `limit`: 1 to 100. Larger values are capped.
- `cursor`: Opaque. Pass back `next_cursor` from the previous page, with the same filters, and on `GET /members` the same `sort` and `order`.

## Dates and times

Each call that takes a window says how it reads its `from` and `to`:

- [`GET /ledger`](https://matrixrewards.co.uk/docs/api/2026-10/reports.md#listLedger) and [`GET /audit-log`](https://matrixrewards.co.uk/docs/api/2026-10/log.md#listAuditLog): 2026-09-16 or 2026-09-16T10:00:00Z. A date means the whole of that day (a `to` of 2026-09-16 includes 23:59 on the 16th).
- [`GET /reports/settlement`](https://matrixrewards.co.uk/docs/api/2026-10/reports.md#getSettlementReport):
  - `from`: The start of the window: an instant in UTC, written with a `Z` and to at most the millisecond, such as 2026-09-16T10:00:00Z. A date alone, or a finer fraction of a second, is refused with 400 `invalid_request`.
  - `to`: The end of the window, written the same way and later than `from`. The report stops just before it: anything recorded at exactly that instant is left out. A date alone, or a finer fraction of a second, is refused with 400 `invalid_request`.

## Headers {#headers}

The headers the answers carry. Each operation's page says which it sends, and which only when they apply.

| Header | What it is |
| --- | --- |
| `Request-Id` | This request's id, the same as a problem's `request_id`. Quote it if you contact support. |
| `X-RateLimit-Limit` | The bucket's size: how many calls of this kind, reads or writes, this key may make at once. |
| `X-RateLimit-Remaining` | Whole calls of this kind left in the bucket after this one. |
| `X-RateLimit-Reset` | Unix seconds when the bucket is full again. |
| `WWW-Authenticate` | Names the scheme a key is sent with: `Bearer`. |
| `Retry-After` | On a 429: Seconds to wait before sending the request again. On a 409: Only with `idempotency_key_in_use`: seconds to wait before sending the same request again for its answer. |
| `Idempotency-Replayed` | Present, `true`, when this is the stored answer to an earlier request with the same Idempotency-Key. |

## Every operation

### Account

What this key is and what it reaches.

- [`GET /me`](https://matrixrewards.co.uk/docs/api/2026-10/account.md#getMe): The account this key belongs to, its stores, and the key's own scopes
- [`GET /keys`](https://matrixrewards.co.uk/docs/api/2026-10/account.md#listKeys): The API keys on this account
- [`POST /keys/self/revoke`](https://matrixrewards.co.uk/docs/api/2026-10/account.md#revokeThisKey): Stop the key making this request, immediately

### Stores

The stores on the account and their programmes.

- [`GET /stores`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#listStores): Every store on this account
- [`GET /stores/{store_key}`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#getStore): One store
- [`GET /stores/{store_key}/programme`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#getProgramme): A store's programme: what is stored, the settings in force, what shoppers are actually paid, and the expiry rule
- [`POST /stores/{store_key}/programme`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#updateProgramme): Change the earn rate, the bonuses, what a point is worth, referrals, spending any amount, the time zone, the ways to earn, or when points expire
- [`GET /stores/{store_key}/programme/rewards`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#listRewards): The rewards a shopper can spend points on at this store
- [`POST /stores/{store_key}/programme/rewards`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#addReward): Add a reward shoppers can spend points on
- [`POST /stores/{store_key}/programme/rewards/{reward_id}`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#changeReward): Change a reward's cost, value, minimum order or label
- [`POST /stores/{store_key}/programme/rewards/{reward_id}/remove`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#removeReward): Remove a reward
- [`GET /stores/{store_key}/programme/offers`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#listOffers): A store's offers
- [`POST /stores/{store_key}/programme/offers`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#addOffer): Add an offer: a campaign, a product offer or a channel offer
- [`POST /stores/{store_key}/programme/offers/{offer_id}`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#changeOffer): Change an offer
- [`POST /stores/{store_key}/programme/offers/{offer_id}/remove`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#removeOffer): Remove an offer
- [`GET /stores/{store_key}/programme/rules`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#listRules): The earn rules in force at this store
- [`GET /stores/{store_key}/design`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#getDesign): A store's design: the colours, words and look of the rewards panel, the product-page line and the account page
- [`POST /stores/{store_key}/design`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#updateDesign): Change the design: colours, words, the panel and product-line look, the account page layout, the terms link
- [`GET /stores/{store_key}/brand`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#getStoreBranding): A store's name and branding as the Matrix Rewards website shows them, and what Shopify has
- [`GET /stores/{store_key}/images`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#listBrandImages): The pictures uploaded to a store, newest first
- [`POST /stores/{store_key}/images`](https://matrixrewards.co.uk/docs/api/2026-10/stores.md#uploadBrandImage): Upload a picture for the store's branding (a logo, a square logo, a cover)

### Members

Shoppers holding points, and the codes they hold.

- [`GET /members`](https://matrixrewards.co.uk/docs/api/2026-10/members.md#listMembers): Shoppers on this account
- [`GET /members/{member_key}`](https://matrixrewards.co.uk/docs/api/2026-10/members.md#getMember): One shopper's record
- [`GET /members/{member_key}/codes`](https://matrixrewards.co.uk/docs/api/2026-10/members.md#listMemberCodes): The reward codes this shopper holds
- [`POST /members/{member_key}/adjustments`](https://matrixrewards.co.uk/docs/api/2026-10/members.md#adjustMemberPoints): Add points to a member's balance, or take them away
- [`POST /members/{member_key}/codes/void`](https://matrixrewards.co.uk/docs/api/2026-10/members.md#cancelMemberCode): Cancel a reward code and give the member back its points

### Reports

The ledger, liability and settlement.

- [`GET /ledger`](https://matrixrewards.co.uk/docs/api/2026-10/reports.md#listLedger): Every points movement on this account, newest first
- [`GET /reports/liability`](https://matrixrewards.co.uk/docs/api/2026-10/reports.md#getLiabilityReport): What this account owes its shoppers
- [`GET /reports/settlement`](https://matrixrewards.co.uk/docs/api/2026-10/reports.md#getSettlementReport): Points earned at one store and spent at another, inside a window

### Billing

Usage against the plan, and the recorded plan.

- [`GET /usage`](https://matrixrewards.co.uk/docs/api/2026-10/billing.md#getUsage): Orders that earned points this billing month, against the plan's cap
- [`GET /plan`](https://matrixrewards.co.uk/docs/api/2026-10/billing.md#getPlan): The subscriptions recorded for this account

### Log

What every key did, and what it was shown.

- [`GET /audit-log`](https://matrixrewards.co.uk/docs/api/2026-10/log.md#listAuditLog): What every key changed, and what it was shown

### Webhooks

Where every points movement is sent, and a way to check a receiver. Managing webhooks needs `write_webhooks`, and a key for an AI assistant or a test key can never do it: an endpoint is a standing channel out of the account. Each event is POSTed as JSON to every enabled endpoint subscribed to its type, signed the Standard Webhooks way: `webhook-id` (the same on every retry, and the thing to de-duplicate on), `webhook-timestamp` (unix seconds of this attempt; reject one more than 5 minutes from your clock), and `webhook-signature: v1,<base64 HMAC-SHA256>` over `<webhook-id>.<webhook-timestamp>.<body>`, keyed by the base64 after `whsec_` in the endpoint's secret, decoded to bytes. Verify the raw body, before parsing it. Answer 2xx within 15 seconds; anything else, a redirect, or no answer is a failure, and the event is sent again after 5 seconds, 5 minutes, 30 minutes, then 2, 5, 10, 14, 20 and 24 hours (each ±10%) — ten attempts over about 75 hours — with the same id and the same bytes. Events can arrive out of order: `data.ledger_entry_id` and `data.created_at` order them. An endpoint that has failed 10 deliveries in a row AND been failing for at least 24 hours is disabled: nothing more is sent to it, what was waiting is abandoned, `webhook.disabled` is written to the audit log, and GET /webhooks shows `status: disabled`. Delete it and create it again once the receiver works. An endpoint receives the events recorded after it was created.

- [`GET /webhooks`](https://matrixrewards.co.uk/docs/api/2026-10/webhooks.md#listWebhookEndpoints): The webhook endpoints on this account, and why any stopped
- [`POST /webhooks`](https://matrixrewards.co.uk/docs/api/2026-10/webhooks.md#createWebhookEndpoint): Send points movements to an https endpoint
- [`DELETE /webhooks/{endpoint_id}`](https://matrixrewards.co.uk/docs/api/2026-10/webhooks.md#deleteWebhookEndpoint): Stop sending to an endpoint
- [`POST /webhooks/{endpoint_id}/test`](https://matrixrewards.co.uk/docs/api/2026-10/webhooks.md#testWebhookEndpoint): Send one signed test event now

The events a webhook endpoint is sent are on [the Webhooks page](https://matrixrewards.co.uk/docs/api/2026-10/webhooks.md#events).

---

Page: https://matrixrewards.co.uk/docs/api/2026-10
Contract: 2026-10 sha256:35af153960028890fea5738799f5a71e535e1eea4dd3f6b8d5f50b37f02363da
