CodeProof by Enthernet Services
VERIFIED BY: AUTOMATION AI AUTHORIZATION: NEVER

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.

PersonaNameRoleCan
developerAda SyntheticDEVELOPERsubmit, read, acknowledge, request explanation
approverGrace SyntheticAPPROVERread, acknowledge, request changes, reject, approve exception
securityLinus SyntheticSECURITY_REVIEWERsubmit, read, all review actions incl. approve exception
auditorEdsger SyntheticAUDITORread, request explanation, metrics
adminBarbara SyntheticADMINsubmit, read, acknowledge, request changes, reject, metrics, manage repos (cannot approve exceptions)
viewerAlan SyntheticVIEWERread 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
FieldRequiredNotes
repositoryyesMust be registered to your tenant (DemoPay-API)
base_commit, candidate_commityesHex 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_tasknoUp to 2,000 chars. Recorded, never used as a policy input.
ai_assistednoYES, NO or UNKNOWN (default)
languagenopython (default) or javascript (dependency checks only)
generation_metadatanosource_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>/reviews

action: 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.

IdScenarioExpectedbase → candidate
Loading…

Statuses & decisions

statusLifecycle: RECEIVED → QUEUED → PREPARING → ANALYZING_DIFF → BUILDING → … → COMPLETED. Infrastructure failures (INVALID_INPUT, SANDBOX_FAILED, TIMEOUT, INTERNAL_ERROR, CANCELLED) never carry a decision.
decisionPASS, REVIEW_REQUIRED or BLOCK, only on COMPLETED. BLOCK beats REVIEW beats PASS.
outcomeWhy, in one word: OK, REVIEW, TEST_FAILED, SECRET_DETECTED, SECURITY_FAILED, DEPENDENCY_FAILED, …
effectiveWhat 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%).

RuleDecisionFires whenException?Meaning
MANDATORY_CHECK_INCOMPLETEBLOCKmandatory_checks_incomplete gt 0noA mandatory check did not complete; CodeProof fails closed.
SECRET_DETECTEDBLOCKsecrets_high_confidence gt 0noHigh-confidence secret committed.
BUILD_FAILEDBLOCKbuild_failed eq trueyesRequired build failed.
TESTS_FAILEDBLOCKtests_failed gt 0yesOne or more tests failed or errored.
TEST_COUNT_REGRESSIONBLOCKtest_count_regression gt 0yesFewer tests exist than at the base commit. Removing tests requires an approved human exception.
CRITICAL_SECURITY_FINDINGBLOCKsast_new_critical gt 0yesNew critical static-analysis finding.
UNVERIFIED_DEPENDENCYBLOCKunverified_dependencies gt 0yesDependency or import could not be verified against the controlled package source (possible hallucinated package).
CRITICAL_VULNERABLE_DEPENDENCYBLOCKvulnerable_dependencies_critical gt 0yesDependency with a known critical vulnerability.
SECRET_POSSIBLEREVIEW_REQUIREDsecrets_medium_confidence gt 0yesPossible secret (medium confidence) needs a human look.
HIGH_SECURITY_FINDINGREVIEW_REQUIREDsast_new_high gt 0yesNew high-severity static-analysis finding.
MEDIUM_SECURITY_FINDINGREVIEW_REQUIREDsast_new_medium gt 0yesNew medium-severity static-analysis finding.
VULNERABLE_DEPENDENCYREVIEW_REQUIREDvulnerable_dependencies_high gt 0yesDependency with a known high-severity vulnerability.
DEPENDENCY_ADDEDREVIEW_REQUIREDdependencies_added gt 0yesNew dependency introduced.
DEPENDENCY_VERIFICATION_INCOMPLETEREVIEW_REQUIREDdependency_verification_incomplete eq trueyesDependency service unavailable; verification incomplete.
AUTHENTICATION_FILES_CHANGEDREVIEW_REQUIREDauth_files_changed gt 0yesAuthentication or authorization code changed.
SECURITY_SENSITIVE_FILES_CHANGEDREVIEW_REQUIREDother_sensitive_files_changed gt 0yesPayments, secrets, migrations, infrastructure or CI configuration changed.
UNSAFE_REPOSITORY_CONTENTREVIEW_REQUIREDunsafe_repository_entries gt 0yesRepository contains unsafe paths or escaping symlinks that were not materialized.
COVERAGE_DROPREVIEW_REQUIREDcoverage_delta_bp lt -500yesLine coverage dropped by more than 5 percentage points.
CRITICAL_MODULE_COVERAGE_DROPREVIEW_REQUIREDcritical_module_coverage_delta_bp lt -200yesCoverage of a critical module (payments/auth) dropped by more than 2 percentage points.
TESTS_RENAMED_OR_REMOVEDREVIEW_REQUIREDbase_tests_missing gt 0yesSome base-commit test ids no longer exist (renamed or replaced).
NO_TESTS_EXECUTEDREVIEW_REQUIREDtests_executed eq 0yesNo tests were executed for this change.

Errors

400Request understood but refused by the service
401{"error":"authentication required"}: missing or unknown token
403Role lacks the permission, or separation of duties
404Not found, or belongs to another tenant (same answer on purpose)
409Conflict: review not allowed in this state
413Body over 64 KB
422Validation failed; detail lists the fields
429Rate limited by the server
503Storage unavailable (no result is claimed) or AI explainer disabled