Simulate ruleset
Evaluates a caller-supplied test payload against the persisted ruleset addressed by — any lifecycle state (DRAFT / ACTIVE / INACTIVE) — and returns an evaluation trace. The ruleset’s own (schema, version) binding validates the payload and resolves rule field paths; the request carries no schema selector and no context. Requires the dedicated admin:rulesets:simulate scope. The simulation is inert — no decision record, no velocity counter increment, no blacklist push, no webhook, no lifecycle event, no backend invocation. Velocity counters are read live and never written, so two identical simulations may differ; the trace labels counter values as live-read.
Authorizations
HS256-signed JWT bearer token, obtained via the OAuth2 client-credentials grant (see Authentication).
Path Parameters
Ruleset ID
Body
The test decision payload. Validates exactly as the live decision body does against the ruleset's bound (schema, version). A "context" key is ignored — routing is fixed by the ruleset addressed in the URL.
Response
Evaluation trace
Result of simulating a ruleset against a test payload. The trace is a superset of the decision response's triggered_rules — same entry vocabulary, extended to every rule of the ruleset with its outcome and the derivations behind it.
One entry per backend rule that was reached, in the published BackendResult shape. Simulation never invokes a backend — decision is null, error is "not_simulated" (sibling of "insufficient_context" — backend skipped, no call made), latency_ms is null. Where the instance has the Link capability disabled, the live path makes no call either and records "backend_capability_disabled" with latency_ms 0; the trace renders that entry instead, so it reads as the live one would.
The simulated ruleset's context routing key.
DRAFT, ACTIVE, INACTIVE A ruleset's declared (schema, version) pair. name references a registry entry; version is required for custom schemas and absent for built-ins, whose version is implicit and advances only via Specter releases. Set at ruleset creation and immutable for the life of that ruleset version — rebinding a context means publishing a new ruleset version with the new binding and activating it. Rulesets that predate the registry surface the launch-backfilled transaction binding.
One entry per rule of the ruleset, in published evaluation order (rules-array order).
Simulated verdict — same semantics as the live decision enum. BLOCK terminates on first match, REVIEW accumulates, ALLOW is the default when nothing fires. PROVISIONAL is unreachable by simulation (no backend is ever invoked). Null exactly when verdict_suppressed is non-null.
ALLOW, REVIEW, BLOCK Present when the run cannot state the verdict a live decision would return. Reaching a live, synchronous backend rule suppresses it (backend_reached) — the backend is not invoked and its answer could change everything after it, so the remaining rules render not_evaluated. An async backend rule suppresses only a verdict that would otherwise be ALLOW (async_backend_reached), where the live path returns PROVISIONAL. Shadow rules (live false) and rules on an instance with the Link capability disabled never suppress.
Authoring soft-warns — advisory only, never affecting the verdict. Emitted e.g. when credential.pan and credential.masked_pan both populate the same BIN attribute with differing values (code bin_attribute_divergence, paths naming both field paths).