Skip to content
MatrixRewards
API docs menu

Safe retries and previews

Send the same change twice and it is made once. Ask for a preview and nothing changes.

Both apply to the two calls that change a member: POST /members/{member_key}/adjustments and POST /members/{member_key}/codes/void.

Idempotency-Key

Every points change and every cancel carries an Idempotency-Key header: a name you choose for that one change, of up to 100 letters, digits, dots, underscores, colons and hyphens. The reference describes it like this:

In short:

  • Use a new key for each new change.
  • To retry a change, send exactly the same request with the same key.
  • Never use a new key to retry a change you are unsure about. A new key is a new change: if the first one was made, you have now made it twice.

The three answers a key can have, besides the first one:

Creating a webhook endpoint takes no Idempotency-Key. POST /webhooks says why, and what to do after an answer that went missing.

Preview a change

Add ?dry_run=true to either call. The reference says of dry_run:

A points change's preview says in outcome what the real call would do: would_apply or would_replay. A cancel's preview says would_void, already_voided, nothing_to_void or would_replay. And of the preview's confirmation:

Test keys

A test key walks the whole flow for real: its preview is a real preview and it can send the confirmation back, but the change itself is refused with test_mode_key. Nothing changes.

Keys for AI assistants

A key you marked as being for an AI assistant cannot make a change in one call. It has to send the Matrix-Confirmation header, which the reference describes like this:

So a change takes four steps:

  1. Choose a new Idempotency-Key and keep it.
  2. Send the change with ?dry_run=true.
  3. Show the person the preview, and wait for a clear yes.
  4. Send the identical request, without dry_run, with the preview's confirmation.token in the Matrix-Confirmation header, within 10 minutes.

Both steps are in your activity log. What the rule proves is that a change was previewed first. It cannot prove a person saw the preview: that is the assistant's job. And it does not protect you from a stolen key, because a thief can preview and confirm too. Against that, a key has its permissions, its limits, the log, and revoking.

A worked example

Set the member's key first, in place of the words in angle brackets, then preview the change. Choose a new Idempotency-Key for each change you make; the one here is an example.

export MEMBER='<member_key from GET /members>'
curl -X POST "https://app.matrixrewards.co.uk/api/2026-10/members/$MEMBER/adjustments?dry_run=true" \
  -H "Authorization: Bearer $MATRIX_API_KEY" \
  -H "Idempotency-Key: goodwill-2026-09-16-0001" \
  -H "Content-Type: application/json" \
  -d '{"delta_points": 50, "reason": "Sorry about the late parcel"}'

The preview:

{
  "object": "adjustment_preview",
  "dry_run": true,
  "outcome": "would_apply",
  "member_key": "mx_3f6c2a9e-8b41-4d7a-9e05-c1b7d24f6a18",
  "delta_points": 50,
  "balance_points_before": 640,
  "balance_points_after": 690,
  "store_key": "example-store",
  "limit": {
    "direction": "credit",
    "limit_points": 100000,
    "used_points": 0,
    "remaining_points": 100000
  },
  "confirmation": {
    "token": "mct_EXAMPLE.EXAMPLE",
    "expires_at": "2026-09-16T10:10:00.000Z"
  },
  "audit_id": "0d1e2f30-4a5b-4c6d-8e7f-00000000000b"
}

Then make the change: the same request, without dry_run, with the preview's confirmation.token in Matrix-Confirmation. Only a key for an assistant has to send it, but any key may, and it is then checked.

export CONFIRMATION='<confirmation.token from the preview>'
curl -X POST "https://app.matrixrewards.co.uk/api/2026-10/members/$MEMBER/adjustments" \
  -H "Authorization: Bearer $MATRIX_API_KEY" \
  -H "Idempotency-Key: goodwill-2026-09-16-0001" \
  -H "Matrix-Confirmation: $CONFIRMATION" \
  -H "Content-Type: application/json" \
  -d '{"delta_points": 50, "reason": "Sorry about the late parcel"}'

The answer:

{
  "object": "adjustment",
  "member_key": "mx_3f6c2a9e-8b41-4d7a-9e05-c1b7d24f6a18",
  "delta_points": 50,
  "balance_points": 690,
  "store_key": "example-store",
  "replayed": false,
  "idempotency_key": "goodwill-2026-09-16-0001",
  "audit_id": "0d1e2f30-4a5b-4c6d-8e7f-00000000000d"
}

Send that second request again and you get the same answer back, with Idempotency-Replayed: true, and the points move once.

Last updated: 25 September 2026