Conditional requests
Catalog and market data reads carry an ETag. Send it back in If-None-Match and, while the data hasn’t changed, the API answers
304 Not Modified with no body, so polling an unchanged resource costs no transfer and no decoding.
GET /v1/events/4102/metricsAuthorization: Bearer tx_live_…
HTTP/1.1 200 OKETag: W/"q2Jx0kVd3H9cS8hT1mNw4A"Cache-Control: private, no-cache
GET /v1/events/4102/metricsIf-None-Match: W/"q2Jx0kVd3H9cS8hT1mNw4A"
HTTP/1.1 304 Not ModifiedETag: W/"q2Jx0kVd3H9cS8hT1mNw4A"- The
ETagof these reads is weak: a hash of the JSON body, so it differs per plan, filter and query. Keep one per request URL. If-None-Matchmay list several ETags, comma-separated, or*; tags compare weakly (aW/prefix is ignored).- A
304carries the currentETagand the rate limit headers. It still counts as a request against your quota. - The seat map overlay (
GET /v1/events/{id}/map/overlay) has a strong ETag that changes with the seat map, the snapshot and the pricing. Seat map artifacts (GET /v1/seatmaps/{hash}) are immutable: their strong ETag is the artifact’s hash. - Browsers revalidate on their own (
Cache-Control: private, no-cache); you only sendIf-None-Matchyourself from servers and scripts.
Endpoints
Section titled “Endpoints”If-None-Match is accepted by:
| Area | Endpoints |
|---|---|
| Catalog | GET /v1/events, /v1/events/{id}, /v1/regions, /v1/catalog/facets, /v1/search, /v1/attractions/{id}, /v1/attractions/{id}/events, /v1/venues/{id}, /v1/venues/{id}/events, /v1/calendar/days, /v1/calendar/items |
| Market data | GET /v1/events/{id}/metrics, /v1/events/{id}/series, /v1/events/{id}/sales, /v1/events/{id}/listings, /v1/events/{id}/listings/changes, /v1/events/{id}/inventory/changes, /v1/sales/feed, /v1/sales/summary, /v1/movers, /v1/compare/series |
| Seat maps | GET /v1/events/{id}/map, /v1/events/{id}/map/overlay, /v1/seatmaps/{hash} |
The API reference lists the If-None-Match parameter and the 304 response on each of them.
In the SDKs
Section titled “In the SDKs”Both SDKs expose the ETag of every response and accept ifNoneMatch (TypeScript) / if_none_match (Python) on the operations above.
A 304 is not an error: the call returns a NotModified value carrying the current etag, headers and rate limit state, and the result
type says so only when you pass the option.
import { NotModified, Status302 } from "@status302/sdk";
const status302 = new Status302({ apiKey: process.env.STATUS302_API_KEY });
const first = await status302.request("get", "/v1/events/{id}/metrics", { path: { id: 4102 } });// first.data: the metrics; first.etag: 'W/"q2Jx0kVd3H9cS8hT1mNw4A"'
const next = await status302.get("/v1/events/{id}/metrics", { path: { id: 4102 }, ifNoneMatch: first.etag });if (next instanceof NotModified) console.log("unchanged");else console.log("new metrics", next.items);import os
from status302 import NotModified, Status302
with Status302(api_key=os.environ["STATUS302_API_KEY"]) as status302: first = status302.with_response.get_event_metrics(4102) # APIResponse: .data, .etag, .status, … nxt = status302.get_event_metrics(4102, if_none_match=first.etag) if isinstance(nxt, NotModified): print("unchanged") else: print("new metrics", nxt["items"])ETag cache
Section titled “ETag cache”To revalidate without tracking ETags yourself, give the client an ETag cache. Every GET whose response carried an ETag is stored by
URL; the next GET of that URL sends If-None-Match, and on 304 the client returns the stored body as if it had been sent again
(status is 304 on the full response). Calls that pass their own ifNoneMatch / if_none_match bypass the cache.
import { MemoryETagCache, Status302 } from "@status302/sdk";
const status302 = new Status302({ apiKey: process.env.STATUS302_API_KEY, etagCache: new MemoryETagCache(1000) });import os
from status302 import MemoryETagCache, Status302
status302 = Status302(api_key=os.environ["STATUS302_API_KEY"], etag_cache=MemoryETagCache(1000))MemoryETagCache keeps the most recently used entries (1000 by default) in memory. Entries never go stale: an ETag identifies its body, so
a 304 proves the stored copy is current. To share a cache between processes, implement the ETagCache interface (get and set of
a CachedResponse by key; async methods are fine in TypeScript) over your own store.
© 2026 status403 Sp. z o.o.Aleja Solidarności 68/121, 00-240 Warsaw, PolandKRS 0001269943NIP 5253108931Share capital PLN 5,000.00
Registry court: District Court for the Capital City of Warsaw, 12th Commercial Division

