Body encoding
Send request bodies as json, form, or multipart.
Set wire.body when an API expects a request body in a particular wire format —
JSON, URL-encoded form, or multipart form data — and you want the stitch to
serialize the body you pass at call time into that shape.
Example
import { } from 'stitchapi';
const = ({
: 'POST',
: 'https://api.example.com',
: '/submit',
: { : 'form' },
});
await ({ : { : 'mango', : 3 } });The body travels in the call input, not the config: submit encodes
{ name: 'mango', qty: 3 } as an application/x-www-form-urlencoded body
because wire.body is 'form'.
Options
wire.body chooses how the call-time body is encoded (default 'json'):
-
json— a JSON body withContent-Type: application/json. The default; reach for it for ordinary REST payloads. -
form— a URL-encodedapplication/x-www-form-urlencodedbody, for APIs that expect classic HTML-form fields (login forms, OAuth token exchanges). Nested objects and arrays serialize exactly as they do in a query string — same walker, samewire.array:await submit({ body: { ids: [1, 2], page: { size: 10 } } }); // → ids%5B0%5D=1&ids%5B1%5D=2&page%5Bsize%5D=10 -
multipart— multipart form data, for file uploads and mixed field-plus-binary payloads; the boundary is set for you. Nested objects/arrays serialize with bracket nesting by default;multipart: 'dot'(≡multipart: { nesting: 'dot' }) switches to dot-path field names. Multipart has its own grammar, sowire.arraydoes not apply to it — andmultipartmay only be set alongsidewire: { body: 'multipart' }, since the slot is ignored on any other body. Note this is multipart encoding of one request, a different thing from S3-style multipart upload — a four-step protocol whose last step, aborting on failure, no HTTP client models for you; the upload you must clean up after covers what the orphaned parts cost when you skip it.
Body encoding is not a surface — it composes with one. wire.body says
how the request payload is framed; a surface
says what kind of interaction the call is (REST, GraphQL, SSE, a stream, a
download). The two are separate axes, so they are separate fields.
The body itself always comes from the call input (await submit({ body })),
never from the config — so one stitch encodes whatever you pass it. See
Guide → stitch() for the full configuration.
wire.body is an http-surface option. The graphql surface builds its
own body — a JSON { query, variables } envelope — so setting wire.body
alongside it is a compile error rather than a silently ignored field. GraphQL
file uploads are a separate wire format (the GraphQL multipart request
spec's
operations/map/file-part envelope), not this JSON body re-encoded as
multipart, and are not supported today. To upload alongside a GraphQL
API, POST the file to a plain http stitch and pass the resulting handle as
a variable. See Request surfaces.
The same applies to llm, which POSTs a provider-shaped JSON body: method
and wire.body are both compile errors on an llm() config. The rest of the
envelope is untouched — wire.response and wire.array are knobs the surface
leaves alone, so they still work.
Anti-pattern: don't hand-serialize the body before you pass it —
stringifying the value yourself and handing the stitch a pre-encoded string
double-encodes it, because wire.body already serializes the value into the
wire format you chose; pass the plain object and let the stitch encode it
once. See stitch().