API Reference
A public, read-only, unauthenticated API. Every endpoint below is designed to be implementable
by a dumb static file server — there is no required query parameter, no server-side state,
and every response is cacheable. Base URL used in these examples:
https://api.circuits.siros.org.
On this page
GET /v1/manifest.json
The full catalog. Cacheable, ETag-conditional, small (a few KB at this catalog's size).
curl -sS https://api.circuits.siros.org/v1/manifest.json | jq .
Conditional revalidation — the normal client path after the first fetch (a 304 costs a few hundred bytes, not the whole document):
curl -sS -D- -o /dev/null \
-H 'If-None-Match: "sha256-<etag-from-first-response>"' \
https://api.circuits.siros.org/v1/manifest.json
# → HTTP/2 304, empty body
Cheap staleness check without transferring the body:
curl -sSI https://api.circuits.siros.org/v1/manifest.json | grep -i x-catalog-generated-at
GET /v1/circuits/{id}.json
A single catalog entry, by id or aliases — the bare object, not wrapped in a manifest envelope. Useful when a client already knows the id it wants and would rather not parse the whole catalog.
curl -sS https://api.circuits.siros.org/v1/circuits/longfellow-libzk-v1_8_2_4307_2945.json | jq .
Requesting an alias 301-redirects to the canonical id:
curl -sSL https://api.circuits.siros.org/v1/circuits/longfellow-8-2.json | jq -r .id
An unpublished or unknown id returns 404 with a problem+json body — the two cases are indistinguishable by design.
GET /v1/circuits?… (optional convenience — no client should depend on it)
A filtered listing, for humans and debugging. Unknown query parameters are ignored, not rejected.
curl -sS 'https://api.circuits.siros.org/v1/circuits?system=longfellow&numAttributes=2' | jq '.circuits[].id'
status defaults to active; pass status=all to include deprecated/revoked entries too.
GET /v1/artifacts/{alg}/{hex}
Content-addressed circuit bytes. {alg} is sha256 for now; {hex} is the lowercase hex digest, also given in the manifest entry's artifact.hash. The address is the integrity guarantee — verify it yourself, don't just trust the server:
HASH=9f2c1d5e4b8a37c60d1e2f4a5b6c7d8e90a1b2c3d4e5f60718293a4b5c6d7e8f
curl -sS -o circuit.zst https://api.circuits.siros.org/v1/artifacts/sha256/$HASH
sha256sum circuit.zst # must equal $HASH
Responses are immutable and cached forever (Cache-Control: immutable) — fetch each hash at most once. Range requests are supported:
curl -sS -r 0-15 -D- -o /dev/null https://api.circuits.siros.org/v1/artifacts/sha256/$HASH
# → HTTP/2 206, Content-Range: bytes 0-15/<size>
Error responses
All non-2xx responses use application/problem+json (RFC 9457):
{
"type": "https://api.circuits.siros.org/problems/artifact-not-found",
"title": "Artifact not found",
"status": 404,
"detail": "No artifact with sha256:9f2c… is present in this catalog.",
"instance": "/v1/artifacts/sha256/9f2c…"
}
Treat the HTTP status code as authoritative, the body as advisory-only. If this API is ever mirrored behind a plain static host or CDN, a miss there returns whatever that host returns for a missing key — not necessarily a parseable problem+json body.
Versioning & stability
/v1/ is the schema-version prefix. On a breaking change, /v2/ would be added while /v1/ keeps being served for at least 12 months — a mobile app silently losing its ability to fetch circuits is a bad failure mode we design against. Additive changes (a new optional field, a new system value) never bump the version; clients are expected to ignore fields and systems they don't recognise.
Generated API reference (OpenAPI/Swagger): api.circuits.siros.org/swagger.