Audit Log
Every setting an operator changes through the Operator API is recorded in the platform audit log. With this API you can view the records of your own operations and revert (restore) an operation to its previous values.
| Method | Path | Purpose |
|---|---|---|
| GET | /operator/v1/audit | Get audit records |
| POST | /operator/v1/audit/{audit_id}/restore | Revert one operation to its previous values |
How audit records are kept
- Every write request (POST, PUT, PATCH, DELETE) except
POST /launchreturns the audit record ID in theX-Audit-Id: <integer>response header. If your admin screens keep their own operation log, store this ID with it. You use it later to check the status withGET /audit?ids=or to restore the change. - A record is stored only when the request succeeds (2xx). Failed requests may also carry an
X-Audit-Idheader, but no record exists for that ID. - Requests that change settings have the before and after values (snapshot) attached to the record. Only records with a snapshot can be reverted.
- If the request includes an
X-Operator-Admin: <admin ID>header (^[A-Za-z0-9_.@-]{1,40}$, not part of the signature), the actor is recorded asoperator:<operator code>/<admin ID>. Without it, the actor isoperator:<operator code>. This value only labels who performed the action and has nothing to do with permissions. - An operator can view and revert only records made under its own operator code. Settings changed by the platform are not visible through this API.
Revertible operations
| Operation | Reverting restores |
|---|---|
PUT /games/{game_code}/bet-limits, PUT /games/{game_code}/lobby | Game bet limits and lobby display settings |
PATCH /tables/{table_id}, POST /tables/{table_id}/close, PUT /tables/{table_id}/{settings, live, timers, rake-rule, card-design, currency} | Dedicated table settings (including reopening a closed table) |
PUT /settings, PUT /card-design | Operator settings |
PUT /rake-defaults | Rake defaults, and the dedicated tables changed along with them by apply_all / rake_floor |
POST /players/{external_id}/logout | Only the player's block status (block). Disconnected sessions are not revived |
PATCH /dealers/{dealer_id}, PUT /dealers/{dealer_id}/photo, DELETE /dealers/{dealer_id}/photo | Dealer name, role, active status and photo (the PIN is not reverted) |
DELETE /private-tables/{private_id} | Cancellation of a private table reservation |
A restore (audit.restore) itself | Cancels the restore — back to the values just before the restore |
Create requests (POST /tables, POST /dealers, POST /private-tables), badge issuance and revocation, and lobby banner image uploads are recorded only and cannot be reverted (restorable: false).
GET /operator/v1/audit
Retrieves audit records newest first (id descending). There are two ways to query.
Query parameters
Method 1 — by ID
| Parameter | Type | Required | Description |
|---|---|---|---|
ids | string | Yes | Comma-separated audit record IDs, up to 500 (e.g. ids=1204,1207). Non-numeric values are skipped |
When ids is given, the filter and paging parameters below are ignored, and only your own records among them are returned (has_more is always false).
Method 2 — by filter
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | No | Prefix match on the operation name (e.g. table. matches table.settings, table.close …) |
target | string | No | Exact match on the target (e.g. tbl_…, a dealer ID, an operator code) |
restorable | 1 | No | Only records with a snapshot |
limit | integer | No | Page size. Default 100, maximum 500 |
page | integer | No | Page number starting from 1 (default 1) |
Request example
GET /operator/v1/audit?action=table.&restorable=1&limit=50&page=1 HTTP/1.1
Host: {API_HOST}
X-Operator: acme
X-Api-Key: ak_live_…
X-Timestamp: 1760839200123
X-Nonce: 8d0f2b4a6c8e0d2f4b6a8c0e
X-Signature: 5c1d…Response example
{
"entries": [
{
"id": 1207,
"admin": "operator:acme/jane",
"action": "table.settings",
"target": "tbl_0198c1d2e3f47a5b8c9d0e1f2a3b4c5d",
"detail": { "currency": "PHP", "active": true, "before": { "…": "…" }, "after": { "…": "…" } },
"ip": "198.51.100.7",
"created_at": "2026-10-19T03:40:12.88Z",
"changes": [
{
"kind": "table",
"key": "0198c1d2-e3f4-7a5b-8c9d-0e1f2a3b4c5d",
"op": "update",
"fields": {
"limits.sb": { "before": 100, "after": 200 },
"limits.bb": { "before": 200, "after": 400 }
}
}
],
"restore_of": null,
"restored_by": null,
"restorable": true
},
{
"id": 1204,
"admin": "operator:acme/jane",
"action": "operator.watch_limit",
"target": "acme",
"detail": { "before": 0, "after": 600 },
"ip": "198.51.100.7",
"created_at": "2026-10-19T03:31:02.4Z",
"changes": [
{ "kind": "operator", "key": "0198a0b1-c2d3-7e4f-8a5b-6c7d8e9f0a1b", "op": "update", "fields": { "watch_limit_sec": { "before": 0, "after": 600 } } }
],
"restore_of": null,
"restored_by": 1210,
"restorable": true
}
],
"has_more": false
}Response fields
| Field | Type | Description |
|---|---|---|
entries[].id | int64 | Audit record ID (= the X-Audit-Id of that request) |
entries[].admin | string | Actor — operator:<code> or operator:<code>/<admin ID> |
entries[].action | string | Operation name (see the table below) |
entries[].target | string | Target (table ID, dealer ID, game code, player external_id, operator code, etc.) |
entries[].detail | object | Operation details (shape varies by operation, usually before / after) |
entries[].ip | string | null | IP of the server that made the request |
entries[].created_at | timestamp | Time recorded |
entries[].changes | array | Summary of changed settings (only when a snapshot exists) — see the table below |
entries[].restore_of | int64 | null | If this record is a restore, the ID of the original record it reverted |
entries[].restored_by | int64 | null | ID of the restore record that reverted this record (null if not reverted) |
entries[].restorable | bool | Whether this record can be reverted |
has_more | bool | Whether there is a next page (query again with page incremented by 1) |
changes[]
| Field | Description |
|---|---|
kind | Kind of the changed target — operator, operator_game, table, dealer, dealer_photo, player, private_reservation |
key | Internal key of the target row |
op | update, create or delete |
fields | Changed item → { before, after }. JSON settings are expanded into dot paths for the changed fields only (e.g. config.rake.rake_floor). Values such as passwords are masked, and large values such as photo bytes are shortened |
changes and detail are summaries for display. Item names are internal platform storage names and may change, so use action, target and restorable for programmatic decisions.
Operation names (action)
| Scope | Names |
|---|---|
| Game | game.bet_limits, game.lobby |
| Table | table.create, table.update, table.close, table.settings, table.currency, table.live, table.timers, table.rake_rule, table.card_design, table.private, table.private_cancel |
| Operator | operator.timezone, operator.multi_table, operator.watch_limit, operator.rake_defaults, operator.card_design |
| Player | player.logout |
| Dealer | dealer.create, dealer.update, dealer.badge_issue, dealer.badge_reissue, dealer.badge_revoke, dealer.photo, dealer.photo_delete |
| Restore | audit.restore |
| Other | api <METHOD> <path pattern> — write requests without a dedicated name (e.g. api PUT /operator/v1/lobby-banners) |
If one request changes several settings (e.g. changing the time zone and multi-table play together with PUT /settings), several records may be created. In that case, the snapshot and X-Audit-Id are attached to the first record.
Errors
| HTTP | Code | Situation |
|---|---|---|
| 500 | INTERNAL_ERROR | Temporary server error |
POST /operator/v1/audit/{audit_id}/restore
Reverts the operation of one audit record to its previous values. The revert itself is also recorded as a new audit record (audit.restore), and its ID is written to restored_by of the original record. Restoring a restore record cancels the restore.
The change is applied immediately to running tables, the dealer tool and entry settings.
Path and request fields
| Field | Type | Required | Description |
|---|---|---|---|
audit_id | int (path) | Yes | ID of the audit record to revert |
force | bool (body) | No | Revert and overwrite even if the same setting was changed again after that operation. Defaults to false |
The body may be omitted (signing an empty body or {} means force: false).
Conflict handling
Before reverting, the platform checks that the current values match "the values right after that operation". If someone changed the same setting again afterwards, nothing is changed and 409 RESTORE_CONFLICT is returned with a list of conflicts. In that case, either
- revert the later operations first, starting from the most recent, or
- to ignore the later changes and overwrite them, send the request again with
force: true.
Request example
curl -X POST {API_BASE}/operator/v1/audit/1207/restore \
-H 'Content-Type: application/json; charset=utf-8' \
-H 'X-Operator: acme' -H 'X-Api-Key: ak_live_…' -H 'X-Operator-Admin: jane' \
-H 'X-Timestamp: 1760839200123' -H 'X-Nonce: 2f4b6a8c0e2d4f6b8a0c2e4d' -H 'X-Signature: b83a…' \
-d '{}'Response example
200 OK (the X-Audit-Id response header is also the restore record ID)
{
"ok": true,
"audit_id": 1211,
"changes": [
{
"kind": "table",
"key": "0198c1d2-e3f4-7a5b-8c9d-0e1f2a3b4c5d",
"op": "update",
"fields": {
"limits.sb": { "before": 200, "after": 100 },
"limits.bb": { "before": 400, "after": 200 }
}
}
]
}| Field | Type | Description |
|---|---|---|
ok | bool | Always true |
audit_id | int64 | ID of the newly created restore record |
changes | array | Summary of the settings actually changed by the restore (same shape as changes in the list) |
Errors
| HTTP | Code | details | Situation |
|---|---|---|---|
| 404 | NOT_FOUND | — | Malformed ID, nonexistent record, or a record belonging to another operator or the platform |
| 403 | NOT_RESTORABLE | — | Includes changes of a kind that cannot be reverted with operator permissions |
| 409 | NOT_RESTORABLE | — | No snapshot to revert (create requests, badges, etc.), or the restore feature is disabled in this environment |
| 409 | RESTORE_BLOCKED | { "kind": "table", "key": "…" } | Cannot be reverted in the current state — e.g. reverting the currency of a table where players are seated. message contains the reason. Try again after the situation changes |
| 409 | RESTORE_CONFLICT | { "conflicts": [ { "kind": "table", "key": "…" } ] } | The same setting was changed again after that operation — see Conflict handling above |
| 500 | INTERNAL_ERROR | — | Server error during the restore |
Example RESTORE_CONFLICT response:
{
"error": {
"code": "RESTORE_CONFLICT",
"message": "changed again after this action — restore the later changes first, or force",
"details": { "conflicts": [ { "kind": "table", "key": "0198c1d2-e3f4-7a5b-8c9d-0e1f2a3b4c5d" } ] }
}
}