API overview
Base URL, authentication, rate limits, common parameters and errors.
Everything the website shows is available as JSON.
https://subnethistory.com/api/v1
All endpoints are HTTP GET and return JSON, except the streaming lookup, which returns server sent events. Responses are UTF-8.
Authentication
None. The API is currently open and requires no key or account. If you plan sustained high volume use, contact [email protected] first.
Rate limits
Requests are limited to 120 per minute per client IP. Exceeding the limit returns HTTP 429 with rate limit headers; back off until the window resets. The health check and the font and flag assets are exempt; everything else counts.
Cold lookups are expensive for the service even when they are free for you. If you are enriching a list of addresses, spread the requests out rather than bursting, and reuse the cached results your earlier requests created.
CORS
Cross origin requests are allowed from any origin, so the API can be called directly from browser applications.
Common query parameters
These apply to the lookup endpoints (/lookup, /lookup/stream, /ip/…, /prefix/…, /asn/…, /history).
| Parameter | Values | Meaning |
|---|---|---|
q | an IP, CIDR prefix or AS number | The query, on endpoints that take one. Same formats as the search bar. |
shallow | 1 | Skip the second enrichment pass. Faster, but ASN level detail discovered from the first pass may be missing. |
offline | 1 | Answer from cache only. Nothing is fetched upstream. |
refresh | 1 | Force upstream refetch, bypassing the cache. Reserved for operators; without authorisation the parameter is ignored and the request is served normally. |
Errors
| Status | When | Body |
|---|---|---|
400 | The query could not be interpreted, or a required parameter is missing | { "error" }, plus a hint for unparseable queries |
404 | Unknown API path | { "error": "not found" } |
429 | Rate limit exceeded | Standard rate limit error body |
502 | The lookup itself failed unexpectedly | { "error": "lookup failed", "detail" } |
An upstream outage alone never fails your request: the affected dataset is reported with a stale or error state in sources and the rest of the report is delivered. A stale dataset still has an answer, the last known good one, so it does not set meta.partial. An error dataset has none, so it does, and meta.retryAfterMs says how long to wait before repeating the lookup. A 502 means the lookup pipeline itself hit an unexpected error (the history endpoint reports the same condition as a plain 500).
Example 400 response:
{
"error": "could not interpret \"hello\" as an IP address, CIDR prefix, or AS number",
"hint": "Try an IP address (8.8.8.8), a CIDR prefix (8.8.8.0/24), or an AS number (AS15169)."
}
Versioning
The API is versioned in the path (/api/v1). Changes within v1 are additive: new fields may appear in responses at any time, so clients should ignore fields they do not recognise.
Endpoints
| Endpoint | Returns |
|---|---|
GET /lookup | The full report, for any query. Also reachable as /ip/…, /prefix/…, /asn/…. |
GET /lookup/stream | The same lookup as server sent events with live progress. |
GET /asn/:asn/neighbours | Paged neighbour lists for an AS. |
GET /asn/:asn/prefixes | Paged announced prefix lists for an AS. |
GET /history | Timeline, insights, sources and meta, without the rest of the report. |
GET /archive | SubnetHistory's own recorded change events and routing observations. |
GET /sources | The credited data sources, machine readable. |
GET /tags | The full tag vocabulary. |
GET /recent | The latest searches across the site. |
GET /whoami | The IP your request arrived from. |