Skip to content

Built on the standards

HTTP already has answers to the hard questions an API client faces: which requests are safe to send twice, how long to wait when a server says "slow down", what an error body looks like, where the next page is. They are written down in RFCs. headgate reads them so you do not have to, and follows them by default.

  • 17 specifications


    IETF RFCs and drafts, the WHATWG event-stream format and Python's own PEP 750, each tied to the behavior it drives.

  • Polite by default


    Retry-After waited exactly, rate-limit headers obeyed, Idempotency-Key sent on writes. Providers see a well-behaved client.

  • Strict where it matters


    A malformed header is ignored, as each spec asks, rather than guessed at. Nothing unsafe is retried.

  • Honest about exceptions


    The one place headgate chooses differently, the cache, is spelled out with the reason.

You do not need to know any of this to use headgate

Every row below is something headgate does for you. The page is here for the curious, for reviewers, and for anyone who has to justify a dependency.

Sending and retrying safely

Standard What it says What headgate does
RFC 9110 §9.2.2 Idempotent methods GET, HEAD, OPTIONS, PUT and DELETE can be repeated without extra effect only these are retried after an ambiguous failure, and only these can be hedged
Idempotency-Key (IETF draft) a client key lets a server recognize a re-sent POST or PATCH IdempotencyKeys() stamps one key per call, so every retry carries the same one
RFC 8470 425 Too Early the server did not process the request retried for every method, POST included, since nothing happened
RFC 9113 §8.7 HTTP/2 REFUSED_STREAM the server refused the stream before doing any work retried for every method, for the same reason
RFC 9110 §15.4 Redirects 303 becomes GET; 307 and 308 keep the method and body followed as written, except a 307 or 308 that would re-send a one-shot body and any https-to-http hop

Waiting when asked

Standard What it says What headgate does
RFC 9110 §10.2.3 Retry-After how long to wait before trying again, in seconds or as a date waited exactly on a 429 or 503, up to a cap; past it the call fails at once and tells you when to come back
RFC 6585 §4 429 Too Many Requests the client is over its rate limit raised as RateLimitError, and pauses the shared budget so other calls stop too
RateLimit headers (IETF draft) RateLimit and RateLimit-Policy say how much quota is left and when it returns an exhausted quota pauses the rate budget until it returns; other quota units are skipped
RFC 9651 Structured Field Values the syntax the RateLimit headers are written in parsed with the RFC's own limits; a malformed field is ignored, as the draft asks

Reading responses

Standard What it says What headgate does
RFC 9457 Problem Details errors as application/problem+json with type, title, detail parsed into exc.problem; the message shows its title and detail instead of raw JSON
RFC 6839 Structured syntax suffixes application/problem+json is a kind of JSON an Expect(accept="application/json") accepts it
RFC 9110 §13.1 Conditional requests If-None-Match and If-Modified-Since let a server answer 304 Not Modified conditional() sends them and returns Fresh or NotModified
WHATWG Server-sent events the text/event-stream format and Last-Event-ID resumption aiter_events() parses events as they arrive; last_event_id= resumes
RFC 9745 Deprecation and RFC 8594 Sunset an endpoint announces it is deprecated or going away a Deprecated event with the dates and links, once per call
Standard What it says What headgate does
RFC 8288 Web Linking Link: <...>; rel="next" names the next page LinkHeader follows it; the parser handles quoted commas and repeated parameters as the RFC says
RFC 6454 Origins an origin is a scheme, host and port credentials are pinned to an origin, circuit breakers are kept per origin

Addresses and paths

Standard What it says What headgate does
RFC 6052 NAT64 64:ff9b::/96 carries an IPv4 address inside IPv6 the SSRF guard judges such an address by the IPv4 address it reaches
PEP 750 Template strings Python 3.14's t"..." keeps values apart from the template each value in a path is percent-encoded as exactly one segment

Caching: where headgate chooses differently

RFC 9111 says what a shared HTTP cache may store, based on headers such as Cache-Control. headgate's cache is hishel's, which implements RFC 9111, but headgate configures it with your rules (which paths, methods and statuses, for how long) instead of the provider's headers. That is on purpose: many APIs send no cache headers, or no-store on data that is safe to keep for an hour. When you want the origin to decide, use conditional reads, which follow RFC 9110 to the letter.

Widely used conventions

Not every useful convention is an RFC. headgate understands the common ones too.

Header Where it comes from What headgate does
retry-after-ms SDKs generated by Stainless, such as OpenAI's a millisecond Retry-After; preferred when both are sent
x-should-retry the same SDKs the server's own word on whether a re-send is safe, followed by default
X-RateLimit-Remaining, X-RateLimit-Reset GitHub, and many others read when RateLimit is absent; the reset may be seconds or a Unix time
x-request-id, request-id, x-amzn-requestid, x-ms-request-id, cf-ray most platforms read into every error's request_id, for support tickets