Rules Engine API Reference
On this page
Manages the JSON Decision Model (JDM) rule sets behind CRAIG’s automated determinations and evaluates inputs against them via the GoRules Zen Engine.
Endpoints
Evaluation
Evaluate input against a rule set
POST /v1/rules/evaluate
Runs the named rule set against the provided input and records an audit trail.
| Field | Type | Required | Description |
|---|---|---|---|
context_id |
UUID (optional) |
No |
Optional context entity ID for the audit trail. |
context_type |
string (optional) |
No |
Optional context type for the audit trail (e.g. "eligibility", "case"). |
input |
object |
Yes |
Input data to feed into the rule set. |
pin |
EvaluationPin (optional) |
No |
Pin |
rule_set |
string |
Yes |
Name of the rule set to evaluate against. |
-
200: Evaluation result
-
401: Unauthorized
-
403: Forbidden
-
404: Rule set not found
-
500: Internal error
-
503: Evaluation exceeded the dispatch budget (CRAIG_RULES__EVAL_TIMEOUT_MS)
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
List evaluation audit records
GET /v1/rules/evaluations
Paginated and filterable list of past rule evaluations. Requires supervisor or admin role.
| Name | In | Required | Description |
|---|---|---|---|
page |
query |
No |
Page number (1-based). |
per_page |
query |
No |
Items per page (max 500). |
context_type |
query |
No |
Filter by context type. |
context_id |
query |
No |
Filter by context entity ID. |
rule_set_name |
query |
No |
Filter by rule set name. |
disposition |
query |
No |
Filter by disposition (#1048): |
-
200: Paginated list of evaluations
-
400: Unknown disposition filter or page depth past the cap
-
401: Unauthorized
-
403: Forbidden — supervisor or admin role required
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Rule Sets
List active rule sets
GET /v1/rules/sets
| Name | In | Required | Description |
|---|---|---|---|
page |
query |
No |
Page number (1-based). |
per_page |
query |
No |
Items per page (max 500). |
search |
query |
No |
Full-text search across name and description. |
prefix |
query |
No |
Plan A § D4: prefix filter (e.g. |
sort_by |
query |
No |
Sort column: name, version (default: created_at). |
sort_dir |
query |
No |
Sort direction: asc or desc (default: desc). |
-
200: Paginated list of active rule sets
-
401: Unauthorized
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Create a new rule set
POST /v1/rules/sets
Validates that the JDM content compiles before persisting. Requires admin role.
| Field | Type | Required | Description |
|---|---|---|---|
client_request_id |
UUID |
Yes |
Client-minted idempotency id (ADR-062 §B, #1265) — REQUIRED.
Same id + identical intent replays the ORIGINAL rule set (the
row as the detail projection now serves it); a different intent
under the same id is a 409 idempotency-conflict. A same-name
create under a FRESH id stays the domain 409 (the retained
|
content |
object |
Yes |
JDM decision model content ( |
description |
string (optional) |
No |
Optional description. |
name |
string |
Yes |
Human-readable name (must be unique). Lowercase with interior
hyphens/underscores: |
version |
string |
Yes |
Semantic version string. |
-
200: Rule set created (a replay returns the rule set as the detail projection now serves it — same client_request_id + intent)
-
400: Invalid JDM content
-
401: Unauthorized
-
403: Forbidden — admin role required
-
409: Name already exists, client_request_id claimed by a different operation, or replayed entity gone (ADR-062)
-
422: Validation failure (including a missing client_request_id)
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Get an active rule set by name
GET /v1/rules/sets/by-name/{name}
| Name | In | Required | Description |
|---|---|---|---|
name |
path |
Yes |
Rule set name (unique) |
-
200: Rule set found
-
401: Unauthorized
-
404: Rule set not found
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Get a rule set by ID
GET /v1/rules/sets/{id}
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Rule set ID |
-
200: Rule set found
-
401: Unauthorized
-
404: Rule set not found
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Update a rule set
PUT /v1/rules/sets/{id}
Partial update — only provided fields are changed. Validates JDM if content is updated. Requires admin role.
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Rule set ID |
If-Match |
header |
Yes |
REQUIRED row REVISION from your last read (ADR-062 §G3), e.g. |
| Field | Type | Required | Description |
|---|---|---|---|
content |
object |
No |
New JDM content (optional, validated if provided). |
description |
string (optional) |
No |
New description (optional). |
name |
string (optional) |
No |
New name (optional). When present, same charset as create. |
version |
string (optional) |
No |
New version (optional). |
-
200: Rule set updated
-
400: Invalid JDM content, or a missing/malformed If-Match
-
401: Unauthorized
-
403: Forbidden — admin role required
-
404: Rule set not found
-
409: Name already exists, or the revision moved since your read (stale If-Match)
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Delete a rule set
DELETE /v1/rules/sets/{id}
Soft-deletes by setting active = false. Requires admin role and a reason query parameter (#1556 — recorded on the audit snapshot).
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Rule set ID |
reason |
query |
Yes |
Why this rule set is being retired (mandatory; audit-visible on the delete snapshot row). |
-
204: Rule set deleted
-
400: Missing
reasonquery parameter (#1556) -
401: Unauthorized
-
403: Forbidden — admin role required
-
404: Rule set not found
-
422: Empty/over-length
reason(#1556) -
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Export a rule set as a downloadable JSON file
GET /v1/rules/sets/{id}/export
Returns the JDM content as an attachment. Requires admin role.
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Rule set ID |
-
200: JDM JSON file
-
401: Unauthorized
-
403: Forbidden — admin role required
-
404: Rule set not found
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Import JDM content into an existing rule set
POST /v1/rules/sets/{id}/import
Replaces the rule set content with the wrapper’s JDM content and auto-generates a timestamp version. Pre-1.0 breaking change (#1265): the body is the {client_request_id, content} wrapper, no longer the bare JDM document. Requires admin role.
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Rule set ID |
| Field | Type | Required | Description |
|---|---|---|---|
client_request_id |
UUID |
Yes |
Client-minted idempotency id (ADR-062 §B, #1265) — REQUIRED. Import is a command on the PATH rule set (the claim’s entity is the path id, not a fresh row): same id + identical intent replays without re-importing (the rule set is returned as it now stands — no second version mint, no revision bump); a different intent — including the same content aimed at a different rule set — is a 409 idempotency-conflict. |
content |
object |
Yes |
JDM decision model content ( |
-
200: Rule set content imported (a replay returns the rule set as it now stands — same client_request_id + intent; no second version mint or revision bump)
-
400: Invalid JDM content
-
401: Unauthorized
-
403: Forbidden — admin role required
-
404: Rule set not found (the claim rolls back — the request id is not burned)
-
409: client_request_id claimed by a different operation, or replayed entity gone (ADR-062)
-
422: Malformed wrapper body (including a missing client_request_id — the pre-#1265 bare-JDM wire)
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Execute a previewed promotion (the consent act)
POST /v1/rules/sets/{id}/promote
Re-binds the candidate content by canonical hash to the named preview, re-CASes the live revision against the preview’s from_revision INSIDE the flip transaction (409 promote-preview-stale; the preview is never burned), then flips content + version, writes the promote snapshot carrying the canary report as evidence, and stages the invalidation + audit events on the same transaction (#1556).
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Rule set ID |
| Field | Type | Required | Description |
|---|---|---|---|
acknowledged_thin_corpus |
boolean |
No |
The thin-corpus consent: when the preview’s corpus was below the evidence floor, the flip refuses unless this names the gap explicitly (an empty diff over an empty corpus is NOT evidence — the zero-fault-green class). |
client_request_id |
UUID |
Yes |
Client-minted idempotency id (ADR-062 §B) — REQUIRED. |
content |
object |
Yes |
Candidate JDM content — must hash-match the preview’s binding. |
preview_id |
UUID |
Yes |
The preview whose evidence this execute consents to. |
reason |
string |
Yes |
Why this promotion is happening (recorded on the snapshot; may restate or extend the preview’s reason). |
version |
string |
Yes |
Must equal the preview’s candidate version. |
-
200: Promoted (a replay returns the rule set as it now stands)
-
400: Invalid JDM content
-
401: Unauthorized
-
403: Forbidden
-
404: Rule set or preview not found
-
409: promote-preview-stale (live revision moved; re-preview), promote-preview-mismatch (content/version/target differ from the preview’s binding), thin-corpus-unacknowledged, or an ADR-062 idempotency conflict
-
422: Malformed body (including a missing client_request_id)
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Preview a promotion: compile + shadow-canary the candidate
POST /v1/rules/sets/{id}/promote/preview
Compiles the candidate, replays the last-N real evaluation inputs against live AND candidate on an isolated thread, persists the categorical diff report, and returns it with the execute binding. No flip happens here; previews are never burned (#1556).
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Rule set ID |
| Field | Type | Required | Description |
|---|---|---|---|
content |
object |
Yes |
Candidate JDM content ( |
reason |
string |
Yes |
Why this promotion is happening (audit-visible; recorded on the preview row and, at execute, the promote snapshot). |
version |
string |
Yes |
The version string the candidate will carry once promoted. Reusing the LIVE version string with different content is refused (version strings stay human-meaningful even though the revision is the true content key). |
-
200: The persisted canary evidence + execute binding
-
400: Invalid JDM content, or the LIVE version string reused with different content
-
401: Unauthorized
-
403: Forbidden — requires RuleSet Update AND RuleEvaluation List (the corpus leg replays real evaluation inputs)
-
404: Rule set not found
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.
Roll back to a snapshotted revision (as a NEW revision)
POST /v1/rules/sets/{id}/rollback
Restores the content + version of the snapshot at (this rule set, target_revision) as a NEW revision — monotone history, the counter never rewinds. No canary (the target content previously served); the content is compile-revalidated because the engine may have moved since the snapshot’s vintage. Refuses on soft-deleted rule sets (recreate is the path — the rebinding doctrine) (#1556).
| Name | In | Required | Description |
|---|---|---|---|
id |
path |
Yes |
Rule set ID |
| Field | Type | Required | Description |
|---|---|---|---|
client_request_id |
UUID |
Yes |
Client-minted idempotency id (ADR-062 §B) — REQUIRED. |
expected_revision |
integer |
Yes |
The live revision this rollback expects to move FROM (the CAS — a concurrent mutation 409s instead of silently compounding). |
reason |
string |
Yes |
Why this rollback is happening (mandatory; an unexplained rollback of eligibility policy is itself an audit finding). |
target_revision |
integer |
Yes |
The snapshot revision to restore — resolved by the FULL
|
-
200: Rolled back (a replay returns the rule set as it now stands)
-
400: The snapshot’s content no longer compiles under the current engine
-
401: Unauthorized
-
403: Forbidden
-
404: Rule set (or an inactive one), or no snapshot at target_revision
-
409: The live revision moved since expected_revision (re-read and retry), or an ADR-062 idempotency conflict
-
422: Malformed body (including a missing client_request_id)
-
500: Internal error
-
503: Service Unavailable (RFC 9457 problem document, ADR-068): database pool exhaustion (carries Retry-After: 5), db-connection-lost, db-outcome-unknown, or a synchronous upstream dependency refusal.
-
504: Gateway Timeout (RFC 9457 problem document, ADR-068): the route-class request ceiling elapsed (request-timeout) or the database canceled the statement (db-timeout) — the server yields first.