/v1/health Liveness probe
| Field | Type |
|---|---|
status | string |
service | string |
api_version | string |
version | string |
Five questions about how your team uses AI. One HTTP call. A score per role, and what to do next.
Quickstart
Five answers, one industry. The whole call:
curl https://api.caiscore.com/v1/score \
-H "Authorization: Bearer $CAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"answers": {
"level": "integrated",
"competence": "harness",
"regulation": "mixed",
"reversibility": "costly",
"detection": "review"
},
"industry": "accounting-firm"
}' import os
import requests
r = requests.post(
"https://api.caiscore.com/v1/score",
headers={"Authorization": f"Bearer {os.environ['CAI_API_KEY']}"},
json={
"answers": {
"level": "integrated",
"competence": "harness",
"regulation": "mixed",
"reversibility": "costly",
"detection": "review",
},
"industry": "accounting-firm",
},
)
print(r.json()["aggregate"]["score"]) const response = await fetch("https://api.caiscore.com/v1/score", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CAI_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
answers: {
level: "integrated",
competence: "harness",
regulation: "mixed",
reversibility: "costly",
detection: "review",
},
industry: "accounting-firm",
}),
});
const { aggregate } = await response.json();
console.log(aggregate.score); Reference
Generated from the OpenAPI document. It can’t drift.
/v1/health Liveness probe
| Field | Type |
|---|---|
status | string |
service | string |
api_version | string |
version | string |
/v1/questions The five CAI questions and their option values
| Field | Type |
|---|---|
meta | object |
questions | array |
/v1/industries Search the curated industry roster
| Name | In | Required | Type | Constraints | Description |
|---|---|---|---|---|---|
q | query | Optional | string | Free-text match against label and curated synonyms. |
| Field | Type |
|---|---|
meta | object |
industries | array |
/v1/industries/{id} One industry, identifier and label only
| Name | In | Required | Type | Constraints | Description |
|---|---|---|---|---|---|
id | path | Required | string |
| Field | Type |
|---|---|
industry | object |
/v1/occupations Search-only occupation discovery
| Name | In | Required | Type | Constraints | Description |
|---|---|---|---|---|---|
q | query | Required | string | At least two characters. | |
limit | query | Optional | integer | min 1; max 10; default 10 |
| Field | Type |
|---|---|
meta | object |
occupations | array |
/v1/occupations/{soc} One occupation, identifier and label only
| Name | In | Required | Type | Constraints | Description |
|---|---|---|---|---|---|
soc | path | Required | string |
| Field | Type |
|---|---|
occupation | object |
/v1/openapi.json This document
/v1/score Score a role roster against the five answers
| Field | Type | Required |
|---|---|---|
answers | object | Required |
occupations | array | Optional |
industry | string | Optional |
| Field | Type |
|---|---|
meta | object |
params | object |
posture | array |
roles | array |
aggregate | object |
suggestions | array |
Errors
Same envelope every time —
{ "error": { "code": "…", "message": "…" } }. Switch on
code; message is for humans.
| Code | Status | Where |
|---|---|---|
unauthorized | 401 | A missing, malformed, or unknown key on any non-exempt route |
rate_limited | 429 | An exhausted rate limit on any non-exempt route |
not_found | 404 | Any request whose path matches no route |
method_not_allowed | 405 | A matched path with the wrong HTTP method |
internal_error | 500 | An unhandled failure, including a misconfigured key or rate-limit binding |
industry_not_found | 404 | GET /v1/industries/:id — unknown id |
query_required | 400 | GET /v1/occupations — missing or too-short q |
invalid_parameter | 400 | GET /v1/occupations — out-of-range limit, or an offset parameter |
occupation_not_found | 404 | GET /v1/occupations/:soc — unknown soc |
unsupported_media_type | 415 | POST /v1/score — Content-Type is not application/json |
invalid_json | 400 | POST /v1/score — body is not valid JSON |
invalid_body | 400 | POST /v1/score — body is not a JSON object |
invalid_answers | 400 | POST /v1/score — answers missing or malformed |
invalid_occupations | 400 | POST /v1/score — occupations is not an array of strings |
invalid_industry | 400 | POST /v1/score — industry is not a string |
industry_not_found | 404 | POST /v1/score — unknown industry id |
missing_roster | 400 | POST /v1/score — neither occupations nor industry given |
empty_roster | 400 | POST /v1/score — resolved roster has zero entries |
roster_too_large | 400 | POST /v1/score — resolved roster exceeds 25 entries |
occupation_not_found | 400 | POST /v1/score — an occupations entry is an unknown SOC code |