Skip to main content

API contract — single source of truth

v0 — May 12, 2026. Every endpoint in the running service is listed here. Before adding, changing, or removing an endpoint, update this file first (DP1 — spec before code). The reviewer expects the diff in this file to land in the same PR as the implementation diff.

Error shape conventions and per-error codes live in docs/error_codes.md.

Conventions

  • All responses are application/json unless explicitly noted (metadata.xml, application/pdf).
  • All write endpoints return 201 Created with the new resource at the top level (e.g. { "device": {...} }).
  • All list endpoints return 200 OK with the collection plus the resolved environment (e.g. { "devices": [...], "environment": "live" }).
  • All errors return 4xx or 5xx with { "error": "<machine_code>", "message": "<human>" }.
  • Rate-limit headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) are present on every authenticated /v1/* response.
  • Tenant + environment headers (X-ZeroAuth-Tenant, X-ZeroAuth-Plan) are present on every authenticated /v1/* response.
  • All /v1/* endpoints accept the API key via Authorization: Bearer za_… or X-API-Key: za_…. Format: za_(live|test)_<48 hex chars>.

Authentication tiers

TierHeaderUsed by
Tenant API keyAuthorization: Bearer za_…/v1/*
Console JWT (24h)Authorization: Bearer eyJ… (issued by /api/console/login)/api/console/keys, /api/console/usage, /api/console/account, /api/console/overview, /api/console/audit
Admin static keyX-API-Key: <ADMIN_API_KEY>/api/admin/*, GET /api/leads
Unauthenticated/api/health, /, /docs/*, /dashboard/*, POST /api/leads/pilot, POST /api/leads/whitepaper, POST /api/console/signup, POST /api/console/login

Endpoints

Health

MethodPathDescription
GET/api/healthService + blockchain + ZKP + Poseidon subsystem status. Public.

Developer console (/api/console/*)

MethodPathAuthDescription
POST/api/console/signupnoneCreate a tenant + first live API key. Per-IP rate limit (10 / 15 min). Password policy: ≥12 chars, letter + digit, denylist.
POST/api/console/loginnoneExchange email + password for a 24h console JWT. Per-IP rate limit.
GET/api/console/keysconsole JWTList API keys for the authenticated tenant.
POST/api/console/keysconsole JWTCreate a new API key (max 10 active per tenant). Returns the raw key once.
DELETE/api/console/keys/:keyIdconsole JWTRevoke an API key. Irreversible.
GET/api/console/usageconsole JWTPer-tenant rate limit, monthly quota, history, recent calls.
GET/api/console/accountconsole JWTPlan, status, limits, account metadata.
GET/api/console/overviewconsole JWTCounts + 10 most-recent rows per stream (devices, users, verifications, attendance, audit). `?environment=live
GET/api/console/auditconsole JWTFilterable business audit events. `?environment=live

Central API — devices (/v1/devices)

MethodPathScopeDescription
POST/v1/devicesdevices:writeRegister a new device. Body: { name, externalId?, locationId?, batteryLevel?, metadata? }.
GET/v1/devicesdevices:readList devices for the tenant's environment. ?status=active|inactive|retired, ?limit=… (≤100).
PATCH/v1/devices/:deviceIddevices:writeMutate name, locationId, batteryLevel, status, metadata, lastSeenAt.

Central API — users (/v1/users)

MethodPathScopeDescription
POST/v1/usersusers:writeEnroll a tenant user. Body: { fullName, externalId?, email?, phone?, employeeCode?, primaryDeviceId?, metadata? }. No biometric template ever accepted.
GET/v1/usersusers:readList enrolled users. ?status=active|inactive, ?limit=….
PATCH/v1/users/:userIdusers:writeMutate user metadata.

Central API — verifications (/v1/verifications)

MethodPathScopeDescription
POST/v1/verificationsverifications:writeRecord a verification event. Body: { method, result, userId?, deviceId?, reason?, confidenceScore?, referenceId?, metadata?, occurredAt? }. methodzkp,fingerprint,face,depth,saml,oidc,manual. resultpass,fail,challenge.
GET/v1/verificationsverifications:readList events. ?method=…, ?result=…, ?limit=….

Central API — attendance (/v1/attendance)

MethodPathScopeDescription
POST/v1/attendanceattendance:writeRecord check-in/out. Body: { userId, type, deviceId?, verificationId?, result?, metadata?, occurredAt? }. typecheck_in,check_out. resultaccepted,rejected.
GET/v1/attendanceattendance:read?type=…, ?result=…, ?limit=….

Central API — audit (/v1/audit)

MethodPathScopeDescription
GET/v1/auditaudit:readRead-only business audit log. ?action=…, ?status=success|failure, ?limit=….

Identity + ZKP (/v1/auth/zkp/*, /v1/identity/*)

MethodPathScopeDescription
POST/v1/auth/zkp/registerzkp:registerHash biometric → DID, anchor on Base Sepolia, return secrets to the client once.
POST/v1/auth/zkp/verifyzkp:verifyVerify Groth16 proof, issue session JWT on success.
GET/v1/auth/zkp/noncenonce:createFresh nonce, 5-minute lifetime.
GET/v1/auth/zkp/circuit-infozkp:verifyCircuit metadata for client SDKs.
GET/v1/identity/meidentity:readUser profile from a session JWT (passed via X-Session-Token).
POST/v1/identity/logoutidentity:readInvalidate a session.
POST/v1/identity/refreshidentity:readRefresh-token → new access token.

SAML + OIDC (/v1/auth/saml/*, /v1/auth/oidc/*)

These endpoints are gated by ENABLE_DEMO_AUTH and currently simulate the assertion exchange — they are not production-quality SAML / OIDC. See A-03, A-04 in threat_model.md. Full implementations will land via @node-saml/node-saml and openid-client and the route signatures will not change.

MethodPathScopeDescription
GET/v1/auth/saml/loginsaml:loginReturns the IdP redirect URL.
POST/v1/auth/saml/callbacksaml:callbackSAML assertion → session JWT.
GET/v1/auth/saml/metadatasaml:loginSP metadata XML.
GET/v1/auth/oidc/authorizeoidc:authorizeOIDC /authorize redirect URL with PKCE.
POST/v1/auth/oidc/callbackoidc:callbackCode → session JWT.

Admin (/api/admin/*)

All require X-API-Key: <ADMIN_API_KEY>. Read-only.

MethodPathDescription
GET/api/admin/statsIn-process counters + blockchain identity count.
GET/api/admin/blockchainLive RPC info, contract addresses, deployer address.
GET/api/admin/privacy-auditZero-storage attestation.
GET/api/leadsAll marketing leads. ?type=pilot|whitepaper.

Marketing (/api/leads/*)

MethodPathAuthDescription
POST/api/leads/pilotnonePilot-access form: { name, company, email, size }.
POST/api/leads/whitepapernoneWhitepaper download form: { email }. Response includes downloadUrl.

Legacy /api/auth/* surface

These exist for backwards compatibility with internal tooling that pre-dates the /v1/* rollout. The legacy SAML and OIDC callbacks are gated by ENABLE_DEMO_AUTH for the same reason as their /v1/* counterparts. Document but plan to deprecate.

MethodPathDescription
GET/api/auth/meCurrent user from session JWT.
POST/api/auth/refreshRefresh tokens.
POST/api/auth/logoutInvalidate a session.
POST/api/auth/zkp/registerRegister identity. Same shape as /v1/auth/zkp/register minus tenant scoping.
POST/api/auth/zkp/verifyVerify proof.
GET/api/auth/zkp/nonceFresh nonce.
GET/api/auth/zkp/circuit-infoCircuit metadata.
GET/api/auth/saml/loginSAML login, demo-gated.
POST/api/auth/saml/callbackSAML callback, demo-gated.
GET/api/auth/saml/metadataSP metadata XML.
GET/api/auth/oidc/authorizeOIDC authorize, demo-gated.
POST/api/auth/oidc/callbackOIDC callback, demo-gated.
GET/api/auth/oidc/.well-known/openid-configurationOIDC discovery document. Note: jwks_uri is intentionally absent (HS256-only today).

LAST_UPDATED: 2026-05-12 OWNER: Pulkit Pareek