Skip to main content

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 from nodes.

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.
GET/v1/specs/{id}

Path parameters

id*stringSpec UUID — the ID in the `/specs/{id}` editor URL, not the schema ID.

Get a Spec

curl -H "Authorization: Bearer $TALONIC_API_KEY" \
  "https://api.talonic.com/v1/specs/e2144027-39c0-44e8-a196-72be1e360749"

Response

Structure fields

schemaobject | nullThe materialized schema: id and name. Null before first publish.
nodes[].node_idstring | nullStage ID within the Spec. Null on a legacy rail that keyed stages by position.
nodes[].positioninteger0-based index in the rail.
nodes[].typestringsource, registry, schema, resolve, valid, assembly, deliver, reconcile, sanitize, triage, switch.
nodes[].policy_idsarray | undefinedData policy IDs — resolve stages.
nodes[].validation_stage_idsarray | undefinedValidation stage IDs — the gates a checkpoint contains.
nodes[].matcher_stage_idstring | undefinedMatcher stage ID — reconcile stages.
nodes[].source_pipeline_idstring | undefinedUpstream run, when the Source stage injects from a pipeline.
phases[].numberinteger1-based execution order.
phases[].rail_stage_idstring | nullThe rail stage this phase compiled from. Join key to nodes[].node_id.
phases[].policy_idstring | undefinedResolution phases.
phases[].validation_stage_idstring | undefinedValidation phases — one per gate.
phases[].matcher_stage_idstring | undefinedMatching phases.
fields[].field_idstringThe Spec document's immutable field identity.
fields[].user_schema_field_idstringThe schema field row that holds the extracted values.

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

400validation_errorThe ID is not a UUID.
401unauthorizedMissing or invalid API key.
404not_foundNo Spec with this ID exists for your organization. If you passed a schema ID, use GET /v1/schemas/{id} and read its spec_id.
429rate_limitedToo many requests. Retry after the period indicated in the Retry-After header.
A Spec that has never been published returns schema: null with empty nodes, phases, and fields. That is a valid read, not an error.