Skip to content
MatrixRewards
API docs menu

Reports

The ledger, liability and settlement.

Part of the API reference, version 2026-10. Every address below starts with the base address:

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

Every points movement on this account, newest first

GET /ledger — the full address is https://app.matrixrewards.co.uk/api/2026-10/ledger.

Needs: the read_reports permission (in the app: “The ledger, what you owe, and settlement between stores”).

The ledger is append-only: a correction is a later row, never an edit to an earlier one.

Parameters

NameInRequiredTypeWhat it is
storequerynostring—
member_keyquerynostring—
fromquerynostring2026-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).
toquerynostring2026-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).
limitquerynointeger, from 1 to 100, default 251 to 100. Larger values are capped.
cursorquerynostringOpaque. Pass back next_cursor from the previous page, with the same filters, and on GET /members the same sort and order.

The answer

A page of ledger entries.

FieldTypeAlways thereWhat it is
datalist of objectyes—
data[].idintegeryes—
data[].atstringyes—
data[].store_keystringyes—
data[].store_namestring, or nullyesNull when the row's store is not one of this account's.
data[].member_keystringyes—
data[].delta_pointsintegeryesSigned: earning is positive, spending and clawbacks negative.
data[].reasonstringyes—
data[].rule_idstringyes—
data[].source_typestringyes—
data[].source_refstring, or nullyesThe platform's own key for what caused the row: an order, a refund, a points change. Null when that key is a reward code — a cancelled code's points coming back (redeem_void) or being taken again because it was spent after all (void_clawback); code_ending and code_ref name the code instead.
data[].order_refstring, or nullyes—
data[].code_endingstring, or nullyesThe last four characters of the reward code this row moved points for; null on a row that is not about a code, and for a code too short to show any of (see CodePage). The whole code is never returned by this API.
data[].code_refstring, matching ^[0-9a-f]{20}$, or nullyesThat code's ref, as listMemberCodes gives it and cancelMemberCode takes it. Null on a row with no code, or when the platform holds no record of the code to give a reference for.
has_morebooleanyes—
next_cursorstring, or nullyes—

Headers on the answer: Request-Id, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. What each header means.

Example

curl "https://app.matrixrewards.co.uk/api/2026-10/ledger" \
  -H "Authorization: Bearer $MATRIX_API_KEY"

The answer:

