Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Projects & artifacts

Decisions and workflows are both artifacts — same storage shape, same CRUD surface, distinguished by kind. Every route below is tenant-scoped (403 with no tenant claim) and grouped under a project path segment, which is just a label within the tenant (see Tenancy).

Artifact shape

{
  "id": "art_9f2c...",
  "tenant": "acme",
  "project": "lending",
  "kind": "decision",
  "name": "loan_risk",
  "model": { "...": "the decision or workflow JSON" }
}

Decisions

Method & pathDescription
POST /projects/{project}/decisionsCreate. Body: { "name": "...", "model": { ... } }
GET /projects/{project}/decisionsList all decisions in the project
GET /projects/{project}/decisions/{artifactId}Get one
PUT /projects/{project}/decisions/{artifactId}Replace name + model in place
DELETE /projects/{project}/decisions/{artifactId}Delete; audited as decision.deleted
POST /projects/{project}/decisions/{artifactId}/simulateRun the saved decision against a body of raw inputs
curl -sS -X POST "$RULEFLOW_API/api/projects/lending/decisions" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{ "name": "loan_risk", "model": { "id": "loan_risk", "inputs": [...], "outputs": [...], "nodes": [...] } }'
{ "id": "art_9f2c...", "tenant": "acme", "project": "lending", "kind": "decision", "name": "loan_risk", "model": { "...": "..." } }

Simulate takes the raw input object as the body (not wrapped):

curl -sS -X POST "$RULEFLOW_API/api/projects/lending/decisions/art_9f2c.../simulate" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{ "credit_score": 780, "debt_to_income": 0.2 }'

A successful simulate (2xx from the engine) records one decision_simulation unit of metered usage — see Usage & quotas.

Workflows

Method & pathDescription
POST /projects/{project}/workflowsCreate. Body: { "name": "...", "model": { ... } }
GET /projects/{project}/workflowsList
PUT /projects/{project}/workflows/{artifactId}Replace in place
DELETE /projects/{project}/workflows/{artifactId}Delete; audited as workflow.deleted
POST /projects/{project}/workflows/{artifactId}/compileCompile the saved workflow to ASL (read-only, not persisted)

There is no GET .../workflows/{artifactId} single-item route — list and filter client-side, or track ids from create/list responses.

Ad-hoc engine operations

Not persisted; useful while authoring before you save anything:

Method & pathForwards to
POST /engine/validate/v1/validate
POST /engine/simulate/v1/simulate
POST /engine/compile-workflow/v1/compile-workflow
POST /engine/diff/v1/diff

These relay the request body verbatim to the engine service and return its response verbatim (status code included) — a 503 means no engine is configured for this deployment.

Storage quota

If the deployment enforces MaxArtifactBytesPerTenant, POST (create only — not update) checks the tenant’s total stored artifact bytes before writing and returns 429 if the new artifact would exceed it:

{ "error": "artifact storage quota exceeded (max 5000000 bytes per tenant)" }

Audit

Audit entries are recorded on writes (deletes explicitly; create/update audit entries are recorded by the release/deploy flows, not per-artifact edit). Read them tenant- or project-scoped:

Method & pathDescription
GET /projects/{project}/auditThis project’s audit entries
GET /audit?project=&action=&actor=&from=&to=&limit=Tenant-wide, filterable (project omitted spans every project)
GET /audit/summaryAggregate counts (by action, actor, day) over the same filters
{ "id": "aud_1a2b...", "tenant": "acme", "project": "lending", "action": "release.created", "actor": "alice@acme.com", "detail": "v1 (3 item(s))" }