# Log

What every key did, and what it was shown.

Part of [the API reference, version 2026-10](https://matrixrewards.co.uk/docs/api/2026-10.md). Every address below starts with the base address:

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

## What every key changed, and what it was shown {#listAuditLog}

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

**Needs:** the `read_audit` permission (in the app: “The activity log — what each key did and saw”).

Append-only. A disclosure row says how many shoppers a read carried; a change row says what changed. `object_ref` names a shopper, so it is returned only to a key that also holds `read_members` — and that read is itself recorded.

### Parameters

| Name | In | Required | Type | What it is |
| --- | --- | --- | --- | --- |
| `actor` | query | no | string | One key id. |
| `from` | query | no | string | 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). |
| `to` | query | no | string | 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). |
| `limit` | query | no | integer, from 1 to 100, default `25` | 1 to 100. Larger values are capped. |
| `cursor` | query | no | string | Opaque. 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 log entries.

| Field | Type | Always there | What it is |
| --- | --- | --- | --- |
| `data` | list of object | yes | — |
| `data[].id` | string | yes | — |
| `data[].at` | string | yes | — |
| `data[].actor_type` | one of `api_key`, `oauth_token`, `staff`, `platform` | yes | Who acted. `platform` is Matrix Rewards itself acting on this account — our staff from the platform console, or a migration — written into this account's own log so it can be seen. |
| `data[].actor_id` | string, or null | yes | — |
| `data[].actor_name` | string, or null | yes | — |
| `data[].client` | string, or null | yes | From the caller's `Matrix-Client` header. |
| `data[].request_id` | string, or null | yes | — |
| `data[].action` | string | yes | — |
| `data[].store_key` | string, or null | yes | — |
| `data[].object_ref` | string, or null | yes | The member key, store key or reward the action touched. Null when the key does not hold `read_members`, even if the entry names one. |
| `data[].detail` | object, open | yes | — |
| `data[].result` | one of `applied`, `dry_run`, `refused`, `disclosed` | yes | — |
| `data[].reason` | string, or null | yes | — |
| `has_more` | boolean | yes | — |
| `next_cursor` | string, or null | yes | — |

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](https://matrixrewards.co.uk/docs/api/2026-10.md#headers).

### Example

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

The answer:

```json
{
  "data": [
    {
      "id": "0d1e2f30-4a5b-4c6d-8e7f-00000000001b",
      "at": "2026-09-16T10:00:00Z",
      "actor_type": "api_key",
      "actor_id": "Kx7Qp2Lm9Vt4Rz8N",
      "actor_name": "Nightly export",
      "client": "example-script/1.0",
      "request_id": "0d1e2f30-4a5b-4c6d-8e7f-000000000008",
      "action": "member.read",
      "store_key": null,
      "object_ref": "mx_3f6c2a9e-8b41-4d7a-9e05-c1b7d24f6a18",
      "detail": {
        "subject_count": 1
      },
      "result": "disclosed",
      "reason": null
    },
    {
      "id": "0d1e2f30-4a5b-4c6d-8e7f-00000000001c",
      "at": "2026-09-16T10:00:00Z",
      "actor_type": "api_key",
      "actor_id": "Kx7Qp2Lm9Vt4Rz8N",
      "actor_name": "Nightly export",
      "client": "example-script/1.0",
      "request_id": "0d1e2f30-4a5b-4c6d-8e7f-000000000013",
      "action": "ledger.read",
      "store_key": null,
      "object_ref": null,
      "detail": {
        "subject_count": 1
      },
      "result": "disclosed",
      "reason": null
    },
    {
      "id": "0d1e2f30-4a5b-4c6d-8e7f-00000000001d",
      "at": "2026-09-16T10:00:00Z",
      "actor_type": "api_key",
      "actor_id": "Kx7Qp2Lm9Vt4Rz8N",
      "actor_name": "Nightly export",
      "client": "example-script/1.0",
      "request_id": "0d1e2f30-4a5b-4c6d-8e7f-000000000007",
      "action": "members.list",
      "store_key": null,
      "object_ref": null,
      "detail": {
        "subject_count": 1
      },
      "result": "disclosed",
      "reason": null
    }
  ],
  "has_more": true,
  "next_cursor": "eyJhdCI6IjIwMjYtMDktMTZUMTA6MDA6MDBaIiwiaWQiOiIwZDFlMmYzMCJ9"
}
```

### Other answers

| Status | What it means | Error pages |
| --- | --- | --- |
| 400 | `invalid_request`: a parameter could not be read; `param` names it. `invalid_cursor`: the `cursor` is not one this list issued. | [invalid_request](https://matrixrewards.co.uk/docs/errors/invalid_request.md), [invalid_cursor](https://matrixrewards.co.uk/docs/errors/invalid_cursor.md) |
| 401 | `unauthenticated`: no usable API key was presented. Malformed, unknown, revoked and wrong-secret are one answer. | [unauthenticated](https://matrixrewards.co.uk/docs/errors/unauthenticated.md) |
| 403 | `forbidden_scope`: the key does not carry the scope this call needs; `required_scope` says which. | [forbidden_scope](https://matrixrewards.co.uk/docs/errors/forbidden_scope.md) |
| 429 | `rate_limited`: too many requests for this key; `bucket` says which allowance. `Retry-After` says how long to wait. | [rate_limited](https://matrixrewards.co.uk/docs/errors/rate_limited.md) |

---

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