Skip to content

Chain

A chain is a graph of steps where later steps use values produced by earlier ones. Call the login endpoint, extract the token, call the real endpoint with it. Create a customer, extract the id, create an order for it.

This is the headline feature, so extraction and variable-passing are first-class rather than bolted on.

Chains are workspace-level, not part of a collection: one YAML file per chain under .tinspec/chains/, with their own formatVersion: 3. They are committed like everything else.

A chain can reference requests from any collection in the project, or carry its own inline copy of a request.

Sixteen node kinds in four groups:

  • Requestrequest. Either a reference to a saved request (collection + name) or an editable inline copy with its own auth and body.
  • Datainput, environment, math, transform, generator, set, aggregate.
  • Control flowcondition, router, loop, merge, split, delay.
  • Logicscript (JavaScript in the engine’s sandboxed runtime) and assert (validate status, body, header, or a variable; routes to a pass or fail branch).

Edges connect nodes. A condition has true/false handles, a router one handle per rule (first match wins), a loop a body and a done handle.

Click a field in a request node’s JSON response and Tinspec creates an extraction — a named variable downstream nodes can use as {{name}}.

extract:
- var: userId
from: body
path: data.id
- var: requestId
from: header
path: x-request-id

from is body (with a dotted path), header (with the header name as path), or status.

  • Steps renders a linear chain as an ordered list of editable cards — URL, headers and body in place for inline requests, outputs, reorder, run to here, test this step. Fan-out branches show as “run together” groups.
  • Graph is the full canvas, built on Svelte Flow, for anything genuinely branching.

It is one chain in both views; the toggle is a rendering choice.

Run the whole chain, run to here, or test a single node. Events stream live: each node shows a status ring (running / done / skipped / error), the activated branch animates, pruned branches fade, and a dock at the bottom tabs between an event log and the current variables.

Final results come back as a snapshot too, including which nodes were skipped or pruned and which assertion failed.

Chains are validated as you author them — missing request references, variables consumed but never produced, extraction paths that do not exist in the spec’s documented 2xx response, non-chainable protocols, dangling edges. Problems show on the step, and errors disable Run.

A chain step expects exactly one response per request, so only single-shot protocols qualify: HTTP, GraphQL, and unary gRPC.

WebSocket sessions, streaming gRPC methods, and LangGraph runs are multi-message and are not chainable. The request picker shows them disabled with a tooltip, and the engine refuses them at run time rather than failing halfway.

A request can name a chain as its pre-run chain. The chain runs first, its output variables merge into the environment, and then the request is sent — so “authenticate, then call” is one press of ⌘↵ with no manual step.

Chains inherit the shared cookie jar automatically, so a login that sets a session cookie is followed by calls that carry it, with nothing to configure.

For an endpoint whose request body requires ids you do not have, Build prerequisites… plans the chain for you: it reads the spec for required *Id body fields and path parameters, finds the POST that produces each one by matching resource stems, recurses, and groups independent steps to run together. It prefers to reference your existing saved requests and generates a step only where none matches.

You get a preview of the steps and the reasoning before anything is created.

See Build a chain for the walkthrough.