Skip to main content

Every request, explained end to end.

Every operation page carries a panel that sends real fetch requests from the reader’s browser, measures their duration, and renders the response. This guide is the technical reference for that panel; the feature page makes the case, and Try-it & CORS covers why a correct request can still be blocked.

The form comes from the schema

Each declared type gets a matching field — and where no form makes sense, the raw JSON body stays the escape hatch:

Declared schemaField
Primitive (string, number, …)Text input
enum up to 7 values, booleanSelect
enum beyond 7 valuesFilterable combobox, free text still allowed
Array of primitivesRepeatable rows
prefixItems tuple (3.1)One fixed slot per position
Object with declared propertiesOne field per property
Free-form object (additionalProperties)Key + value rows
format: binaryFile input
Composite of objects (oneOf, …)Structured editor; a discriminated oneOf gets a variant selector

Fields stay text-typed even for numbers and dates, deliberately: a native number or date input would refuse a {{var}}, and a variable must remain typable everywhere. Values are coerced to their declared type at send time, and the placeholder shows the declared example when one exists. A discriminated oneOf body gets a variant selector: switching variants removes the other variant’s keys, and the discriminator property is filled in automatically, read-only.

The body’s kind follows the selected media type: JSON gets a text editor plus structured fields, multipart/* gets one field per property with file inputs for binary parts, urlencoded gets the same fields as text, a binary media type gets a file picker, and text-family types (XML included) get a text editor — an XML body starts pre-filled with a generated sample document. One deliberate degradation: a format: binary property under urlencoded becomes a text field, because percent-encoded form values cannot carry a file — you paste the encoded value instead.

Body validation is deliberately minimal: well-formed JSON plus the presence of top-level required fields, checked after {{var}} interpolation. The form helps you build the request; it never stands between you and sending an experiment.

One request, two editors

The request is editable from the central doc column and from the panel, and the two always show the same request — edit a field in either, the other follows. The media type is a single choice shared by both: since it decides which editor a body gets, two columns free to drift would document and edit two different bodies.

In a JSON body, a {{var}} may sit unquoted ("petId": {{petId}}), so the interpolated value lands as a number rather than a string. A missing variable blocks the send with a visible signal — the literal is never sent — and typing {{ autocompletes from the variables in scope, each with its provenance. Credentials follow their own conventions: see Auth & onboarding.

Serialization, the boring parts

style and explode are resolved with their spec defaults (form in query and cookie, simple in path and header) and applied on send: exploded query arrays repeat the pair (?tags=cat&tags=dog), non-exploded forms join on the style’s delimiter, deepObject brackets each property (?owner[city]=Lyon), and label/matrix path styles add their prefixes. Three declarations that change what leaves the browser get a visible badge in the doc:

  • allowReserved — reserved characters pass through unencoded; a space becomes %20, never +.
  • allowEmptyValue?verbose= is a value in itself, sent through an explicit toggle; a blank field still means “don’t send”.
  • in: cookie parameters — edited like any other, folded into one Cookie header. Browsers drop a Cookie header set by a script, and the panel says so under the fields; the header still reaches the cURL export and the snippets, which is usually why you wanted it.

Snippets in ten languages

Every request renders as a live snippet in cURL, fetch, Node, Python, PHP, Ruby, Java, C#, Go and HTTPie. The snippet follows what you type — it is the request that would actually be sent — and the selected language is remembered across operations.

Import: cURL, Postman, HAR

The import dialog (header toolbar) turns a request written elsewhere into a pre-filled try-it. It never sends and never writes anything on its own.

  • cURL — paste the command; the parser understands -X, -H, the -d/--data* family, --data-urlencode, -F, -u, --url, -G and attached short arguments (-XPOST). Unknown options are listed as ignored, never guessed at.
  • Postman Collection v2.1 — the folder tree is flattened, path variables are substituted, and raw/urlencoded/formdata/graphql bodies plus basic/bearer/apikey auth come through. Collection variables are reported, never turned into environments behind your back.
  • HAR — one entry per recorded request; recorded cookies are dropped, with a warning.

Format detection reads the content, not the file extension. Matching against the schema strips known server prefixes and scores operations by literal path segments matched; equal scores are an ambiguity the dialog presents rather than resolving silently, and anything unimportable is listed before you commit. A matched credential becomes the conventional auth.X variable in the session’s run scope — sensitive, redacted in history, and never written into your stored environments: a value pasted from someone else’s terminal is not yours to keep.

Export: four formats, redacted by default

Any request — from the panel or from history — exports as a copyable cURL command (multi-line, with a “substitute variables” toggle), a Postman v2.1 collection (which Insomnia imports natively), Markdown ready for a GitHub issue (request, response, environment, timing), or HAR 1.2. Sensitive values are redacted by default in every format, disableable explicitly. A per-request share link exists too: it re-templates sensitive values back into {{var}} before encoding, so a pasted link never carries a token.

One HAR detail worth knowing: httpVersion carries the protocol the transfer snapshot actually observed — http/1.1, h2, h3 — never a hardcoded guess. When the protocol cannot be known (a cross-origin response without Timing-Allow-Origin, an entry archived before the field existed), the HAR says nothing rather than something plausible.

History: replay, reload, bounded

Every sent request writes an IndexedDB entry: resolved request, response, duration, environment, and the list of sensitive values used — which is what makes redaction on display and export possible. The list filters by endpoint, environment, status and free text, and each entry offers two actions: replay as-is (send again, unchanged) and reload into the try-it (edit first). Above the response panel, a run selector lists past calls for the operation on screen; selecting one shows its archived response without re-sending anything.

The same history also feeds two read-only views in the doc itself: a recent-calls strip at the bottom of each operation page (time, status, duration, environment), and a most-used card on the overview, ranked by the reader’s own call counts — the two numbers a page with no backend can honestly show, since there is no telemetry to aggregate.

Retention is history.maxEntries (default 500) and history.maxAgeDays (default 30), whichever hits first, purged on write and stated in the dialog — silent eviction reads as data loss. Bodies beyond 256 KB are truncated with a visible flag. File uploads never reach storage at all: only the file’s name, size and type are kept, so replay is disabled on such an entry (re-sending would post a caption, not a file) while reload stays available — that is where you pick the file again.

When it fails, and when it succeeds

A failed send is diagnosed in the panel — offline, mixed content, CORS, or unreachable host, phrased as “most likely” because the browser hides the details from the page. A successful response gets its headers read back to you: rate limits, Retry-After, Deprecation and Sunset, Link pagination, ETag and Last-Modified validators, correlation ids, plus protocol, compression and cache facts.

Two of those insights are buttons, not just labels: a Link header with next/prev relations gets a follow button that loads the neighboring page into the try-it, and a response carrying validators gets a conditional replay — the same request re-sent with If-None-Match/If-Modified-Since, expecting a 304 (GET and HEAD only).

Cross-origin, two response headers unlock the full material: Access-Control-Expose-Headers (without it the browser reveals only a safelist, and the panel says the list may be incomplete) and Timing-Allow-Origin (without it transfer sizes read zero and the compression and cache chips stay hidden). Both are covered in Try-it & CORS.

Two details worth knowing

  • An in-flight request is cancelable. A Cancel control sits next to Send while one is out; an abort is announced as information, not rendered as a network failure, and writes no history entry.
  • The most specific server wins. An operation that declares its own servers keeps it; an environment’s base URL replaces the root server only. The base URL displayed is the one the send will hit.