API docs
Everything you need to test CodeProof from a terminal or your own CI. The public demo is open: get a token for a synthetic persona and call the API.
All data here is mock-up data. Tokens are for synthetic personas, the only repository is the synthetic DemoPay-API, and every verification is wiped every 60 minutes.
Quick start
Base URL https://codeproof.enthernetservice.com. Every /api/v1 call except the demo ones needs Authorization: Bearer <token>. Your tenant always comes from the token.
# 1. Get a token for the synthetic developer
TOKEN=$(curl -s -X POST https://codeproof.enthernetservice.com/api/v1/demo/login/developer | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')
# 2. Submit scenario D (authorization-sensitive change)
VID=$(curl -s -X POST -H "Authorization: Bearer $TOKEN" https://codeproof.enthernetservice.com/api/v1/demo/scenarios/D/run | python3 -c 'import sys,json;print(json.load(sys.stdin)["verification_id"])')
# 3. Read the result (repeat until status is COMPLETED, usually ~1s)
curl -s -H "Authorization: Bearer $TOKEN" https://codeproof.enthernetservice.com/api/v1/verifications/$VID
# 4. Approve the exception as someone else
APPROVER=$(curl -s -X POST https://codeproof.enthernetservice.com/api/v1/demo/login/approver | python3 -c 'import sys,json;print(json.load(sys.stdin)["token"])')
curl -s -X POST -H "Authorization: Bearer $APPROVER" -H "Content-Type: application/json" \
-d '{"action":"APPROVE_EXCEPTION","reason":"Accepted for the demo after review."}' \
https://codeproof.enthernetservice.com/api/v1/verifications/$VID/reviews
Auth & personas
Tokens come from POST /api/v1/demo/login/{persona}. They're static demo tokens for synthetic users; production uses SSO. A token from another tenant gets 404 for your data, never a hint that it exists.
| Persona | Name | Role | Can |
|---|---|---|---|
developer | Ada Synthetic | DEVELOPER | submit, read, acknowledge, request explanation |
approver | Grace Synthetic | APPROVER | read, acknowledge, request changes, reject, approve exception |
security | Linus Synthetic | SECURITY_REVIEWER | submit, read, all review actions incl. approve exception |
auditor | Edsger Synthetic | AUDITOR | read, request explanation, metrics |
admin | Barbara Synthetic | ADMIN | submit, read, acknowledge, request changes, reject, metrics, manage repos (cannot approve exceptions) |
viewer | Alan Synthetic | VIEWER | read only |
Get a token
export TOKEN=<paste the token here>
Endpoints
GET/healthzService health, sandbox kind and policy version
Who can call it: anyone, no token
curl https://codeproof.enthernetservice.com/healthz
{
"status": "ok",
"database": "ok",
"version": "0.1.0",
"demo_mode": true,
"ai_enabled": false,
"sandbox": "linux-namespace",
"policy_version": "codeproof-default@2026.10.1+ccd8b94b3478"
}
GET/api/v1/demoThe synthetic repository, personas and scenario commits
Who can call it: anyone, no token
curl https://codeproof.enthernetservice.com/api/v1/demo
Returns repository, base_commit, personas and scenarios (each with id, title, declared_task, expected and candidate_commit). The live values are in the scenario table below.
POST/api/v1/demo/login/{persona}Get a bearer token for a synthetic persona
Who can call it: anyone, no token
curl -X POST https://codeproof.enthernetservice.com/api/v1/demo/login/developer
{
"token": "…",
"synthetic": true
}Personas: developer, approver, security, auditor, admin, viewer.
GET/api/v1/meWho the token belongs to and what it may do
Who can call it: any persona
curl -H "Authorization: Bearer $TOKEN" https://codeproof.enthernetservice.com/api/v1/me
{
"user_id": "usr_demo_developer",
"tenant_id": "demo",
"name": "Ada Synthetic (developer)",
"role": "DEVELOPER",
"synthetic": true,
"permissions": [
"explanation.request",
"review.ACKNOWLEDGE",
"verification.read",
"verification.submit"
]
}
GET/api/v1/repositoriesRepositories registered to your tenant
Who can call it: any persona
curl -H "Authorization: Bearer $TOKEN" https://codeproof.enthernetservice.com/api/v1/repositories
{"repositories": [{"name": "DemoPay-API", "synthetic": true}]}
POST/api/v1/demo/scenarios/{id}/runSubmit one of the scenario commits (A–G)
Who can call it: developer, security, admin
curl -X POST -H "Authorization: Bearer $TOKEN" https://codeproof.enthernetservice.com/api/v1/demo/scenarios/D/run
{
"verification_id": "ver_91757889c3414b80a08b",
"status": "QUEUED",
"reused": false
}202 for a new verification, 200 with "reused": true when the same change was already verified (idempotency).
POST/api/v1/verificationsSubmit any base → candidate change of a registered repository
Who can call it: developer, security, admin
curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"repository":"DemoPay-API","base_commit":"<base>","candidate_commit":"<candidate>",
"declared_task":"Add receipt formatter","ai_assisted":"YES",
"generation_metadata":{"source_type":"ide","human_or_ai":"YES","tool_name":"my-codegen"}}' \
https://codeproof.enthernetservice.com/api/v1/verifications| Field | Required | Notes |
|---|---|---|
repository | yes | Must be registered to your tenant (DemoPay-API) |
base_commit, candidate_commit | yes | Hex git object ids, 7–64 chars. Use the commits from GET /api/v1/demo. A commit that doesn't exist is accepted, then ends as INVALID_INPUT with no decision. |
declared_task | no | Up to 2,000 chars. Recorded, never used as a policy input. |
ai_assisted | no | YES, NO or UNKNOWN (default) |
language | no | python (default) or javascript (dependency checks only) |
generation_metadata | no | source_type, human_or_ai, tool_name, tool_version, generation_session_reference |
Unknown fields are rejected with 422, so a tenant id, URL or command can't be passed in. Response is the same shape as the scenario run.
GET/api/v1/verificationsYour tenant's verifications, newest first
Who can call it: any persona
curl -H "Authorization: Bearer $TOKEN" "https://codeproof.enthernetservice.com/api/v1/verifications?limit=20"
limit defaults to 50, max 200. Each item has id, status, decision, outcome, evidence_hash, timeline, summary and effective (what CI should do).
GET/api/v1/verifications/{id}One verification with full evidence, integrity and reviews
Who can call it: any persona
curl -H "Authorization: Bearer $TOKEN" https://codeproof.enthernetservice.com/api/v1/verifications/ver_91757889c3414b80a08b
{
"verification": {
"id": "ver_91757889c3414b80a08b",
"status": "COMPLETED",
"decision": "REVIEW_REQUIRED",
"outcome": "REVIEW",
"summary": {
"security_findings": 1,
"secrets": 0,
"dependencies_added": 0,
"tests_executed": 18,
"rules_fired": [
"HIGH_SECURITY_FINDING",
"AUTHENTICATION_FILES_CHANGED"
],
"files_changed": 2
},
"effective": {
"ci_status": "action_required",
"label": "REVIEW_REQUIRED"
}
},
"evidence": {
"policy_decision": "REVIEW_REQUIRED",
"policy_rules_fired": [
{
"rule": "HIGH_SECURITY_FINDING",
"decision": "REVIEW_REQUIRED",
"observed": 1,
"threshold": {
"op": "gt",
"value": 0
},
"exception_allowed": true,
"reason": "New high-severity static-analysis finding."
}
],
"diff_summary": "\u2026",
"build_result": "\u2026",
"test_result": "\u2026",
"coverage_result": "\u2026",
"security_findings": "\u2026",
"secret_findings": [],
"dependency_findings": [],
"environment": "\u2026",
"attestation": "\u2026",
"ai_used_for_authority": false,
"evidence_hash": "sha256:\u2026"
},
"integrity": {
"hash_verifies": true,
"attestation_verifies": true,
"index_matches": true,
"valid": true
},
"reviews": [],
"explanations": [],
"authority": {
"verified_by": "AUTOMATION",
"ai_authorization": "NEVER"
}
}Poll this until verification.status is COMPLETED (or an infrastructure failure such as SANDBOX_FAILED or TIMEOUT, which never carries a decision). A DemoPay run takes about a second.
GET/api/v1/verifications/{id}/evidenceDownload the sealed evidence bundle (JSON)
Who can call it: any persona
curl -H "Authorization: Bearer $TOKEN" -o evidence.json \ https://codeproof.enthernetservice.com/api/v1/verifications/<id>/evidence
Canonical JSON with an HMAC attestation. Check it offline with python -m codeproof.cli verify-evidence evidence.json (needs the signing key).
GET/api/v1/verifications/{id}/integrityRe-check the stored evidence hash and attestation
Who can call it: any persona
curl -H "Authorization: Bearer $TOKEN" https://codeproof.enthernetservice.com/api/v1/verifications/<id>/integrity
{
"verification_id": "ver_\u2026",
"evidence_hash": "sha256:\u2026",
"hash_verifies": true,
"attestation_verifies": true,
"index_matches": true,
"valid": true
}
POST/api/v1/verifications/{id}/reviewsRecord a human action on a completed verification
Who can call it: ACKNOWLEDGE: developer, approver, security, admin · REQUEST_CHANGES / REJECT: approver, security, admin · APPROVE_EXCEPTION: approver, security (never the submitter, never admin)
curl -X POST -H "Authorization: Bearer $APPROVER_TOKEN" -H "Content-Type: application/json" \
-d '{"action":"APPROVE_EXCEPTION","reason":"Header check is behind the support VPN; accepted."}' \
https://codeproof.enthernetservice.com/api/v1/verifications/<id>/reviewsaction: ACKNOWLEDGE, APPROVE_EXCEPTION, REJECT or REQUEST_CHANGES. reason: 10–2,000 chars. Returns 201. The evidence and decision never change; the review is layered on top and shows in effective (for example REVIEW_REQUIRED — EXCEPTION APPROVED).
Refusals: 403 wrong role or you submitted the change · 409 PASS needs no exception, the verification isn't complete, a fired rule can't be waived (SECRET_DETECTED, MANDATORY_CHECK_INCOMPLETE), or evidence integrity failed.
POST/api/v1/verifications/{id}/explanationsAsk the optional AI explainer for a plain-language summary
Who can call it: all except viewer
AI is switched off on this server, so this returns 503 with "verification_unaffected": true. When enabled, the explanation is stored separately and can never change evidence or the decision.
GET/api/v1/dashboardCounters for your tenant
Who can call it: any persona
{
"verifications_total": 14,
"pass": 1,
"review_required": 1,
"blocked": 5,
"not_verified": 7,
"in_progress": 0,
"security_findings": 2,
"secrets_detected": 1,
"dependencies_added": 1,
"tests_executed": 116,
"average_verification_ms": 645,
"ai_assisted_changes": 10,
"human_exceptions": 0
}
Scenario commits
Use these with POST /api/v1/verifications, or run them by id. Loaded live from GET /api/v1/demo.
| Id | Scenario | Expected | base → candidate |
|---|---|---|---|
| Loading… | |||
Statuses & decisions
| status | Lifecycle: RECEIVED → QUEUED → PREPARING → ANALYZING_DIFF → BUILDING → … → COMPLETED. Infrastructure failures (INVALID_INPUT, SANDBOX_FAILED, TIMEOUT, INTERNAL_ERROR, CANCELLED) never carry a decision. |
|---|---|
| decision | PASS, REVIEW_REQUIRED or BLOCK, only on COMPLETED. BLOCK beats REVIEW beats PASS. |
| outcome | Why, in one word: OK, REVIEW, TEST_FAILED, SECRET_DETECTED, SECURITY_FAILED, DEPENDENCY_FAILED, … |
| effective | What CI should do now, with human reviews applied: ci_status is success, failure, action_required, pending or error. |
Policy rules (codeproof-default v2026.10.1)
Facts are measured by automation; rules only compare them to constants. Coverage is in basis points (10000 = 100%).
| Rule | Decision | Fires when | Exception? | Meaning |
|---|---|---|---|---|
MANDATORY_CHECK_INCOMPLETE | BLOCK | mandatory_checks_incomplete gt 0 | no | A mandatory check did not complete; CodeProof fails closed. |
SECRET_DETECTED | BLOCK | secrets_high_confidence gt 0 | no | High-confidence secret committed. |
BUILD_FAILED | BLOCK | build_failed eq true | yes | Required build failed. |
TESTS_FAILED | BLOCK | tests_failed gt 0 | yes | One or more tests failed or errored. |
TEST_COUNT_REGRESSION | BLOCK | test_count_regression gt 0 | yes | Fewer tests exist than at the base commit. Removing tests requires an approved human exception. |
CRITICAL_SECURITY_FINDING | BLOCK | sast_new_critical gt 0 | yes | New critical static-analysis finding. |
UNVERIFIED_DEPENDENCY | BLOCK | unverified_dependencies gt 0 | yes | Dependency or import could not be verified against the controlled package source (possible hallucinated package). |
CRITICAL_VULNERABLE_DEPENDENCY | BLOCK | vulnerable_dependencies_critical gt 0 | yes | Dependency with a known critical vulnerability. |
SECRET_POSSIBLE | REVIEW_REQUIRED | secrets_medium_confidence gt 0 | yes | Possible secret (medium confidence) needs a human look. |
HIGH_SECURITY_FINDING | REVIEW_REQUIRED | sast_new_high gt 0 | yes | New high-severity static-analysis finding. |
MEDIUM_SECURITY_FINDING | REVIEW_REQUIRED | sast_new_medium gt 0 | yes | New medium-severity static-analysis finding. |
VULNERABLE_DEPENDENCY | REVIEW_REQUIRED | vulnerable_dependencies_high gt 0 | yes | Dependency with a known high-severity vulnerability. |
DEPENDENCY_ADDED | REVIEW_REQUIRED | dependencies_added gt 0 | yes | New dependency introduced. |
DEPENDENCY_VERIFICATION_INCOMPLETE | REVIEW_REQUIRED | dependency_verification_incomplete eq true | yes | Dependency service unavailable; verification incomplete. |
AUTHENTICATION_FILES_CHANGED | REVIEW_REQUIRED | auth_files_changed gt 0 | yes | Authentication or authorization code changed. |
SECURITY_SENSITIVE_FILES_CHANGED | REVIEW_REQUIRED | other_sensitive_files_changed gt 0 | yes | Payments, secrets, migrations, infrastructure or CI configuration changed. |
UNSAFE_REPOSITORY_CONTENT | REVIEW_REQUIRED | unsafe_repository_entries gt 0 | yes | Repository contains unsafe paths or escaping symlinks that were not materialized. |
COVERAGE_DROP | REVIEW_REQUIRED | coverage_delta_bp lt -500 | yes | Line coverage dropped by more than 5 percentage points. |
CRITICAL_MODULE_COVERAGE_DROP | REVIEW_REQUIRED | critical_module_coverage_delta_bp lt -200 | yes | Coverage of a critical module (payments/auth) dropped by more than 2 percentage points. |
TESTS_RENAMED_OR_REMOVED | REVIEW_REQUIRED | base_tests_missing gt 0 | yes | Some base-commit test ids no longer exist (renamed or replaced). |
NO_TESTS_EXECUTED | REVIEW_REQUIRED | tests_executed eq 0 | yes | No tests were executed for this change. |
Errors
400 | Request understood but refused by the service |
401 | {"error":"authentication required"}: missing or unknown token |
403 | Role lacks the permission, or separation of duties |
404 | Not found, or belongs to another tenant (same answer on purpose) |
409 | Conflict: review not allowed in this state |
413 | Body over 64 KB |
422 | Validation failed; detail lists the fields |
429 | Rate limited by the server |
503 | Storage unavailable (no result is claimed) or AI explainer disabled |