CorsacAPI referencepreview

Corsac API

REST · JSON over HTTPS · bearer-token auth. Everything customer-facing lives under /api/app/*. Browse the eval library, push your runs, and read or write the human review decision on each one.

The canonical reference is the live OpenAPI document at https://api.corsac.ai/openapi.json (rendered at /docs and /swagger). The page below is a hand-written tour of the same surface; field-level shapes always defer to OpenAPI.
Introduction

Getting started

Browse GET /api/app/evals to find a spec, mint a workspace API key in the Corsac dashboard, then push your first eval result from CI in three lines. Every Corsac eval — automated or human-reviewed — flows through a single ingestion endpoint and is then queryable per org.

curl https://api.corsac.ai/api/app/evals/clinical_safety/external-run \
  -H "Authorization: Bearer $CORSAC_API_KEY" \
  -H "Content-Type: application/json" \
  -d @eval-result.json
Introduction

Authentication

Most endpoints authenticate with a workspace API key in the Authorization header. Keys are prefixed csk_ and minted by an org admin from the Corsac dashboard. There is one active key per organization at a time; regenerating auto-revokes the previous key.

http
Authorization: Bearer csk_...

The eval-library list endpoint (GET /api/app/evals) is the one exception — it's anonymous so crawlers and unauthenticated visitors can discover available evals. Spec detail (rubric, evaluators, cases) and everything run/review-related require auth.

Read endpoints also accept the session cookie issued to a signed-in user, so the same paths back both the SDK and the dashboard. Endpoints that record a human decision (the PUT on a review action) require a session — API-key callers receive a 403 by design.

The bearer token grants org-wide access. Store it as a secret (CI environment variable, secret manager). Rotate via the dashboard if it's exposed.
Introduction

Errors

Errors follow the FastAPI convention: a JSON body with a single detail field plus a conventional HTTP status code. Validation failures (422) include a structured list under detail with the offending field path.

StatusWhen
400Malformed request: wrong content-type, conflicting path/body values, or an unrecoverable parse error.
401Missing, invalid, or revoked bearer token; or no active session.
403Authenticated but not allowed: API-key caller hit a session-only endpoint, or non-admin hit an admin endpoint.
404Resource doesn't exist or is in another organization.
422Validation failure on the request body. See `detail` for field path and message.
5xxServer error. Retry with backoff; surface request id from logs if it persists.
json
{
  "detail": "Spec not found: clinical_safety"
}
Introduction

Pagination

List endpoints accept limit (max 200, default 50) and pre-filter by the actor's organization. There is no cursor today; ordering is newest-first bystarted_at.

Introduction

OpenAPI reference

The autogenerated schema is the source of truth for request and response shapes:

  • GET https://api.corsac.ai/openapi.json — raw schema
  • https://api.corsac.ai/docs — ReDoc reference
  • https://api.corsac.ai/swagger — interactive Swagger console
GET/api/app/evals

List evals

Anonymous browse of the eval library. Returns the thin list shape (name, slug, vendor, use-case, short description, counts) so crawlers and unauthenticated visitors can discover what's available. No auth header required.

Parameters
None.
Request
bash
curl https://api.corsac.ai/api/app/evals
Response · 200 OK
json
[
  {
    "spec_id": "clinical_safety",
    "name": "Clinical Safety",
    "vendor": "Hippocratic AI",
    "use_case": "Patient intake",
    "short_description": "PHI redaction, medication safety, citation fidelity.",
    "evaluator_count": 4,
    "case_count": 412
  }
]
GET/api/app/evals/{spec_id}

Get eval spec detail

Full eval spec including rubric, evaluator configs (thresholds, weights, severity), and example cases. Requires auth — this is the deliberate marketplace wall: anonymous visitors can browse names and descriptions via the list endpoint, but rubric internals require signup.

Parameters
spec_id
path stringrequired
The eval spec slug (e.g. clinical_safety).
include_examples
query booloptional
Include example cases inline. Default true.
max_examples
query integeroptional
0–200; default 20.
Request
bash
curl https://api.corsac.ai/api/app/evals/clinical_safety \
  -H "Authorization: Bearer $CORSAC_API_KEY"
Response · 200 OK
json
{
  "spec_id": "clinical_safety",
  "name": "Clinical Safety",
  "vendor": "Hippocratic AI",
  "use_case": "Patient intake",
  "description": "...",
  "evaluators": [ /* full rubric */ ],
  "examples": [ /* sample cases */ ]
}
POST/api/app/evals/{spec_id}/external-run

Push an eval result

Ingest a pre-computed eval result for a spec. This is the canonical SDK entry point — your CI or runner does the scoring locally, then sends the EvalResult JSON to Corsac for storage, gating, and routing to review.

