CAI Get a survey →

API

Use the standard from anything.

cai.canine.dev is the authority for the rubric catalogs and the scoring fold, served over a small JSON API. The catalogs are the open standard, so the read endpoints are public — the Watchdog surveyor and anyone else call these instead of carrying their own copy.

Rate limits

To keep the standard free and available, anonymous requests to /api are rate-limited per client IP:

  • 1 request / second
  • 3 requests / minute
  • 15 requests / day

The limits chain — a request must satisfy all three. Over the limit returns 429 Too Many Requests with a Retry-After header. The rubric catalog is immutable per version, so cache the rubric you use — you should never need to fetch a given version more than once. The client-side WASM calculator runs entirely in your browser and is not rate-limited.

Two surfaces carry their own, more generous budgets instead: authenticated registry calls (a valid bearer token is the abuse control — a per-principal allowance far above any real delivery loop) and the registry's public probes /api/registry/keys and /api/registry/health (per-IP, sized so offline verification and monitoring never trip it).

The Watchdog surveyor (watchdog.canine.dev) calls these same public endpoints, exempt from the limit as a co-located partner.

Rubric catalog

GET /api/rubrics

The published rubric versions, newest first.

curl https://cai.canine.dev/api/rubrics

{ "latest": "rubric-2026.08.17", "versions": ["rubric-2026.08.17", "rubric-2026.08.16", "rubric-2026.08.15", "rubric-2026.08.14", "rubric-2026.08.12"] }

GET /api/rubrics/{version}/catalog

A version's full catalog — every lens and dimension it defines (latest resolves to the newest). This is the versioned, archived definition of the standard.

curl https://cai.canine.dev/api/rubrics/latest/catalog

{
  "rubricVersion": "rubric-2026.08.17",
  "lenses": [ { "key": "codeHealth", "label": "Code Health" }, … ],
  "dimensions": [
    { "id": "D1", "name": "Cyclomatic Complexity", "lens": "codeHealth",
      "evaluator": "tool", "whatItMeasures": "…", "family": "dimension", "ceilingRung": "Prevented" },
    …  (127 dimensions)
  ]
}

Scoring

POST /api/score

Fold an evidence bundle (measured dimensions) into the CAI + per-lens roll-up. The body is the bundle JSON.

curl -X POST https://cai.canine.dev/api/score \
  -H 'Content-Type: application/json' \
  --data @evidence.json

{
  "cai": 69.56,
  "band": "Adequate",
  "rubricVersion": "rubric-2026.08.15",
  "lenses": [ { "lens": "maturity", "score": 65.1, "weight": 0.457, "contribution": 29.77 }, … ]
}

POST /api/verify

Reproduce a published headline from its evidence (the bundle carries headlineScore).

curl -X POST https://cai.canine.dev/api/verify -H 'Content-Type: application/json' --data @survey.json

{ "reproduced": true, "computed": 69.56, "claimed": 69.6, "delta": 0.04, "tolerance": 0.5 }

The fold is open and deterministic — see the spec for the algorithm, or the reference implementation to run it offline.