HTTP Caching (ETags)
The API supports standard HTTP conditional request headers. If you're polling endpoints or building anything that checks data repeatedly, ETags let you skip the download entirely when nothing has changed.
How ETags Work
Every successful response includes an ETag header — a fingerprint of the response data. On your next request, send that fingerprint back. If the data is unchanged, the server replies with 304 Not Modified and an empty body. You use your cached copy and save the bandwidth.
First request: GET /v2/stats → 200 OK + ETag: "a1b2c3d4e5f6"
Second request: GET /v2/stats + If-None-Match: "a1b2c3d4e5f6"
→ 304 Not Modified (data unchanged — use your copy)
→ 200 OK + new ETag (data changed — read the new body)
Best candidates for ETag polling.
/v2/stats, /v2/versions, and /v2/roadmap/* change infrequently — ETags are especially valuable here. If you poll more often than the refresh interval for that endpoint, 304 responses tell you nothing has changed without spending quota.
If-None-Match
The most common pattern. Send the ETag from a previous response; get a 304 if nothing changed, or a fresh 200 with new data if it has.
GET /v2/users/dymerz HTTP/1.1
Host: API_HOST
x-api-key: YOUR_API_KEY
If-None-Match: "a1b2c3d4e5f6"
| Response | What it means | Action |
|---|---|---|
304 Not Modified | Data unchanged | Use your cached copy — no body to parse |
200 OK | Data changed | Read the new body, store the new ETag |
Store the ETag response header value alongside your cached data. On every subsequent request for the same resource, send it back via If-None-Match.
Freshness Headers in the Response Body
Every successful response also includes timestamp fields that give you application-level freshness information — no header parsing needed:
{
"success": true,
"message": "ok",
"updatedAt": "2026-05-31T10:00:00.000Z",
"expiresAt": "2026-05-31T11:00:00.000Z",
"data": { ... }
}
| Where | Format | What it tells you |
|---|---|---|
updatedAt body field | ISO 8601 | When the data was last scraped from RSI |
Last-Modified header | HTTP-date | Same as updatedAt — for HTTP-level conditional caching |
expiresAt body field | ISO 8601 | When the cache may next be automatically re-scraped |
Expires header | HTTP-date | Same as expiresAt — HTTP-native expiry signal |
updatedAt and Last-Modified reflect the same moment. expiresAt and Expires reflect the same moment — updatedAt plus the endpoint's refresh interval.
Schedule your next poll precisely.
Use expiresAt to know exactly when the data might change. There is no point re-fetching before that timestamp unless you pass ?refresh=true.
Putting It Together: Efficient Polling
Here's a complete pattern for polling funding stats without burning quota:
First request — no ETag yet:
GET /v2/stats?chart=day HTTP/1.1
Host: API_HOST
x-api-key: YOUR_API_KEYSave the ETag from the response header and the expiresAt from the body.
Subsequent requests — send the ETag back, and only poll after expiresAt:
GET /v2/stats?chart=day HTTP/1.1
Host: API_HOST
x-api-key: YOUR_API_KEY
If-None-Match: "a1b2c3d4e5f6"| Response | What to do |
|---|---|
200 OK | Data changed — read new body, store new ETag and expiresAt |
304 Not Modified | Nothing changed — keep your cached copy, no quota spent |
This combination — smart cache + ETags + expiresAt scheduling — means you never waste a quota request and never download a response you already have.