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 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. Where no form makes sense, the raw JSON body is the escape hatch.
| Declared schema | Field |
|---|---|
| Primitive (string, number, …) | Text input |
enum up to 7 values (a oneOf of constants counts as one), boolean | Select |
enum beyond 7 values | Filterable combobox, free text still allowed |
| Array of primitives | Repeatable rows |
prefixItems tuple (3.1) | One fixed slot per position |
| Object with declared properties | One field per property |
Free-form object (additionalProperties) | Key + value rows |
format: binary | File input |
Composite of objects (oneOf, …) | Structured editor; a discriminated oneOf gets a variant selector |
Fields stay text-typed even for numbers and dates. A native number or date input would refuse a {{var}}, and a variable has to remain typable everywhere. Values are coerced to their declared type at send time, and the placeholder shows the declared example when one exists.
In a discriminated oneOf body, switching variants removes the other variant’s keys, and the discriminator property is filled in automatically and left 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.
- Text-family types, XML included, get a text editor. An XML body starts pre-filled with a generated sample document.
One degradation to know: a format: binary property under urlencoded becomes a text field, because percent-encoded form values cannot carry a file. Paste the encoded value instead.
Body validation is minimal on purpose: well-formed JSON, plus the presence of top-level required fields, checked after {{var}} interpolation. The form helps you build the request rather than gate it.
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, and the other follows.
The media type is a single choice shared by both, since it decides which editor the body gets.
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, and the literal is never sent. Typing {{ autocompletes from the variables in scope, each with its provenance. Credentials follow their own conventions — see Auth & onboarding.
Parameter serialization
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 change what leaves the browser, and each gets 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: cookieparameters — edited like any other, folded into oneCookieheader. Browsers drop aCookieheader 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 the point.
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, so it is the request that would actually be sent. The selected language is remembered across operations.
Import: cURL, Postman, HAR
The import dialog, in the 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,-Gand attached short arguments (-XPOST). Unknown options are listed as ignored rather than guessed at. - Postman Collection v2.1 — the folder tree is flattened, path variables are substituted, and
raw/urlencoded/formdata/graphqlbodies plusbasic/bearer/apikeyauth come through. Collection variables are reported rather than turned into environments. - 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 presented as an ambiguity for you to resolve, 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.
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
- HAR 1.2
Sensitive values are redacted by default in every format, and can be included explicitly. A secret carried in the URL is masked even when URL encoding changes it — a base64 API key reads %2B, %2F and %3D there. A per-request share link exists too: it re-templates sensitive values back into {{var}} before encoding, so a pasted link carries no token.
One HAR detail: httpVersion carries the protocol the transfer snapshot actually observed — http/1.1, h2, h3 — never a hardcoded guess. When the protocol cannot be known, such as a cross-origin response without Timing-Allow-Origin or an entry archived before the field existed, the field is left empty.
History: replay, reload, bounded
Every sent request writes an IndexedDB entry: the resolved request, the response, the duration, the 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. Each entry offers two actions: replay as-is, which sends again unchanged, and reload into the try-it, which lets you 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.
The same history 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.
Retention is history.maxEntries (default 500) and history.maxAgeDays (default 30), whichever is reached first, purged on write and stated in the dialog. Bodies beyond 256 KB are truncated with a visible flag.
File uploads never reach storage: only the file’s name, size and type are kept. Replay is therefore disabled on such an entry, 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. The diagnosis is 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 rather than labels. A Link header with next/prev relations gets a follow button that loads the neighbouring page into the try-it. 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. Without Access-Control-Expose-Headers the browser reveals only a safelist, and the panel says the list may be incomplete. Without Timing-Allow-Origin transfer sizes read zero and the compression and cache chips stay hidden. Both are covered in Try-it & CORS.
What the browser refuses to send is named rather than failing in silence. A header no page may set — Origin, Content-Length, any Sec- header, the full list of the Fetch standard — is named under the headers as soon as the request carries it, and a TRACE operation says browsers refuse the method. A body the document declares on a GET or HEAD is shown with a note and left out of the send. All of it stays in the cURL command, which is how you send it. A request to http://localhost or 127.0.0.1 is never called mixed content: browsers allow those from an https page.
Three 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 rather than as a network failure, and writes no history entry.
- Server variables are filled in.
https://{region}.api.example.comsends to the variable’s default rather than to a literal{region}, and an environment created from that server keeps{{region}}as one of its variables — change it once and every request moves. - The most specific server wins. An operation that declares its own
serverskeeps it; an environment’s base URL replaces the root server only. The base URL displayed is the one the send will hit.