Check what a list's write rules would do with a write, without making it. The rules run exactly as they would on a real request, including variable substitution and the list's JSON schema, and the response shows every part of every rule and what it evaluated to.
Send rules to try a rule set that hasn't been saved yet. Leave it out to test the list's own rules.
POST https://api.jsonpad.io/lists/{listId}/rules/testThis needs user auth mode, or a token with update permission on the list: a dry run with rule text of your own could read any field, including ones a guard index hides. It's metered like any other request — the command line tool can run the same checks offline for nothing.
listIdstringA list id or path name.{action: "update"itemId: "current-game"new: {status: "started"currentPlayerId: "4d1c…"moves: [0: {playerId: "8f2a…"column: 3}]}identityId: "8f2a…"}actionstringcreate, update, delete or restore. A restore is checked against the update rules, as it is on a real write.rulesnullable stringThe rules to test. Defaults to the list's saved rules, and testing a list with no rules is an error.itemIdstringAn item id or alias to take the old data and metadata from. Its data is read in full, without guard indexes hiding anything, which is why this endpoint needs permission to edit the list.oldanyThe item's data before the write, which overrides the item's own. Ignored for create.newanyThe data after the write. Ignored for delete.patcharrayA JSON Patch applied to the old data to make the new data, instead of sending new.mergeanyA JSON merge patch applied to the old data, instead of sending new.identityIdstringAn identity to make the write as, loaded from your account.identitynullable objectAn identity object to make the write as, which doesn't have to exist. null means no identity.tokenobjectThe token to make the write as, as { id, tags }. Useful for checking a rule that reads token.tags. Defaults to the calling token.nowstringAn ISO-8601 date the rules see as now, for testing deadlines. Defaults to the current time.pointernullable stringThe JSON pointer a partial-data write targets, which rules read as request.pointer.substitutebooleanWhether to run $jsonpad-var substitution on the new data first, as a real write does. Defaults to true.schemabooleanWhether to check the list's JSON schema between the two stages, as a real write does. Defaults to true.The response is 200 whatever the rules decided: allowed and status say what a real write would have got.
{allowed: falsestage: "allow"status: 403code: "WRITE_RULE_DENIED"reason: "no-allow-passed"message: "Write denied by list rules"statement: nulloperation: "update"action: "update"engineVersion: "1.0.0"languageVersion: 1diagnostics: []budget: {used: 33limit: 100000}statements: [0: {index: 0kind: "allow"label: "your turn"line: 5span: {start: 87end: 191line: 5column: 1endLine: 7endColumn: 41}operations: [0: "update"]result: falseerror: nullerrorLine: nulltrace: [0: {id: 20span: {start: 156end: 190line: 7column: 6endLine: 7endColumn: 40}value: false}]}]}allowedbooleanWhether the write would go through.stagestringWhich step decided: allow (nothing authorised it), schema (the list's JSON schema refused it), require (a check failed), or ok.statusnumberThe status a real write would have got: 200, 400 or 403.codenullable stringWRITE_RULE_DENIED, WRITE_RULE_FAILED or VALIDATION_ERROR, or null when the write is allowed.messagenullable stringWhat a real write would have been told. For a failed require that's your else message.statementnullable objectThe statement that decided, as { index, kind, label, line }. It's null when no allow passed, because no single statement is to blame.diagnosticsarrayThe checker's warnings about the rules that were tested, each with a severity, a code, a message and a span.budgetobjectHow much of the per-write evaluation budget these rules used, and the limit.statementsarrayEvery statement that ran, in order, with its result and any error. Statements that don't cover the operation aren't included, and nothing after the decision runs.
trace holds one entry per expression that was evaluated, with its span in the rule text and its value. Short-circuited expressions have no entry at all, so the trace is exactly what the engine looked at.
newanyThe data the rules saw, after variable substitution. Only included in user auth mode.In token auth mode the trace keeps its shape and its boolean results, but every other value is left out and the entry is marked "hidden": true instead, so a token that can edit a list still can't read values out of it this way. The new field is left out for the same reason.