{
  "data": [
    {
      "id": 3,
      "at": "2026-09-16T10:00:00.000Z",
      "store_key": "example-store",
      "store_name": "Example Store",
      "member_key": "mx_3f6c2a9e-8b41-4d7a-9e05-c1b7d24f6a18",
      "delta_points": 500,
      "reason": "Reward removed — points returned",
      "rule_id": "redeem_void",
      "source_type": "redeem_void",
      "source_ref": null,
      "order_ref": null,
      "code_ending": "4TPB",
      "code_ref": "5f0c2d8e91a47b36c0de"
    },
    {
      "id": 2,
      "at": "2026-09-16T10:00:00.000Z",
      "store_key": "example-store",
      "store_name": "Example Store",
      "member_key": "mx_3f6c2a9e-8b41-4d7a-9e05-c1b7d24f6a18",
      "delta_points": 50,
      "reason": "Sorry about the late parcel",
      "rule_id": "admin_adjustment",
      "source_type": "admin_adjustment",
      "source_ref": "admin|api.Kx7Qp2Lm9Vt4Rz8N|goodwill-2026-09-16-0001|mx_3f6c2a9e-8b41-4d7a-9e05-c1b7d24f6a18|50",
      "order_ref": null,
      "code_ending": null,
      "code_ref": null
    },
    {
      "id": 1,
      "at": "2026-08-04T11:02:00Z",
      "store_key": "example-store",
      "store_name": "Example Store",
      "member_key": "mx_3f6c2a9e-8b41-4d7a-9e05-c1b7d24f6a18",
      "delta_points": 640,
      "reason": "Points earned on your order",
      "rule_id": "base_earn",
      "source_type": "order",
      "source_ref": "o-1001",
      "order_ref": null,
      "code_ending": null,
      "code_ref": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}

Other answers

StatusWhat it meansError pages
400invalid_request: a parameter could not be read; param names it. invalid_cursor: the cursor is not one this list issued.invalid_request, invalid_cursor
401unauthenticated: no usable API key was presented. Malformed, unknown, revoked and wrong-secret are one answer.unauthenticated
403forbidden_scope: the key does not carry the scope this call needs; required_scope says which.forbidden_scope
429rate_limited: too many requests for this key; bucket says which allowance. Retry-After says how long to wait.rate_limited
503access_not_recorded: the read could not be written to the account's audit log, so no data was returned.access_not_recorded

What this account owes its shoppers

GET /reports/liability — the full address is https://app.matrixrewards.co.uk/api/2026-10/reports/liability.

Needs: the read_reports permission (in the app: “The ledger, what you owe, and settlement between stores”).

Summed from the ledger, not from the balance cache. The money value is null with a reason rather than a guess when the stores redeem at different rates or none is configured.

The answer

The liability report.

FieldTypeAlways thereWhat it is
as_atstringyes—
redeemable_pointsintegeryesHeld by members in credit — what could be spent tomorrow.
net_pointsintegeryesThe algebraic sum, including negative balances.
members_in_creditintegeryes—
total_membersintegeryes—
points_expiring_within_daysinteger, or nullyesPoints due to expire within expiring_within_days that can still be taken: the shopper holds them, was shown every warning whose window has already passed, and can still be shown the rest because a store they shop at shows the expiry countdown. It is the most that can go, not a forecast: a shopper who misses a later warning keeps their points. Null means we could not tell, which is not the same as none.
expiring_within_daysintegeryes—
outstanding_codeslist of objectyes—
outstanding_codes[].store_keystringyes—
outstanding_codes[].countintegeryes—
outstanding_codes[].cost_pointsintegeryes—
valuationobject, or nullyes—
valuation.currencystringyes—
valuation.minor_unitsintegeryes—
valuation.major_unitsstringyes—
valuation_unavailableone of mixed_rates, no_rate_configured, or nullyes—
redeem_rate_by_storelist of objectyes—
redeem_rate_by_store[].store_keystringyes—
redeem_rate_by_store[].currencystring, or nullyes—
redeem_rate_by_store[].redeem_points_per_major_unitinteger, or nullyes—

Headers on the answer: Request-Id, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. What each header means.

Example

curl "https://app.matrixrewards.co.uk/api/2026-10/reports/liability" \
  -H "Authorization: Bearer $MATRIX_API_KEY"

The answer:

{
  "as_at": "2026-09-16T10:00:00Z",
  "redeemable_points": 1190,
  "net_points": 1190,
  "members_in_credit": 1,
  "total_members": 1,
  "points_expiring_within_days": 0,
  "expiring_within_days": 90,
  "outstanding_codes": [],
  "valuation": {
    "currency": "GBP",
    "minor_units": 1190,
    "major_units": "11.90"
  },
  "valuation_unavailable": null,
  "redeem_rate_by_store": [
    {
      "store_key": "example-outlet",
      "currency": "GBP",
      "redeem_points_per_major_unit": 100
    },
    {
      "store_key": "example-store",
      "currency": "GBP",
      "redeem_points_per_major_unit": 100
    }
  ]
}

Other answers

StatusWhat it meansError pages
401unauthenticated: no usable API key was presented. Malformed, unknown, revoked and wrong-secret are one answer.unauthenticated
403forbidden_scope: the key does not carry the scope this call needs; required_scope says which.forbidden_scope
429rate_limited: too many requests for this key; bucket says which allowance. Retry-After says how long to wait.rate_limited

Points earned at one store and spent at another, inside a window

GET /reports/settlement — the full address is https://app.matrixrewards.co.uk/api/2026-10/reports/settlement.

Needs: the read_reports permission (in the app: “The ledger, what you owe, and settlement between stores”).

The window is two absolute UTC instants. The report keeps the engine's own field names.

Parameters

NameInRequiredTypeWhat it is
fromqueryyesstringThe 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.
toqueryyesstringThe 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.

The answer

The settlement report.

FieldTypeAlways thereWhat it is
reportobject, openyesThe settlement report in the engine's own field names.

An open object has no fixed set of fields: it is sent as the platform holds it, in its own field names.

Headers on the answer: Request-Id, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. What each header means.

Example

curl "https://app.matrixrewards.co.uk/api/2026-10/reports/settlement?from=2026-09-01T00:00:00Z&to=2026-10-01T00:00:00Z" \
  -H "Authorization: Bearer $MATRIX_API_KEY"

The answer:

{
  "report": {
    "accountId": "acc_example",
    "window": {
      "from": "2026-09-01T00:00:00Z",
      "to": "2026-09-16T00:00:00Z"
    },
    "lines": [],
    "totals": {
      "redeemedPoints": 0,
      "consumedPoints": 0,
      "attributedPoints": 0,
      "unattributedPoints": 0,
      "valueByCurrency": {}
    },
    "attributionComplete": true,
    "anomalies": [],
    "unpricedSpendSites": [],
    "unknownSpendSites": [],
    "clampedFutureRows": 0,
    "ledgerDigest": "17b799bbaf2815941767da47eebbc881fac4e92211c327b92723cad37f5003b7"
  }
}

Other answers

StatusWhat it meansError pages
400invalid_request: a parameter or the body could not be read; param names it.invalid_request
401unauthenticated: no usable API key was presented. Malformed, unknown, revoked and wrong-secret are one answer.unauthenticated
403forbidden_scope: the key does not carry the scope this call needs; required_scope says which.forbidden_scope
429rate_limited: too many requests for this key; bucket says which allowance. Retry-After says how long to wait.rate_limited
503access_not_recorded: the read could not be written to the account's audit log, so no data was returned.access_not_recorded

Last updated: 14 October 2026