Validation
Validate params, query, body, headers, and the response, failing fast before the request when input is wrong.
Use validation when you want a stitch to reject bad input before it leaves the process and to verify the response once it arrives — input is checked before the request, so wrong params, query, body, or headers fail fast with no network call.
Example
import { } from 'stitchapi';
import { } from 'zod';
const = <{ : number; : string }>({
: 'POST',
: 'https://api.example.com',
: '/users',
: { : .({ : .() }) },
: .({ : .(), : .() }),
});A bad body rejects before the POST is sent; a response that doesn't match
output rejects after. Either way the stitch throws
STITCH_VALIDATION, and the stitch<T> generic
keeps the resolved value typed as { id: number; name: string }.
Options
input is a map of { params, query, body, headers }, each an optional
Validator. Every entry present is validated against the call input before
the request — the fail-fast guarantee — so the request never goes out with input
the API would reject.
A declared slot also shapes the request: the request is built from the value
the schema returned, so whatever it coerces, defaults or strips is what goes on
the wire. A z.object(...) strips unknown keys by default, so an extra key a
caller tacked onto a declared slot never reaches the API — which matters most
when the caller is untrusted, such as a model calling through
the MCP surface.
A schema that transforms therefore reshapes the request. This is how a stitch maps your field names onto the API's — the call argument is typed from the schema's input side, so callers keep the house shape while the wire gets the API's. See Reshaping the request.
A schema constrains one slot. An undeclared slot stays a full
passthrough, so declaring params does nothing about query. And a query
pair written into the endpoint (?tenant=acme) is a default that
input.query overrides — declare the slot if callers must not move it.
output is a single Validator that checks the response body after it returns.
(Pass a drift() spec here instead to report changes without throwing — see
Schema drift detection.)
Anti-pattern: don't reach for a strict output validator to catch
upstream API changes — an additive, non-breaking change to the response then
throws STITCH_VALIDATION and breaks the call. Pass a drift() spec to
output instead, so changes are reported without failing the request. See
Schema drift detection.
input and output accept the schema directly — a raw z.object(...), any
Standard Schema validator (Valibot,
ArkType), or a plain predicate. Each slot's type accepts the schema as written,
and the engine adapts it internally, so there's no cast at the call site.
See Reference → Config types for every field on
input and output.