Developers
API reference
All JSON is snake_case; timestamps are ISO-8601 UTC; errors use a single envelope.
{ "error": { "code": "release_blocked", "message": "Release refused: the payment is HELD…", "details": {} } }Public verification API
| Method | Path | Description |
|---|---|---|
POST | /api/v1/verify/receipt | Verify a receipt. Body: receipt, content?, intended_action?, audience?. No side effects except an attempt log visible to the issuer. 60/min/IP. |
GET | /api/v1/issuers | Demo trust registry: issuers, status and public JWKs. Also at /.well-known/tumaini-trust-registry.json. |
POST | /api/v1/verify/evidence | Verify a signed case-evidence report (JWS). 30/min/IP. |
GET | /api/v1/evidence-keys | Public keys used to sign evidence reports. |
POST | /api/v1/sandbox/receipt | Issue a 1-hour sandbox receipt from Falcon Demo Bank (fictional). 10/min/IP. |
GET | /api/health | Service health: database, media service (model, C2PA) and contextual-analysis state. |
GET | /api/context/status | Contextual-analysis capability state: disabled | not_configured | configured_not_enabled | ready. Never exposes credentials. |
Consumer API (session cookie)
State-changing requests must be same-origin. Rate limit: 120 mutations/min per workspace.
| Method | Path | Description |
|---|---|---|
POST | /api/session | Create or resume an anonymous isolated demo workspace (httpOnly cookie). |
GET/POST | /api/cases | List / create verification cases. |
GET | /api/cases/{id} | Full case: assets, analyses, provenance, actions, challenges, timeline. |
POST | /api/cases/{id}/media | Upload audio/image/video (multipart, ≤ 4 MB). |
POST | /api/cases/{id}/receipt | Attach and verify a signed authorisation. |
POST | /api/cases/{id}/assess | Re-run extraction and risk policy. |
POST | /api/cases/{id}/decision | Record the final decision. |
GET | /api/cases/{id}/report | Signed evidence report (?download=1). |
POST | /api/actions | Create a protected (simulated) payment. idempotency_key required. |
POST | /api/actions/{id}/challenge | Send verification to a pre-registered trusted contact. |
POST | /api/actions/{id}/release | Release — refused unless VERIFIED and all checks satisfied. |
POST | /api/actions/{id}/cancel | Cancel. |
POST | /api/challenges/respond | Contact's answer, authenticated by one-time token. |
GET/POST | /api/trusted-contacts | List / add trusted contacts. |
GET/POST | /api/reports | List / file impersonation reports. |
POST | /api/context/analyze | Contextual analysis (Gemini adapter). JSON {text, consent: true, claimed_sender?, locale?, case_id?} or multipart with file. Requires consent; 503 context_unavailable until enabled; 10/hour/workspace. |
POST | /api/demo/scenarios/{key} | family-voice | government-notice | bank-payment | tampered-request | ai-outage | child-message (?lang=ar). |
POST | /api/demo/reset | Reset the caller's workspace only. |
Institution API (institution session)
POST /api/institution/login, /overview, /keys, /keys/{kid}/revoke, /communications, /communications/{id}/revoke, /verifications, /incidents, /audit, /c2pa/sign. Key generation, revocation, payment requests and C2PA signing require the admin role.
Contextual analysis response
Returned only when the capability is enabled. Observations are signals, never proof; assessment_with_context is computed by a function that can only add caution and is never saved.
{ "status": "completed", "role": "contextual_signal", "provider": "gemini", "model": "<configured>",
"observation": { "summary": "…", "claimed_identity": { "name": "Falcon Bank", "type": "institution" },
"requests": [ { "kind": "payment", "detail": "AED 150 fee" } ], "urls": ["…"], "urgency": true,
"secrecy": false, "indicators": [ … ], "explanation": { "en": "…", "ar": "…" }, "confidence": "medium" },
"usage": { "input_tokens": 420, "output_tokens": 180, "estimated_cost_usd": 0.0006 },
"redactions": { "card": 0, "iban": 0, "code": 1, "email": 0 }, "assessment_with_context": null }Webhooks
Not implemented. Planned: signed callbacks for verification outcomes and incident reports.
Error codes
| HTTP | Codes |
|---|---|
400 | invalid_request, invalid_json, unsupported_media, invalid_upload |
401 | no_session, no_institution_session, invalid_credentials |
403 | cross_origin, forbidden |
404 | case_not_found, action_not_found, contact_not_found, invalid_token |
409 | invalid_transition, checks_unsatisfied, release_blocked, guard_rejected, contact_not_pre_established, challenge_closed, case_closed |
410 | challenge_expired |
413 | file_too_large, payload_too_large |
422 | provider_blocked (contextual analysis) |
429 | rate_limited |
502/503/504 | context_unavailable, provider_timeout, provider_unreachable, provider_auth_failed, provider_invalid_response |
500 | internal_error (no internal details are returned) |