Get a Spec
Read a Spec's structure: its stages in authoring order and in compiled execution order, each with the live IDs it points at, plus the Spec-field to schema-field mapping.
Returns the Spec's identity, version state, and structure. Structure and IDs only — no rules, gate configuration, prompts, samples, or ground truth.
Two stage lists, and they differ on purpose
The response carries the stages twice, because "the stages of a Spec" has two legitimate answers and collapsing them would misrepresent one of the two.
nodes— the rail as authored, in editing order. Includes stages that do not execute on their own, such as Source and Data Product.phases— the compiled execution plan, in run order. Source and Data Product produce no phase; a validation checkpoint expands to one phase per member gate. So this list is often a different length fromnodes.
rail_stage_id on a phase is the join key back to nodes[].node_id. It is also the per-step cost-attribution key, so a phase here lines up with its spend on GET /v1/usage/pipelines/{id}.
phases describes what a new run would execute, compiled from the current rail. To see what a specific run actually executed, read its frozen plan with GET /v1/pipelines/{id}?include=phases — same shape, same join key. Comparing the two shows configuration drift since that run./v1/specs/{id}Path parameters
Get a Spec
curl -H "Authorization: Bearer $TALONIC_API_KEY" \
"https://api.talonic.com/v1/specs/e2144027-39c0-44e8-a196-72be1e360749"Response
Structure fields
Response (abridged)
{
"id": "e2144027-39c0-44e8-a196-72be1e360749",
"name": "Order Intake V25",
"schema_id": "2e3ddf8c-b9ab-4934-bb11-a371e9c5d7a8",
"version": 3,
"materialized_version": 3,
"schema": { "id": "2e3ddf8c-b9ab-4934-bb11-a371e9c5d7a8", "name": "Order Intake V25" },
"nodes": [
{ "node_id": "s-source", "position": 0, "type": "source", "name": "Source" },
{ "node_id": "s-schema", "position": 1, "type": "schema", "name": "Extraction",
"schema_id": "2e3ddf8c-b9ab-4934-bb11-a371e9c5d7a8" },
{ "node_id": "res-1", "position": 2, "type": "resolve", "name": "Resolution",
"policy_ids": ["fadfb451-7c2e-4849-a6f1-1f5d20116336"] },
{ "node_id": "rec-1", "position": 3, "type": "reconcile", "name": "Matching",
"matcher_stage_id": "d055b6f8-b324-4bc2-98ef-048e893ba762" },
{ "node_id": "s-deliver", "position": 4, "type": "deliver", "name": "Data Product" }
],
"phases": [
{ "number": 1, "phase_id": "phase-1", "type": "extraction", "name": "Extraction",
"rail_stage_id": "s-schema" },
{ "number": 2, "phase_id": "phase-2", "type": "resolution", "name": "Resolution",
"rail_stage_id": "res-1", "policy_id": "fadfb451-7c2e-4849-a6f1-1f5d20116336" },
{ "number": 3, "phase_id": "phase-3", "type": "matching", "name": "Matching",
"rail_stage_id": "rec-1", "matcher_stage_id": "d055b6f8-b324-4bc2-98ef-048e893ba762" }
],
"fields": [
{ "field_id": "c086cb2d-06bf-4c22-9007-c6e455531133",
"user_schema_field_id": "a3952c40-9f78-41a3-975f-57c5c79c3fae",
"name": "shipper_number", "type": "string" }
]
}Note that the five rail nodes compiled to three phases: Source and Data Product mark composition, they do not execute as phases of their own.
The field mapping
Every field in a Spec carries a field_id that is minted once and never changes, even when the field is renamed. Everything inside the Spec references that ID rather than the name: switch-lane conditions, assembly anchors, gate scopes, ground-truth keys, rule bindings. The values themselves live on a schema field row with its own ID.
fields pairs the two, which is what lets you resolve a Spec-level reference to actual extracted data. That pairing is not available on any other endpoint.
Errors
Error responses
schema: null with empty nodes, phases, and fields. That is a valid read, not an error.