Parameters
spec_id
path stringrequired
The eval spec slug (e.g. clinical_safety). Must match the optional spec_id in the body if present.
body
EvalResult (JSON)required
Per-example metrics, aggregates, and run metadata. Field shape lives in the OpenAPI ExternalRunRequestV2 schema.
Request
bash
curl https://api.corsac.ai/api/app/evals/clinical_safety/external-run \
  -H "Authorization: Bearer $CORSAC_API_KEY" \
  -H "Content-Type: application/json" \
  -d @eval-result.json
Response · 200 OK
json
{
  "run_id": "run_2fJ4...",
  "spec_id": "clinical_safety",
  "organization_id": "org_8c12...",
  "status": "completed",
  "gate_status": "passed",
  "aggregates": { /* ... */ },
  "failed_metrics": [],
  "started_at": "2026-05-13T15:42:11Z",
  "finished_at": "2026-05-13T15:42:14Z"
}
GET/api/app/runs

List runs

Paginated list of runs in the caller's organization, newest first. Accepts either a session cookie or a bearer API key.

Parameters
spec_id
query stringoptional
Filter to a single eval spec slug.
limit
query integeroptional
1–200; default 50.
Request
bash
curl 'https://api.corsac.ai/api/app/runs?spec_id=clinical_safety&limit=20' \
  -H "Authorization: Bearer $CORSAC_API_KEY"
Response · 200 OK
json
[
  {
    "run_id": "run_2fJ4...",
    "spec_id": "clinical_safety",
    "status": "completed",
    "gate_status": "passed",
    "started_at": "2026-05-13T15:42:11Z",
    "finished_at": "2026-05-13T15:42:14Z"
  }
]
GET/api/app/runs/{run_id}

Get a run

Fetch a single run by id. Org-scoped — runs in another organization return 404.

Parameters
run_id
path stringrequired
The run identifier returned by external-run or list.
Request
bash
curl https://api.corsac.ai/api/app/runs/run_2fJ4... \
  -H "Authorization: Bearer $CORSAC_API_KEY"
Response · 200 OK
json
{
  "run_id": "run_2fJ4...",
  "spec_id": "clinical_safety",
  "organization_id": "org_8c12...",
  "status": "completed",
  "gate_status": "passed",
  "aggregates": { /* ... */ },
  "failed_metrics": [],
  "failed_primary_metrics": [],
  "blocked_reason": null
}
GET/api/app/review-actions

List review decisions

All human review decisions recorded against runs in the caller's organization.

Parameters
None.
Request
bash
curl https://api.corsac.ai/api/app/review-actions \
  -H "Authorization: Bearer $CORSAC_API_KEY"
Response · 200 OK
json
[
  {
    "run_id": "run_2fJ4...",
    "decision": "approved",
    "notes": "Reviewed by clinical lead; rubric pass.",
    "updated_at": "2026-05-13T16:02:11Z",
    "updated_by_user_id": "user_..."
  }
]
GET/api/app/review-actions/{run_id}

Get a review decision

Read the current review decision for a single run. 404 if no decision has been recorded yet.

Parameters
run_id
path stringrequired
The run identifier.
Request
bash
curl https://api.corsac.ai/api/app/review-actions/run_2fJ4... \
  -H "Authorization: Bearer $CORSAC_API_KEY"
Response · 200 OK
json
{
  "run_id": "run_2fJ4...",
  "decision": "approved",
  "notes": "Reviewed by clinical lead; rubric pass.",
  "updated_at": "2026-05-13T16:02:11Z",
  "updated_by_user_id": "user_..."
}
PUT/api/app/review-actions/{run_id}

Set a review decision

Record or update the human review decision on a run. Session-only — API-key callers get 403 because review decisions are human-accountability artifacts and we record the acting user id on every transition.

Parameters
run_id
path stringrequired
The run identifier.
decision
body enumrequired
Allowed values are defined by the review-decision policy on the backend; consult OpenAPI for the current set.
notes
body string?optional
Free-text rationale captured alongside the decision.
Request
bash
curl -X PUT https://api.corsac.ai/api/app/review-actions/run_2fJ4... \
  -H "Cookie: corsac_session=..." \
  -H "Content-Type: application/json" \
  -d '{ "decision": "approved", "notes": "Reviewed by clinical lead." }'
Response · 200 OK
json
{
  "run_id": "run_2fJ4...",
  "decision": "approved",
  "notes": "Reviewed by clinical lead.",
  "updated_at": "2026-05-13T16:02:11Z",
  "updated_by_user_id": "user_..."
}
SDKs

Coming soon

Official TypeScript and Python SDKs are on the roadmap. In the meantime, the API is small enough to call with fetch or requests; the snippets in Getting started are copy-pasteable.

If you'd like early access to the SDKs or a specific language wrapper, email hello@corsac.ai.

Ready to integrate?

Mint a workspace API key from the dashboard and push your first run in under a minute.

Get an API key