Authentication
Every request carries an API key as a bearer token:
curl -s https://codetruss.com/api/v1/repos \
-H "Authorization: Bearer ct_live_..."
Keys are created in Dashboard → Settings → API keys by an organization admin, on the Team plan or higher. The plaintext is shown once at creation and never again; only the display prefix is listed afterwards. Every key is scoped to one organization — there is no cross-organization access, whatever the scopes.
A missing or invalid key returns 401. A key that lacks the scope an
endpoint requires returns 403 with the missing scope named.
Scopes
| Scope | Grants |
|---|---|
repos:read | List repositories and their scores |
scans:read | Read scan status, scores, and finding counts |
scans:write | Start scans |
receipts:read | List and read synced CLI receipts |
receipts:write | Sync CLI receipts (what codetruss sync uses) |
Rate limits
Requests are rate-limited per key. Exceeding the limit returns 429 with a
Retry-After header carrying the wait in seconds.
Errors
Errors are JSON: { "error": "<message>" } with a meaningful status —
401 unauthenticated, 403 missing scope, 402 plan limit, 404 not
found or outside the key's organization, 409 conflict, 429 rate
limited.
Endpoints
List repositories
GET /api/v1/repos — scope repos:read
Returns every repository in the key's organization, newest first.
{ "repos": [ { "id": "…", "name": "owner/name", "defaultBranch": "main",
"isPrivate": true, "status": "READY", "primaryLanguage": "TypeScript",
"healthScore": 82, "debtScore": 78, "archScore": 84, "securityScore": 71,
"docsScore": 66, "lastIndexedAt": "…", "createdAt": "…" } ] }
List scans for a repository
GET /api/v1/repos/{repoId}/scans — scope scans:read
Recent scans for one repository, each with its finding count.
Start a scan
POST /api/v1/repos/{repoId}/scans — scope scans:write
{ "type": "FULL_AUDIT" }
type is optional: FULL_AUDIT (default), ARCHITECTURE,
SECURITY, DOCUMENTATION, or QUICK. Returns 201 with
{ "scan": { "id", "type", "status", "createdAt" } }. A scan already in
progress returns 409; a plan scan limit returns 402.
Read a scan
GET /api/v1/scans/{scanId} — scope scans:read
Status, scores, and finding counts:
{ "scan": { "id": "…", "repoId": "…", "repoName": "owner/name",
"type": "FULL_AUDIT", "status": "COMPLETED",
"scores": { "health": 82, "debt": 78, "arch": 84, "security": 71, "docs": 66 },
"findingCounts": { "CRITICAL": 0, "HIGH": 3, "MEDIUM": 11, "LOW": 25, "INFO": 40, "total": 79 },
"securityFindingCounts": { "CRITICAL": 0, "HIGH": 1, "MEDIUM": 2, "LOW": 3, "INFO": 1, "total": 7 },
"error": null, "startedAt": "…", "completedAt": "…", "createdAt": "…" } }
findingCounts spans every category — rendering "N high" from it presents
maintainability work as security work. securityFindingCounts is the same
shape over the security categories only; use it for anything security-labelled.
List synced receipts
GET /api/v1/cli/receipts — scope receipts:read
Verified receipt summaries for the organization. Query parameters:
verdict (PASS | REVIEW_REQUIRED | FAILED), q (task-text
search, ≤200 chars), limit (1–100, default 50).
Read a synced receipt
GET /api/v1/cli/receipts/{receiptId} — scope receipts:read
One receipt with its verification state. Receipts are re-verified against their signature on read — a stored receipt that no longer verifies says so rather than being served as evidence.
Sync a receipt
POST /api/v1/cli/receipts — scope receipts:write
The endpoint codetruss sync calls. The body is the CLI's signed sync
envelope; it is verified before it is stored, and the plan must include
receipt sync. Rather than hand-building the envelope, use the CLI.
Device authentication
POST /api/v1/cli/auth/device, POST /api/v1/cli/auth/token, and
POST /api/v1/cli/auth/session implement the CLI's device-authorization
login (codetruss auth login). They authenticate the CLI itself, not API
keys, and are documented here only so the surface list is complete.