Release candidate — 1.0.0-rc.7
StitchAPI
GuidesData shaping

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 with Content-Type: application/json. The default; reach for it for ordinary REST payloads.

  • form — a URL-encoded application/x-www-form-urlencoded body, 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, same wire.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, so wire.array does not apply to it — and multipart may only be set alongside wire: { 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().

See also

On this page