API / version 1
Evidence in stable JSON.
The public API exposes the same timestamped observations as the website. It is read-only and needs no key or account.
Requests and caching
Every response is application/json and carries Cache-Control: public, s-maxage=60, stale-while-revalidate=300. Honouring that header costs you nothing and keeps the index cheap to serve, so please read from your cache rather than polling. Only GET and HEAD are served; any other method returns 405 with an Allow header.
Errors never return a bare status. The body is always an object with a code that is safe to branch on and a message written for a person:
{ "error": { "code": "invalid_limit", "message": "limit must be an integer from 1 to 100" } }List servers
GET /api/v1/servers- q
- Free text matched against the title, registry name, and description.
- state
- One of
verified,stale,broken,auth_required, orunverifiable. - package
- The package registry type:
npm,pypi, oroci. - transport
- The transport declared by the Registry record, for example
stdio. - client
- A client slug, as listed on Clients — for example
claude-code. - limit
- An integer from 1 to 100. Defaults to 25. A value outside that range is refused rather than clamped, so a client is never handed a different number of rows than it asked for without being told.
- cursor
- The
nextCursorfrom the previous response. Omit it for the first page; it isnullon the last.
GET /api/v1/servers?state=verified&package=npm&limit=2
{
"data": [
{
"id": "srv_01J…",
"registryName": "example/one",
"title": "Example Server",
"description": "What the server says it does.",
"state": "verified",
"observedAt": "2026-09-15T00:00:00.000Z",
"toolCount": 3,
"url": "/servers/example/one"
}
],
"nextCursor": null
}Server detail
GET /api/v1/servers/:namespace/:nameReturns the Registry metadata, the runnable packages, and the public observation history for one server, under data. Each run in that history names the exact package version it tested, which is usually not the version published today. An unknown pair returns 404 with the code not_found.
Verification run
GET /api/v1/verification-runs/:idOne observation, by its identifier. A run that has not cleared the confirmation rule is absent here and returns 404 with the code not_found — the same answer as a run that never existed, because any difference between the two would disclose a failure the rule exists to withhold.
Dataset statistics
GET /api/v1/stats{ "data": { "indexedServers": 979, "verifiedServers": 0, "observedAt": null } }Error codes
- invalid_limit
400— the limit was not an integer from 1 to 100.- invalid_cursor
400— the cursor is malformed, or was made against a different sort order. Start again from the first page.- not_found
404— no such server, or no publishable run with that identifier.- method_not_allowed
405— the API is read-only. The response names the methods that are served.
What is not exposed
Internal stderr, worker leases, and pending confirmation details are never published, and a state always carries the timestamp of the observation it describes rather than the time you asked for it.