# API reference: the immut agent API v1 This is the curated endpoint set that covers the entire proof lifecycle: create a proof from a hash, poll it, download the certificate, and verify publicly. It is deliberately small. The full interactive reference for every other endpoint (folders, users, billing, key management) lives at [app.immut.io/docs](https://app.immut.io/docs). **Base URL:** `https://backend.immut.io/api/v1` **CORS-open mirror** (for browser-based callers): `https://backend.immut.io/api/public/v1` **Machine-readable version of this page:** [`GET https://backend.immut.io/api/v1/docs`](https://backend.immut.io/api/v1/docs) (no auth) and [/docs/openapi.json](/docs/openapi.json) ## How do I authenticate? Every authenticated endpoint takes a Bearer token: ``` Authorization: Bearer imut_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ``` Keys are created by a human account owner at [app.immut.io/account?tab=api-keys](https://app.immut.io/account?tab=api-keys) (Professional and Enterprise plans include API access) and carry scopes. Agents should hold `documents:write` and `certificates:read` only. Rate limits: 60 requests per minute, 10,000 per day per key; a 429 response carries a `Retry-After` header. Proofs created by paid organisations anchor to **XRPL mainnet** and are permanent. --- ## POST /proofs Create a proof from a locally computed SHA-256 hash. The file itself is never uploaded. Requires scope `documents:write`. Idempotent per hash and workspace. **Request body** | Field | Type | Required | Notes | |---|---|---|---| | `hash` | string | yes | 64-character hex SHA-256 digest of the file | | `workspace` | string | yes | Workspace id (see GET /workspaces) | | `fileName` | string | no | Display name, max 255 chars | | `fileSize` | number | no | Bytes | | `mimeType` | string | no | Defaults to `application/octet-stream` | | `metadata` | object | no | `metadata.description` (max 500 chars) appears on listings | **Response 201** ```json { "success": true, "data": { "proofId": "6a55f4b3f8878465844f8b43", "txHash": "02790DA05EF2999C77A2B462CE0F7A1E11A52FB295F3AE3FF542112B12B7A8E5", "verifyUrl": "https://livenet.xrpl.org/transactions/.../detailed", "certPath": "/api/v1/certificates/6a55f4b3f8878465844f8b43", "ledger": "mainnet", "ledgerIndex": 105588998, "timestamp": "2026-07-14T08:34:59.412Z", "hashScheme": "hmac-sha256-nonce-v3", "proofCommitment": "64-char hex anchored on-chain", "proofNonce": "64-char hex, KEEP THIS: required to verify a salted proof" } } ``` If the hash was already proven in that workspace, the response is 200 with `"alreadyProven": true` and the same data shape. Store `proofNonce` durably; it is confidential to the file owner and required for verification under the default salted scheme (see [Security](/docs/security)). **Errors:** 400 `INVALID_HASH`, 400 `INVALID_WORKSPACE`, 401, 403 `API_ACCESS_DISABLED`, 429, 502 `XRPL_ERROR` (safe to retry: the failed attempt is rolled back). --- ## GET /proofs/{proofId} Poll a proof's status and details. Requires scope `documents:read`. Add `?includeSalt=true` to include `proofNonce` in the response. **Response 200** ```json { "success": true, "data": { "proofId": "6a55f4b3f8878465844f8b43", "txHash": "0279...A8E5", "verifyUrl": "https://livenet.xrpl.org/transactions/.../detailed", "certPath": "/api/v1/certificates/6a55f4b3f8878465844f8b43", "ledger": "mainnet", "ledgerIndex": 105588998, "timestamp": "2026-07-14T08:34:59.412Z", "blockchainStatus": "completed", "fileName": "report-final.pdf", "fileHash": "d287...ff6b", "hashScheme": "hmac-sha256-nonce-v3", "proofCommitment": "9f2c...b9c" } } ``` `blockchainStatus` is `pending`, `processing`, or `completed`. **Errors:** 400 `INVALID_PROOF_ID`, 404 `PROOF_NOT_FOUND`. --- ## GET /certificates/{proofId} Download the court-ready certificate PDF for a proof. Requires scope `certificates:read`. The PDF includes the transaction hash, ledger details, verification guide, and (for salted proofs) the proof salt/nonce. ```bash curl -s https://backend.immut.io/api/v1/certificates/$PROOF_ID \ -H "Authorization: Bearer $IMMUT_API_KEY" \ -o certificate.pdf ``` --- ## GET /api/public/verify/{txHash} Public keyless verification. Full URL: `https://backend.immut.io/api/public/verify/{txHash}`. Returns the on-chain record for any immut transaction hash, resolving the correct ledger network per proof. **Response 200** ```json { "success": true, "data": { "transactionHash": "0279...A8E5", "network": "mainnet", "verified": true, "explorerUrl": "https://livenet.xrpl.org/transactions/.../detailed", "ledgerIndex": 105588998, "ledgerCloseTime": "2026-07-14T08:35:02.000Z", "memo": { "fileHash": "...", "hashScheme": "hmac-sha256-nonce-v3" } } } ``` To confirm a file matches: recompute `sha256(file)`; if `memo.hashScheme` is `sha256-plain-v1`, compare directly with `memo.fileHash`; if it is a salted scheme, compute `HMAC-SHA-256(key=proofNonce, message=sha256 digest bytes)` and compare. The browser page at [app.immut.io/verify](https://app.immut.io/verify) does this without any tooling. --- ## GET /workspaces List the organisation's workspaces. Requires scope `workspaces:read`. Used once during setup to find the `workspace` id for POST /proofs. ```json { "success": true, "data": [ { "_id": "6a343b4d0de29d485cd1f710", "name": "Default Workspace" } ] } ``` --- ## GET /documents List existing proofs with pagination and filters. Requires scope `documents:read`. Query params: `page` (default 1), `limit` (default 20, max 100), `workspace`, `blockchainStatus`, `search`. Response carries `data` (array) and `meta` (`page`, `limit`, `total`). --- ## Webhooks: GET /webhooks, POST /webhooks Get notified instead of polling. Requires scope `webhooks:manage`. **POST body:** `{ "url": "https://your-endpoint", "events": ["upload.completed", "certificate.generated"], "description": "optional" }` Available events include `document.created`, `upload.completed`, `upload.failed`, `certificate.generated`, `workspace.created`. The response includes a signing `secret` (shown once) used to HMAC-sign deliveries. URLs must be HTTPS in production. `POST /webhooks/test` sends a test delivery; `GET /webhooks/deliveries` lists recent deliveries. --- ## GET /docs `https://backend.immut.io/api/v1/docs`, no auth. Machine-readable JSON quickstart covering this whole surface: base URLs, auth, endpoint skeletons, rate limits, verification recipes, and security notes. Agents that only have the API base URL can bootstrap from it. ## What is deliberately not in this reference? Multipart file upload. immut's agent contract is hash-only: file bytes never leave your environment, which is the property that makes the privacy model work. Humans can upload via the app at [app.immut.io](https://app.immut.io); the full endpoint catalogue is at [app.immut.io/docs](https://app.immut.io/docs).