Skip to main content
GET /rulesets/{ruleset_id}/graph (and the composed GET /rulebooks/{rulebook_id}/graph) return the ruleset as a graph: every field, every compiled criterion, the groups they roll up into, and how those groups combine into the outcome. It’s the same compiled logic /schema and /explain describe, laid out as nodes and edges instead of a flat field list — useful for rendering a visual map, for an agent that wants to reason about rule structure programmatically, or for spot-checking that a generated ruleset compiled the shape you expected. Public rulesets are accessible without an API key, the same as /decide and /schema — see Do you even need a key?.

Request

URL-encode the slug’s / as %2F (or pass the concrete dated ruleset_id from a /decide envelope — either resolves, same as /schema and /explain).

Response shape

  • graph.nodes — one entry per field, criterion, group, and a single terminal outcome node. node.type is one of field, criterion, group, outcome.
  • graph.edges — directed {source, target, type} triples: field_to_criterion, criterion_to_group, group_to_outcome. Follow them to render your own layout instead of Mermaid.
  • graph.stats — a quick summary (field/criterion/group counts, section count). shared_fields is nonzero only on a composed rulebook graph where two sections reference the same field.
  • mermaid — a ready-to-render Mermaid flowchart string covering the same graph. Paste it into any Mermaid renderer, or embed it directly if your docs/UI already renders Mermaid.

Criterion nodes: the three altitudes

Each criterion node carries a display object with the same underlying compiled expression shown three ways, so a caller can pick the altitude it needs:

The empty/legacy case: display.routes can be null

display.routes is a best-effort structural rendering built from the same expression as sentence and expr. If a criterion’s compiled expression is shaped in a way the route-tree builder doesn’t yet cover, the server catches that internally and returns routes: null for that node — sentence and expr are always populated (they come from the same code path that already backs /explain), so a caller can always fall back to sentence for display and expr for exact logic, even when routes is absent. Never assume routes is present; branch on it being null the same way you’d branch on any optional field.

overlay — decision-time status (include_graph_overlay)

By default every node’s overlay is null — the graph above is pure structure, independent of any particular decision. Pass include_graph_overlay: true on /decide to get the same graph back with each node’s overlay stamped with that decision’s outcome, so you can render a map that’s colored by what actually happened:
The response’s graph_overlay field is the same {nodes, edges, sections, stats} shape as above, but each criterion’s overlay (and display.routes.overlay) is now {"status": "satisfied", "supporting_facts": [...]} (or not_satisfied / pending) instead of null:
See Debug a failing decide for a worked example using the overlay to spot which criterion failed.

Rulebook graphs (composed)

GET /rulebooks/{rulebook_id}/graph (path forms: /rulebooks/{rulebook_id}/graph and /rulebooks/{namespace}/{name}/graph) returns the same {nodes, edges, sections, stats} IR, merged across every ruleset the rulebook composes — graph.sections lists each member section, and stats.shared_fields counts fields two or more sections reference in common. Unlike ruleset-level /graph, rulebook endpoints are not anonymous — they need an API key (the same rule as rulebook_id on /decide; see Do you even need a key? and missing_api_key).

Rendering the Mermaid string

The mermaid field is plain text — feed it straight into any Mermaid-compatible renderer:
The node IDs above are shortened for readability — the live response prefixes them with the full section slug (e.g. group_aethis/uk-fsm/child-eligibility_school_type_check) so a composed rulebook graph never collides node IDs across sections.
Solid arrows (-->, ==>) trace the compiled decision path; dotted arrows (-.->) trace which fields feed which criteria. A criterion shared by two or more sections in a composed rulebook graph is styled with the shared class (gold fill) so it’s visually obvious which parts of the map are doing double duty.

See also

  • Debug a failing decide — using include_graph_overlay and include_trace together to pinpoint a failing criterion.
  • Decision envelope — the full /decide response contract.
  • Errors referencemissing_api_key and other failure shapes you’ll hit calling the rulebook-level endpoints anonymously.