One typed action in, one signed proof out. Base URL https://api.useprovenant.xyz in production, or http://127.0.0.1:8000 when you run the sandbox locally.
The sandbox runs the full API with no provider keys — identity and notarization are simulated so you can integrate offline, then flip to real fulfillment by setting one environment variable. Requires Python 3.10+.
Start a verification (simulated — returns a signed proof immediately):
python agent_demo.py to watch a mock agent hit the notarization wall, call the tool, and verify the returned proof end to end.The verify_identity verb becomes real the moment a Stripe key is present — no code change. Stripe test mode is free.
sk_test_…).dashboard.stripe.com/identity (test mode is free).Now verify-identity returns a real hosted url. Open it, complete Stripe's verification (test document images in test mode), then poll GET /v1/identity/{action_id} until status is verified and a signed proof appears. Full deploy steps (Render + custom domain + webhook) are in SETUP_LIVE.md.
An action is a typed request to perform one real-world verb. Every action resolves to one of: verified/completed (with a proof), pending (awaiting a human session), rejected (failed validation or compliance), or failed.
A proof is a JSON object of substantive claims plus a key_id, content_hash, signature, and public_key. Verify it offline, or via POST /v1/verify. Verification recomputes the canonical hash and checks the signature against the trusted key for key_id — not the embedded key — so a re-signed forgery is rejected.
The local sandbox is unauthenticated for development. Production uses a bearer API key on every request:
POST/v1/actions/verify-identity
Starts an IAL2 identity-verification session. Returns immediately; with Stripe configured the response is pending with a hosted url.
| Field | Type | Notes |
|---|---|---|
| name | string | required |
| string | required | |
| return_url | string | optional redirect after the session |
GET/v1/identity/{action_id} — polls the provider; once verified, the response includes a signed proof.
POST/v1/actions/notarize Sandbox
Notarizes a document via remote online notarization. Sandbox fulfillment today; licensed RON network in private beta.
| Field | Type | Notes |
|---|---|---|
| document_name | string | required |
| document_sha256 | string | required, 64 hex chars |
| jurisdiction | string | 2-letter US state code |
| parties | array | each: name, email, role |
| idempotency_key | string | optional, retry-safe |
GET/v1/actions/{action_id} returns a stored notarization result.
POST/v1/verify — body { "proof": { … } }. Returns { "valid": true, "reason": "valid" }. Also runs offline: python -m tangible.verify proof.json.
POST/v1/proofs/{proof_id}/revoke — marks a proof revoked. Subsequent verification returns valid: false, reason: "proof has been revoked".
GET/v1/ledger/verify — recomputes the hash chain and returns { valid, reason, entries }. Any tampering, insertion, or reordering breaks the chain.
POST/v1/webhooks/stripe — receives Stripe Identity events. Subscribe to identity.verification_session.verified; set STRIPE_WEBHOOK_SECRET to enforce signature verification. On a verified event, Provenant finalizes the session and issues the proof — no polling needed.
| Status | Meaning |
|---|---|
| 200 | OK — check the body's status for rejected actions |
| 400 | Bad request or webhook signature failure |
| 404 | Unknown action or session id |
| 422 | Validation error (bad email, malformed sha256, duplicate parties) |