{"openapi":"3.1.0","info":{"title":"tryVidimus API","version":"1","description":"\nThe tryVidimus API turns the photos and videos taken during a transaction into **sealed proofs** that anyone can verify independently. Each file is captured live, signed (C2PA) and timestamped (RFC 3161) by a neutral third party, so neither side can later say the file was edited.\n\n## How it works\n\n1. **Create a capture session** with `POST /v1/capture-sessions`. You get a `capture_url`.\n2. **Send that link** to the person who takes the photos (the provider or the recipient). They capture on their phone; the files go straight to storage and never pass through your servers.\n3. **We seal the proof**: we verify the files, sign them and obtain a timestamp for the proof, usually within seconds. You receive a `proof.sealed` webhook, or you read the proof with `GET /v1/proofs/{id}`.\n4. **Anyone can verify it** with the public routes, without an account.\n\n## Base URL and format\n\n`https://api.tryvidimus.com`. Everything is JSON over HTTPS; plain HTTP is not served. Identifiers are prefixed strings (`prf_…` for proofs, `cps_…` for capture sessions, `med_…` for media).\n\n## Authentication\n\nSend your API key as a bearer token:\n\n```\nAuthorization: Bearer sk_test_…\n```\n\nA key belongs to one organization and carries **scopes**: `create_proof` (create capture sessions), `read_proof` (read proofs), `manage_webhooks` (manage webhook endpoints), `manage_templates` (manage capture templates and capture themes) and `manage_settings` (manage your settings). A call without the right scope fails with `403 insufficient_scope`. `GET /v1/me` tells you which key you are using.\nThe capture page routes use the session token in the URL instead of a key, and the public verification routes need nothing.\n\n## Timestamps\n\nEvery proof carries its **own RFC 3161 timestamp token**, issued by an independent timestamp authority and checked before the proof is sealed. Two dates are never mixed up. `captured_at` (on each file) is the time **our service observed** the file: it is not qualified. `gen_time` (on the timestamp) is the time **certified by the authority**: for a qualified timestamp (`qualified: true`) it is an eIDAS qualified timestamp, given to the second, and proves the proof existed at the latest at that time. In test mode the timestamp is simulated and proves nothing. Anyone can check a timestamp without us: with the `manifest_sha256` and the token from the public bundle, `openssl ts -verify -digest <manifest_sha256> -in proof.tsr -CAfile chain.pem`.\n\n## Test and live mode\n\nThe prefix of the key sets the mode: `sk_test_…` for the sandbox, `sk_live_…` for production. The two modes never share data: a test key never sees a live proof (it gets a `404`). In test mode nothing is billed and timestamps are **simulated**: they have no legal value and verification reports `test_mode`.\n\n## Languages\n\nThe capture page and the texts of a capture template can be shown in several languages. Give the language of the person who captures with `locale` when you create a capture session: a BCP 47 tag such as `en`, `fr`, `es`, `de` or `pt-BR`. A capture template (`POST /v1/capture-templates`) can hold each text in several languages; when a language is missing, the page uses the base language (`pt` for `pt-BR`), then the default language of the template, then English.\n\n## Look of the capture page\n\nCreate a capture **theme** with `POST /v1/capture-themes`: a name, a main color, a language, and a logo with `PUT /v1/capture-themes/{id}/logo`. You can have several themes, for example one per brand. Choose the theme of a capture template with `theme_id` in `POST /v1/capture-templates`; without it, the capture page uses your default theme. Themes are the same in test and live.\n\n## Before and after\n\nTo compare the state of an item at two moments (a handover and a return, for example), capture the first one as usual, wait until its proof is sealed, then create the second capture session with `compare_to` set to the `id` of the first proof. The first is the \"before\", the second the \"after\". The \"before\" must be sealed, with the same `external_reference` and the same `party`; a proof is either a \"before\" or an \"after\", never both, and has at most one partner. The \"after\" uses the same template as the \"before\", so the person is asked for at least as many photos, shot by shot (leave `template_id` out). Each proof tells its partner: `compare_to` on the \"after\", `compared_by` on the \"before\". To list the proofs still waiting for their \"after\", use `GET /v1/proofs?linked=false`.\n\nIf two links aim at the same \"before\", the first capture to be finished wins. The other is not saved: finishing it fails with `409 compare_to_already_used`, no proof is created, no credit is used, and you receive a `capture_session.rejected` webhook (its body carries `session_id`, `code`, `compare_to`, `external_reference`, `party`, `stage` and `rejected_at`). The refusal also appears in your logs. We do not compare the photos or judge the condition of the item: the proofs only show what each party captured, and weighing them is up to you.\n\n## Idempotency\n\n`POST /v1/capture-sessions` requires an `Idempotency-Key` header: a unique value (for example a UUID) for each creation you attempt. If a call fails on the network, send it again with the **same** key: you get the original response (with the header `Idempotent-Replayed: true`) instead of a second session. Keys are kept for 1 hour. Reusing a key with a different body fails with `422 idempotency_key_reused`; a request still being processed fails with `409 request_in_progress` and a `Retry-After` header.\n\n## Pagination\n\nList routes use cursors, not page numbers. Pass `limit` (1 to 100, 50 by default) and read `has_more` and `next_cursor` in the answer; give `next_cursor` back as `cursor` to get the next page. A proof created while you page through the list never causes a duplicate or a gap. Treat the cursor as opaque.\n\n## Errors\n\nErrors follow RFC 9457 (`application/problem+json`):\n\n```json\n{\n  \"type\": \"https://api.tryvidimus.com/errors/proof-not-found\",\n  \"title\": \"Proof not found\",\n  \"status\": 404,\n  \"code\": \"proof_not_found\"\n}\n```\n\nBranch on `code`, which is stable. `title` is for people and can change. `field` names the faulty field of a `422`.\n\n## Rate limits\n\nEach key has a number of requests per minute (60 by default). Calls that create things cost more than reads. Every authenticated answer carries `RateLimit-Limit` and `RateLimit-Remaining`. Past the limit you get `429 rate_limited` with a `Retry-After` header, in seconds.\n\n## Webhooks\n\nInstead of polling, declare an endpoint with `POST /v1/webhook-endpoints` and choose the events: `proof.sealed`, `proof.failed`, `capture_session.completed`, `capture_session.rejected`, and two reserved for a later version, `capture_session.expired` and `dossier.ready` (accepted, but never sent yet). We `POST` a JSON body to your HTTPS URL. `events` (plural) is the list you subscribe to when you create the endpoint; each body we send carries `event` (singular), the name of the one event it reports (for example `\"event\": \"proof.sealed\"`), followed by the fields of that event. The exact body of each message, with the meaning of every field, is in the **Webhook events** group of this reference. A capture that ends produces two messages, `capture_session.completed` then `proof.sealed`, each sent on its own. If your server does not answer with a `2xx` status, we retry after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then give up.\n\n`capture_session.completed` is sent when the person has finished the capture, a few seconds after the files are saved and **before** the proof is sealed. Its body carries `session_id`, `proof_id`, `external_reference`, `party`, `stage` and `completed_at`. It is the reliable signal that the capture is over, since the person may close the page before being taken back to your app: wait for `proof.sealed` before relying on the proof. Endpoints created before this event existed do not receive it until they subscribe to it.\n\nTo see what was sent and why a delivery failed, read it with `GET /v1/webhook-deliveries/{id}` (or open it in your account): you get the JSON body of the event exactly as your endpoint received it, which you can copy to replay the event on your own server, the HTTP status and the beginning of the answer of your server on the last attempt, and the reason of a failure. To try your server, send yourself an example event with `POST /v1/webhook-endpoints/{id}/test`: it has the same fields as a real event, with example values and `\"test\": true`, and it is signed with your secret like any delivery, so you can check your signature code end to end. At most 20 test events per endpoint per hour.\n\nEach delivery carries three headers:\n\n| Header | Meaning |\n| --- | --- |\n| `X-Signature` | `t=<unix seconds>,v1=<signature>` (one `v1` per active secret) |\n| `X-Webhook-Id` | Identifier of this delivery attempt |\n| `X-Event-Id` | Identifier of the event: **identical across retries**, use it to ignore duplicates |\n\n**Verify every call**: the signature is the HMAC-SHA256, in lowercase hexadecimal, of `<t>.<raw body>`, keyed with your endpoint secret (the whole string, including `whsec_`). Compare it with each `v1` value, and reject the call if `t` is more than 5 minutes old.\n\n```js\nimport { createHmac, timingSafeEqual } from 'node:crypto';\n\nfunction isValid(header, rawBody, secret, toleranceSeconds = 300) {\n  const parts = header.split(',');\n  const t = Number(parts.find((p) => p.startsWith('t='))?.slice(2));\n  if (!Number.isFinite(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;\n  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();\n  return parts\n    .filter((p) => p.startsWith('v1='))\n    .some((p) => {\n      const given = Buffer.from(p.slice(3), 'hex');\n      return given.length === expected.length && timingSafeEqual(given, expected);\n    });\n}\n```\n\nThe secret is shown **once**, when the endpoint is created or rotated. Rotation keeps the old secret valid for a while so you can switch without losing a call.\n\nTo see what was sent to your endpoints and what your server answered, read the delivery log with `GET /v1/webhook-deliveries` (filter by `endpoint_id` or `status`, for example `abandoned`). It never contains the content that was sent.\n"},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{}},"paths":{"/health":{"get":{"summary":"Service status","tags":["Health"],"description":"Public. Tells whether the API is up, with its version and the commit it runs. It does not check the other services.","responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","description":"Always `ok` when the API answers.","enum":["ok"]},"version":{"type":"string","description":"Version of the API.","examples":["0.2.0"]},"commit":{"type":"string","description":"The commit the API was built from.","examples":["4203fc32c36a38f00d71e6b2c959d20c54abf6f5"]}},"required":["status","version","commit"],"additionalProperties":false}}}}}}},"/health/details":{"get":{"summary":"Detailed status (monitoring)","tags":["Health"],"description":"Reserved for monitoring: needs the monitoring token, not an API key. Checks the services the API depends on.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded"],"description":"`degraded` when a check fails."},"version":{"type":"string","description":"Version of the API."},"commit":{"type":"string","description":"The commit the API was built from."},"checks":{"type":"object","properties":{"database":{"type":"object","properties":{"status":{"type":"string","enum":["ok","error","not_configured"],"description":"`ok`, `error`, or `not_configured` when the service is not set up (never reported as `ok`)."},"latency_ms":{"type":"number","description":"How long the check took, in milliseconds."}},"required":["status"],"additionalProperties":false,"description":"The database."},"storage":{"type":"object","properties":{"status":{"type":"string","enum":["ok","error","not_configured"],"description":"`ok`, `error`, or `not_configured` when the service is not set up (never reported as `ok`)."},"latency_ms":{"type":"number","description":"How long the check took, in milliseconds."}},"required":["status"],"additionalProperties":false,"description":"The file storage."},"timestamp_authority":{"type":"object","properties":{"status":{"type":"string","enum":["ok","error","not_configured"],"description":"`ok`, `error`, or `not_configured` when the service is not set up (never reported as `ok`)."},"latency_ms":{"type":"number","description":"How long the check took, in milliseconds."}},"required":["status"],"additionalProperties":false,"description":"The timestamp authority."}},"required":["database","storage","timestamp_authority"],"additionalProperties":false,"description":"One check per dependency."}},"required":["status","version","commit","checks"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["ok","degraded"],"description":"`degraded` when a check fails."},"version":{"type":"string","description":"Version of the API."},"commit":{"type":"string","description":"The commit the API was built from."},"checks":{"type":"object","properties":{"database":{"type":"object","properties":{"status":{"type":"string","enum":["ok","error","not_configured"],"description":"`ok`, `error`, or `not_configured` when the service is not set up (never reported as `ok`)."},"latency_ms":{"type":"number","description":"How long the check took, in milliseconds."}},"required":["status"],"additionalProperties":false,"description":"The database."},"storage":{"type":"object","properties":{"status":{"type":"string","enum":["ok","error","not_configured"],"description":"`ok`, `error`, or `not_configured` when the service is not set up (never reported as `ok`)."},"latency_ms":{"type":"number","description":"How long the check took, in milliseconds."}},"required":["status"],"additionalProperties":false,"description":"The file storage."},"timestamp_authority":{"type":"object","properties":{"status":{"type":"string","enum":["ok","error","not_configured"],"description":"`ok`, `error`, or `not_configured` when the service is not set up (never reported as `ok`)."},"latency_ms":{"type":"number","description":"How long the check took, in milliseconds."}},"required":["status"],"additionalProperties":false,"description":"The timestamp authority."}},"required":["database","storage","timestamp_authority"],"additionalProperties":false,"description":"One check per dependency."}},"required":["status","version","commit","checks"],"additionalProperties":false}}}}}}},"/v1/capture-sessions":{"post":{"summary":"Create a capture session","tags":["Capture sessions"],"description":"Creates a one-time capture session for one transaction and returns a `capture_url`. Send that link to the person who must take the photos or videos (the provider or the recipient): the files go from their phone straight to storage and never pass through your servers. Requires the `create_proof` scope and an `Idempotency-Key` header. The link expires at `expires_at` (30 minutes by default). The proof appears once the person has finished. A capture template (`template`, or the one matching `stage` and `category`) sets the shots the person is asked to take and the texts they see. With a production key, a session is refused with `402 insufficient_balance` when your available balance cannot cover one more proof: the available balance is your balance minus the proofs still promised (captures open or not yet sealed), so your balance never goes below zero. Add funds to open new ones (a capture already started always finishes). Sandbox keys are never refused.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"external_reference":{"type":"string","pattern":"^[A-Za-z0-9_.:/#=+-]{1,200}$","description":"Your own identifier for the transaction (a booking, an order…). It ties together all the proofs of one transaction. A technical identifier only: no e-mail address, no name, no spaces.","examples":["booking_4471"]},"party":{"type":"string","enum":["provider","recipient"],"description":"Who takes the photos: `provider` (the one who hands the item over) or `recipient` (the one who receives it).","examples":["provider"]},"stage":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"The moment of the transaction, as an identifier of your choice (`pickup`, `return`, `delivery`…). Lowercase letters, digits, `_`, `.` and `-`, 64 characters at most.","examples":["pickup"]},"category":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"The kind of item or service, as an identifier of your choice. Same format as `stage`.","examples":["vehicle"]},"template_id":{"type":"string","maxLength":80,"description":"The capture template to use, by its `id` (`tpl_…`, from `POST /v1/capture-templates`): it sets the shots the person is asked to take and the welcome and completion texts. Leave it out to use the active template that matches `stage` and `category`, if any. `422 template_not_found` if it does not exist, is archived or belongs to the other mode.","examples":["tpl_01m4akapdbe8e8qq3er9r5qwyj"]},"compare_to":{"type":"string","maxLength":80,"description":"Makes this capture the \"after\" of a proof you already have (the \"before\"), by its `id` (`prf_…`). The \"before\" must be sealed, with the same `external_reference` and the same `party`, and must not itself be an \"after\". The person is asked for at least as many photos, shot by shot, as the \"before\" has, using the same template (so leave `template_id` out). A proof can be compared to only one other: if two links aim at the same \"before\", the first capture to finish wins and the other is rejected with `409 compare_to_already_used` (and a `capture_session.rejected` webhook). Errors: `422 compare_to_not_found`, `compare_to_not_sealed`, `compare_to_mismatch`, `compare_to_is_after`, `compare_template_mismatch`; `409 compare_to_already_used`.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"locale":{"type":"string","maxLength":35,"pattern":"^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$","description":"The language of the person who captures, as a BCP 47 tag: `en`, `fr`, `es`, `de`, `pt-BR`, `es-419`, `zh-Hans`… The capture page and the texts of the template are shown in this language when it has them (see `GET /v1/capture-templates`). Leave it out to use the language of your capture theme.","examples":["de"]},"return_url":{"type":"string","maxLength":2048,"format":"uri","description":"Where to send the person once the capture is finished: the capture page shows its completion text, then takes the person back to this address after a few seconds, with `proof_id` and `session_id` added to it. Its site must be in your allowed return origins (`PATCH /v1/settings`), else the call fails with `422 return_url_not_allowed`. `https` only; `http://localhost` is accepted for sandbox keys. Leave it out to keep the person on the page.","examples":["https://app.example.com/bookings/4471/capture-done"]},"location_reference":{"type":"string","maxLength":100,"pattern":"^[A-Za-z0-9_.:/#=+-]{1,200}$","description":"Your own identifier for the place of the transaction (a site, a locker…). Same format as `external_reference`, 100 characters at most.","examples":["site_paris_12"]}},"required":["external_reference","party"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{8,255}$"},"example":"7f3c1e2a-9b4d-4e6f-8a1c-5d2b3e4f6a7b","in":"header","name":"idempotency-key","required":true,"description":"A unique value for each creation you attempt (for example a UUID), 8 to 255 characters: letters, digits, `_`, `.`, `:` and `-`. Send it again, unchanged, to retry safely: you get the original answer. Kept for 24 hours."}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the capture session.","examples":["cps_01m4akapdbe8e8qq3er9r5qwyj"]},"capture_url":{"type":"string","description":"The link to send to the person who takes the photos. It works once and expires at `expires_at`.","examples":["https://capture.tryvidimus.com/3f9aXq…"]},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the link stops working (ISO 8601, UTC).","examples":["2026-10-07T12:00:00.000Z"]},"mode":{"type":"string","enum":["live","test"],"description":"The mode of your API key, which the session inherits.","examples":["test"]},"compare_to":{"description":"The proof this capture will be compared to (the `compare_to` you sent); `null` for an ordinary capture.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"],"type":["string","null"]}},"required":["id","capture_url","expires_at","mode","compare_to"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/webhook-endpoints":{"post":{"summary":"Create a webhook endpoint","tags":["Webhook endpoints"],"description":"Declares a URL to receive events (see the *Webhooks* section above for the signature). Returns the endpoint with its **secret, shown only this once**. Up to 10 endpoints per mode; `422 invalid_webhook_url` if the URL is not acceptable. Requires the `manage_webhooks` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"description":"Where we send the events. HTTPS only, on a public domain name (no IP address, no `localhost`, no internal name), without credentials or fragment, on port 443 or above 1023.","examples":["https://example.com/webhooks/tryvidimus"]},"events":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["proof.sealed","proof.failed","capture_session.expired","capture_session.completed","capture_session.rejected","dossier.ready"]},"description":"The events to receive, without duplicates: `proof.sealed`, `proof.failed`, `capture_session.completed`, `capture_session.rejected`, and two reserved for a later version, `capture_session.expired` and `dossier.ready` (accepted, but never sent yet). Each message we send then names its event in the `event` field of its body.","examples":[["proof.sealed","proof.failed"]]},"description":{"type":"string","maxLength":200,"description":"A note for yourself, 200 characters at most.","examples":["Production, billing service"]}},"required":["url","events"],"additionalProperties":false}}}},"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the webhook endpoint.","examples":["whe_01m4akapdbe8e8qq3er9r5qwyj"]},"mode":{"type":"string","enum":["live","test"],"description":"The endpoint belongs to the mode of the key that created it, and only receives events of that mode.","examples":["test"]},"url":{"type":"string","description":"Where the events are sent.","examples":["https://example.com/webhooks/tryvidimus"]},"description":{"description":"Your note, if any.","type":["string","null"]},"events":{"type":"array","items":{"type":"string","enum":["proof.sealed","proof.failed","capture_session.expired","capture_session.completed","capture_session.rejected","dossier.ready"]},"description":"The events this endpoint receives.","examples":[["proof.sealed","proof.failed"]]},"status":{"type":"string","enum":["active","disabled"],"description":"`disabled` endpoints receive nothing."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the endpoint was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."},"secrets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the secret.","examples":["whs_01m4akapdbe8e8qq3er9r5qwyj"]},"hint":{"type":"string","description":"The first characters of the secret, to recognize it. Never enough to sign.","examples":["whsec_AbCd"]},"status":{"type":"string","enum":["active","expired"],"description":"`active`: used to sign deliveries. `expired`: no longer used."},"expires_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When this secret stops being used, during a rotation; `null` for the current secret."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the secret was created (ISO 8601, UTC)."}},"required":["id","hint","status","expires_at","created_at"],"additionalProperties":false},"description":"The signing secrets: one, or two during a rotation. Never the secret itself."},"secret":{"type":"string","description":"The signing secret in clear. **This is the only time it is shown**: store it now. It is never returned again, and we cannot read it back.","examples":["whsec_…"]}},"required":["id","mode","url","description","events","status","created_at","updated_at","secrets","secret"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"get":{"summary":"List webhook endpoints","tags":["Webhook endpoints"],"description":"Lists the webhook endpoints of your organization, in the mode of your key. Secrets are never included. Requires the `manage_webhooks` scope.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the webhook endpoint.","examples":["whe_01m4akapdbe8e8qq3er9r5qwyj"]},"mode":{"type":"string","enum":["live","test"],"description":"The endpoint belongs to the mode of the key that created it, and only receives events of that mode.","examples":["test"]},"url":{"type":"string","description":"Where the events are sent.","examples":["https://example.com/webhooks/tryvidimus"]},"description":{"description":"Your note, if any.","type":["string","null"]},"events":{"type":"array","items":{"type":"string","enum":["proof.sealed","proof.failed","capture_session.expired","capture_session.completed","capture_session.rejected","dossier.ready"]},"description":"The events this endpoint receives.","examples":[["proof.sealed","proof.failed"]]},"status":{"type":"string","enum":["active","disabled"],"description":"`disabled` endpoints receive nothing."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the endpoint was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."},"secrets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the secret.","examples":["whs_01m4akapdbe8e8qq3er9r5qwyj"]},"hint":{"type":"string","description":"The first characters of the secret, to recognize it. Never enough to sign.","examples":["whsec_AbCd"]},"status":{"type":"string","enum":["active","expired"],"description":"`active`: used to sign deliveries. `expired`: no longer used."},"expires_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When this secret stops being used, during a rotation; `null` for the current secret."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the secret was created (ISO 8601, UTC)."}},"required":["id","hint","status","expires_at","created_at"],"additionalProperties":false},"description":"The signing secrets: one, or two during a rotation. Never the secret itself."}},"required":["id","mode","url","description","events","status","created_at","updated_at","secrets"],"additionalProperties":false},"description":"Your webhook endpoints, in the mode of the key."}},"required":["data"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/webhook-endpoints/{id}":{"get":{"summary":"Get a webhook endpoint","tags":["Webhook endpoints"],"description":"Returns one webhook endpoint. The secret is never included. Requires the `manage_webhooks` scope.","parameters":[{"schema":{"type":"string"},"example":"whe_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the webhook endpoint."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the webhook endpoint.","examples":["whe_01m4akapdbe8e8qq3er9r5qwyj"]},"mode":{"type":"string","enum":["live","test"],"description":"The endpoint belongs to the mode of the key that created it, and only receives events of that mode.","examples":["test"]},"url":{"type":"string","description":"Where the events are sent.","examples":["https://example.com/webhooks/tryvidimus"]},"description":{"description":"Your note, if any.","type":["string","null"]},"events":{"type":"array","items":{"type":"string","enum":["proof.sealed","proof.failed","capture_session.expired","capture_session.completed","capture_session.rejected","dossier.ready"]},"description":"The events this endpoint receives.","examples":[["proof.sealed","proof.failed"]]},"status":{"type":"string","enum":["active","disabled"],"description":"`disabled` endpoints receive nothing."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the endpoint was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."},"secrets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the secret.","examples":["whs_01m4akapdbe8e8qq3er9r5qwyj"]},"hint":{"type":"string","description":"The first characters of the secret, to recognize it. Never enough to sign.","examples":["whsec_AbCd"]},"status":{"type":"string","enum":["active","expired"],"description":"`active`: used to sign deliveries. `expired`: no longer used."},"expires_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When this secret stops being used, during a rotation; `null` for the current secret."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the secret was created (ISO 8601, UTC)."}},"required":["id","hint","status","expires_at","created_at"],"additionalProperties":false},"description":"The signing secrets: one, or two during a rotation. Never the secret itself."}},"required":["id","mode","url","description","events","status","created_at","updated_at","secrets"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"patch":{"summary":"Update a webhook endpoint","tags":["Webhook endpoints"],"description":"Changes the URL, the events, the note or the status of an endpoint. Send only the fields to change, at least one. Use `status: disabled` to pause deliveries without deleting the endpoint. Requires the `manage_webhooks` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"description":"Where we send the events. HTTPS only, on a public domain name (no IP address, no `localhost`, no internal name), without credentials or fragment, on port 443 or above 1023.","examples":["https://example.com/webhooks/tryvidimus"]},"events":{"minItems":1,"maxItems":6,"type":"array","items":{"type":"string","enum":["proof.sealed","proof.failed","capture_session.expired","capture_session.completed","capture_session.rejected","dossier.ready"]},"description":"The events to receive, without duplicates: `proof.sealed`, `proof.failed`, `capture_session.completed`, `capture_session.rejected`, and two reserved for a later version, `capture_session.expired` and `dossier.ready` (accepted, but never sent yet). Each message we send then names its event in the `event` field of its body.","examples":[["proof.sealed","proof.failed"]]},"description":{"anyOf":[{"type":"string","maxLength":200,"description":"A note for yourself, 200 characters at most.","examples":["Production, billing service"]},{"type":"null"}],"description":"A note for yourself, 200 characters at most. Send `null` to remove it."},"status":{"type":"string","enum":["active","disabled"],"description":"`disabled` stops all deliveries to this endpoint; `active` resumes them."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"example":"whe_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the webhook endpoint."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the webhook endpoint.","examples":["whe_01m4akapdbe8e8qq3er9r5qwyj"]},"mode":{"type":"string","enum":["live","test"],"description":"The endpoint belongs to the mode of the key that created it, and only receives events of that mode.","examples":["test"]},"url":{"type":"string","description":"Where the events are sent.","examples":["https://example.com/webhooks/tryvidimus"]},"description":{"description":"Your note, if any.","type":["string","null"]},"events":{"type":"array","items":{"type":"string","enum":["proof.sealed","proof.failed","capture_session.expired","capture_session.completed","capture_session.rejected","dossier.ready"]},"description":"The events this endpoint receives.","examples":[["proof.sealed","proof.failed"]]},"status":{"type":"string","enum":["active","disabled"],"description":"`disabled` endpoints receive nothing."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the endpoint was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."},"secrets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the secret.","examples":["whs_01m4akapdbe8e8qq3er9r5qwyj"]},"hint":{"type":"string","description":"The first characters of the secret, to recognize it. Never enough to sign.","examples":["whsec_AbCd"]},"status":{"type":"string","enum":["active","expired"],"description":"`active`: used to sign deliveries. `expired`: no longer used."},"expires_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When this secret stops being used, during a rotation; `null` for the current secret."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the secret was created (ISO 8601, UTC)."}},"required":["id","hint","status","expires_at","created_at"],"additionalProperties":false},"description":"The signing secrets: one, or two during a rotation. Never the secret itself."}},"required":["id","mode","url","description","events","status","created_at","updated_at","secrets"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"delete":{"summary":"Delete a webhook endpoint","tags":["Webhook endpoints"],"description":"Deletes an endpoint: it receives nothing more. Requires the `manage_webhooks` scope.","parameters":[{"schema":{"type":"string"},"example":"whe_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the webhook endpoint."}],"security":[{"bearerAuth":[]}],"responses":{"204":{"description":"Default Response"},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/webhook-endpoints/{id}/rotate-secret":{"post":{"summary":"Rotate the secret of an endpoint","tags":["Webhook endpoints"],"description":"Creates a new secret and keeps the old one valid for `expires_in_seconds` (24 hours by default, 7 days at most), so you can switch without losing a call: during that time each delivery carries one signature per active secret. The new secret is **shown only this once**. While two secrets are active, a new rotation fails with `409 rotation_in_progress`. Requires the `manage_webhooks` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"expires_in_seconds":{"type":"integer","minimum":60,"maximum":604800,"description":"How long the old secret stays valid, in seconds: from 60 to 604800 (7 days). A default applies if you leave it out (24 hours).","examples":[86400]}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"example":"whe_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the webhook endpoint."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the webhook endpoint.","examples":["whe_01m4akapdbe8e8qq3er9r5qwyj"]},"mode":{"type":"string","enum":["live","test"],"description":"The endpoint belongs to the mode of the key that created it, and only receives events of that mode.","examples":["test"]},"url":{"type":"string","description":"Where the events are sent.","examples":["https://example.com/webhooks/tryvidimus"]},"description":{"description":"Your note, if any.","type":["string","null"]},"events":{"type":"array","items":{"type":"string","enum":["proof.sealed","proof.failed","capture_session.expired","capture_session.completed","capture_session.rejected","dossier.ready"]},"description":"The events this endpoint receives.","examples":[["proof.sealed","proof.failed"]]},"status":{"type":"string","enum":["active","disabled"],"description":"`disabled` endpoints receive nothing."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the endpoint was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."},"secrets":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the secret.","examples":["whs_01m4akapdbe8e8qq3er9r5qwyj"]},"hint":{"type":"string","description":"The first characters of the secret, to recognize it. Never enough to sign.","examples":["whsec_AbCd"]},"status":{"type":"string","enum":["active","expired"],"description":"`active`: used to sign deliveries. `expired`: no longer used."},"expires_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When this secret stops being used, during a rotation; `null` for the current secret."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the secret was created (ISO 8601, UTC)."}},"required":["id","hint","status","expires_at","created_at"],"additionalProperties":false},"description":"The signing secrets: one, or two during a rotation. Never the secret itself."},"secret":{"type":"string","description":"The signing secret in clear. **This is the only time it is shown**: store it now. It is never returned again, and we cannot read it back.","examples":["whsec_…"]}},"required":["id","mode","url","description","events","status","created_at","updated_at","secrets","secret"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/webhook-deliveries":{"get":{"summary":"List webhook deliveries","tags":["Webhook endpoints"],"description":"The log of what was sent to your endpoints, most recent first, in the mode of your key, with cursor pagination. Each delivery is one event for one endpoint, with its state (`pending`, `delivered`, `failed` or `abandoned`), the number of attempts and the HTTP status your server last answered. Filter by `endpoint_id` or `status` (for example `abandoned` to find the events your server never accepted). The content that was sent is never included. A cursor that was altered fails with `422 invalid_cursor`; an unknown `endpoint_id` with `404 webhook_endpoint_not_found`. Requires the `manage_webhooks` scope.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":100},"example":20,"in":"query","name":"limit","required":false,"description":"How many deliveries to return, from 1 to 100."},{"schema":{"type":"string","maxLength":300},"in":"query","name":"cursor","required":false,"description":"The `next_cursor` of the previous page. Opaque: do not build or change it."},{"schema":{"type":"string","maxLength":40},"example":"whe_01m4akapdbe8e8qq3er9r5qwyj","in":"query","name":"endpoint_id","required":false,"description":"Only the deliveries to this webhook endpoint."},{"schema":{"type":"string","enum":["pending","delivered","failed","abandoned"]},"example":"failed","in":"query","name":"status","required":false,"description":"Only the deliveries in this state, for example `failed` or `abandoned` to find what needs your attention."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of this delivery attempt series.","examples":["whd_01m4akapdbe8e8qq3er9r5qwyj"]},"endpoint_id":{"type":"string","description":"The webhook endpoint the event is sent to.","examples":["whe_01m4akapdbe8e8qq3er9r5qwyj"]},"event_id":{"type":"string","description":"Identifier of the event: the same on every attempt (the `X-Event-Id` header), use it to ignore duplicates.","examples":["evt_01m4akapdbe8e8qq3er9r5qwyj"]},"event_type":{"type":"string","description":"The event, for example `proof.sealed`.","examples":["proof.sealed"]},"status":{"type":"string","enum":["pending","delivered","failed","abandoned"],"description":"`pending`: waiting for its first or next attempt. `delivered`: your server answered with a `2xx`. `failed`: the last attempt failed, a new one is planned. `abandoned`: every attempt failed, we stopped.","examples":["delivered"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many attempts were made.","examples":[1]},"next_attempt_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the next attempt is planned (ISO 8601, UTC); `null` when none is."},"last_attempt_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the last attempt was made (ISO 8601, UTC); `null` before the first."},"response_code":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The HTTP status your server answered on the last attempt; `null` if it did not answer.","examples":[200]},"error":{"anyOf":[{"type":"string","enum":["http_status","network_error","blocked_address","invalid_url","no_active_secret"]},{"type":"null"}],"description":"Why the last attempt failed, in one word: `http_status` (your server answered outside `2xx`), `network_error` (unreachable, timeout, certificate refused), `blocked_address` (the URL points to a non-public address), `invalid_url`, `no_active_secret`. `null` when the last attempt succeeded or there was none.","examples":["http_status"]},"test":{"type":"boolean","description":"`true` for a test event you sent yourself with `POST /v1/webhook-endpoints/{id}/test`."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the event was queued for this endpoint (ISO 8601, UTC)."}},"required":["id","endpoint_id","event_id","event_type","status","attempts","next_attempt_at","last_attempt_at","response_code","error","test","created_at"],"additionalProperties":false},"description":"The deliveries of your endpoints in the mode of the key, most recent first."},"has_more":{"type":"boolean","description":"`true` when there are more deliveries after this page."},"next_cursor":{"description":"Pass it as `cursor` to get the next page; `null` on the last page.","type":["string","null"]}},"required":["data","has_more","next_cursor"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/webhook-deliveries/{id}":{"get":{"summary":"Get a webhook delivery","tags":["Webhook endpoints"],"description":"One delivery with what was sent: the JSON `payload` of the event exactly as your endpoint received it (copy it to replay the event on your own server), the state, the number of attempts, the HTTP status and the beginning of the answer of your server on the last attempt, and why it failed. Requires the `manage_webhooks` scope.","parameters":[{"schema":{"type":"string"},"example":"whd_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the webhook delivery."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of this delivery attempt series.","examples":["whd_01m4akapdbe8e8qq3er9r5qwyj"]},"endpoint_id":{"type":"string","description":"The webhook endpoint the event is sent to.","examples":["whe_01m4akapdbe8e8qq3er9r5qwyj"]},"event_id":{"type":"string","description":"Identifier of the event: the same on every attempt (the `X-Event-Id` header), use it to ignore duplicates.","examples":["evt_01m4akapdbe8e8qq3er9r5qwyj"]},"event_type":{"type":"string","description":"The event, for example `proof.sealed`.","examples":["proof.sealed"]},"status":{"type":"string","enum":["pending","delivered","failed","abandoned"],"description":"`pending`: waiting for its first or next attempt. `delivered`: your server answered with a `2xx`. `failed`: the last attempt failed, a new one is planned. `abandoned`: every attempt failed, we stopped.","examples":["delivered"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many attempts were made.","examples":[1]},"next_attempt_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the next attempt is planned (ISO 8601, UTC); `null` when none is."},"last_attempt_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the last attempt was made (ISO 8601, UTC); `null` before the first."},"response_code":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The HTTP status your server answered on the last attempt; `null` if it did not answer.","examples":[200]},"error":{"anyOf":[{"type":"string","enum":["http_status","network_error","blocked_address","invalid_url","no_active_secret"]},{"type":"null"}],"description":"Why the last attempt failed, in one word: `http_status` (your server answered outside `2xx`), `network_error` (unreachable, timeout, certificate refused), `blocked_address` (the URL points to a non-public address), `invalid_url`, `no_active_secret`. `null` when the last attempt succeeded or there was none.","examples":["http_status"]},"test":{"type":"boolean","description":"`true` for a test event you sent yourself with `POST /v1/webhook-endpoints/{id}/test`."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the event was queued for this endpoint (ISO 8601, UTC)."},"payload":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{},"description":"The JSON body of the event, exactly as it was sent to your endpoint (the same on every attempt). Copy it to replay the event on your own server.","examples":[{"event":"proof.sealed","proof_id":"prf_01m4akapdbe8e8qq3er9r5qwyj","status":"sealed"}]},"response_body":{"description":"The beginning of what your server answered on the last attempt (4,096 characters at most); `null` if it did not answer or sent nothing.","examples":["{\"received\":true}"],"type":["string","null"]}},"required":["id","endpoint_id","event_id","event_type","status","attempts","next_attempt_at","last_attempt_at","response_code","error","test","created_at","payload","response_body"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/webhook-endpoints/{id}/test":{"post":{"summary":"Send a test event to a webhook endpoint","tags":["Webhook endpoints"],"description":"Sends an example event to an endpoint, to try your server: the body has the same fields as the real event, with example values and `\"test\": true`, and it is signed with the secret of the endpoint like any delivery (see the *Webhooks* section above). It appears in the delivery log with `test: true`. The endpoint must be `active` (`409 webhook_endpoint_disabled` otherwise); at most 20 test events per endpoint per hour (`429 too_many_test_events`). Requires the `manage_webhooks` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event_type":{"type":"string","enum":["proof.sealed","proof.failed","capture_session.completed","capture_session.rejected"],"description":"The event to send as a test: its body has the same fields as the real event, with example values and `\"test\": true`.","examples":["proof.sealed"]}},"required":["event_type"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"example":"whe_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the webhook endpoint."}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of this delivery attempt series.","examples":["whd_01m4akapdbe8e8qq3er9r5qwyj"]},"endpoint_id":{"type":"string","description":"The webhook endpoint the event is sent to.","examples":["whe_01m4akapdbe8e8qq3er9r5qwyj"]},"event_id":{"type":"string","description":"Identifier of the event: the same on every attempt (the `X-Event-Id` header), use it to ignore duplicates.","examples":["evt_01m4akapdbe8e8qq3er9r5qwyj"]},"event_type":{"type":"string","description":"The event, for example `proof.sealed`.","examples":["proof.sealed"]},"status":{"type":"string","enum":["pending","delivered","failed","abandoned"],"description":"`pending`: waiting for its first or next attempt. `delivered`: your server answered with a `2xx`. `failed`: the last attempt failed, a new one is planned. `abandoned`: every attempt failed, we stopped.","examples":["delivered"]},"attempts":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many attempts were made.","examples":[1]},"next_attempt_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the next attempt is planned (ISO 8601, UTC); `null` when none is."},"last_attempt_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the last attempt was made (ISO 8601, UTC); `null` before the first."},"response_code":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"The HTTP status your server answered on the last attempt; `null` if it did not answer.","examples":[200]},"error":{"anyOf":[{"type":"string","enum":["http_status","network_error","blocked_address","invalid_url","no_active_secret"]},{"type":"null"}],"description":"Why the last attempt failed, in one word: `http_status` (your server answered outside `2xx`), `network_error` (unreachable, timeout, certificate refused), `blocked_address` (the URL points to a non-public address), `invalid_url`, `no_active_secret`. `null` when the last attempt succeeded or there was none.","examples":["http_status"]},"test":{"type":"boolean","description":"`true` for a test event you sent yourself with `POST /v1/webhook-endpoints/{id}/test`."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the event was queued for this endpoint (ISO 8601, UTC)."}},"required":["id","endpoint_id","event_id","event_type","status","attempts","next_attempt_at","last_attempt_at","response_code","error","test","created_at"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/proofs/{id}":{"get":{"summary":"Get a proof","tags":["Proofs"],"description":"Returns one proof of your organization, in the mode of your key: its status, why it failed if it did, and its files. Requires the `read_proof` scope. An unknown proof, or one that belongs to another organization or mode, gives the same `404 proof_not_found`.","parameters":[{"schema":{"type":"string"},"example":"prf_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the proof."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the proof.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"status":{"type":"string","enum":["pending","processing","sealed","failed"],"description":"`pending`: created, waiting to be processed. `processing`: being verified, signed and timestamped (see `processing_stage`). `sealed`: signed and timestamped, final. `failed`: see `failure`.","examples":["sealed"]},"processing_stage":{"anyOf":[{"type":"string","enum":["verifying","signing","awaiting_timestamp"]},{"type":"null"}],"description":"While `processing`: `verifying` (we re-read the files), `signing` (we sign the copies), `awaiting_timestamp` (waiting for the timestamp token). `null` otherwise."},"failure":{"anyOf":[{"type":"object","properties":{"code":{"type":"string","description":"Why it failed, for example `hash_mismatch` (the file we received is not the one declared) or `invalid_media` (not a valid photo or video). Rely on `retriable` to know whether the failure can be run again.","examples":["hash_mismatch"]},"retriable":{"type":"boolean","description":"`true` when the cause was temporary on our side. Before reporting a failure we already retry automatically (signing: up to 8 attempts; timestamping: up to 24 hours), so a failed proof is not retried again by itself: we can run it again for you on request. Do not create a new capture session, the files are kept with the proof. `false`: the failure is final and needs a new capture."}},"required":["code","retriable"],"additionalProperties":false},{"type":"null"}],"description":"Present only when `status` is `failed`."},"mode":{"type":"string","enum":["live","test"],"description":"Mode of the key that created the proof.","examples":["test"]},"external_reference":{"type":"string","description":"The identifier you gave when creating the capture session.","examples":["booking_4471"]},"party":{"type":"string","enum":["provider","recipient"],"description":"Who took the photos.","examples":["provider"]},"stage":{"description":"The moment of the transaction, as you declared it.","examples":["pickup"],"type":["string","null"]},"category":{"description":"The category, as you declared it.","examples":["vehicle"],"type":["string","null"]},"location_reference":{"description":"The place, as you declared it.","type":["string","null"]},"dispute_status":{"type":"string","enum":["none","active"],"description":"`active` while the proof is under dispute: its files are then kept until the dispute is closed."},"compare_to":{"anyOf":[{"type":"string","description":"Identifier of the proof.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},{"type":"null"}],"description":"When this proof is an \"after\", the `id` of the \"before\" it was captured to be compared with; `null` otherwise.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"compared_by":{"anyOf":[{"type":"string","description":"Identifier of the proof.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},{"type":"null"}],"description":"When this proof is a \"before\", the `id` of the \"after\" captured to be compared with it; `null` while it has none. A proof is either a \"before\" or an \"after\", and has at most one partner.","examples":["prf_01m4akapdbe8ev5xgt0hkpcn14"]},"skipped":{"type":"array","items":{"type":"object","properties":{"step_id":{"type":"string","description":"The `id` of the shot of the template.","examples":["garden"]},"reason":{"type":"string","enum":["nothing_to_report","not_applicable"],"description":"What the person declared: nothing to report, or the shot does not apply.","examples":["nothing_to_report"]}},"required":["step_id","reason"],"additionalProperties":false},"description":"The shots the person declared instead of photographing them (the template must have allowed it). These are declarations of the person who captured, not measured by us; empty when none."},"credits_consumed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount debited for this proof, in euros. It is debited when the proof is sealed, only in production: `0` for a sandbox proof or while the proof is not sealed. The movement is listed in `GET /v1/credits/transactions`.","examples":[1]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the proof was created (ISO 8601, UTC)."},"sealed_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the proof was sealed (ISO 8601, UTC); `null` until then."},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the file.","examples":["med_01m4akapdbe8ev5xgt0hkpcn14"]},"media_type":{"type":"string","enum":["photo","video"],"description":"Kind of file.","examples":["photo"]},"mime_type":{"type":"string","description":"Type of the file.","examples":["image/jpeg"]},"size_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Size of the original file in bytes.","examples":[36525]},"label":{"description":"The label given when the upload was requested, if any.","examples":["front"],"type":["string","null"]},"captured_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When our service received the file (ISO 8601, UTC). It is the time we observed, not the time shown by the phone, and it is not a qualified timestamp: only the timestamp of the proof (`gen_time`) proves when it existed."},"original_sha256":{"description":"SHA-256 of the original file, as we measured it.","type":["string","null"]},"signed_sha256":{"description":"SHA-256 of the signed copy (C2PA), once it exists.","type":["string","null"]},"signed":{"type":"boolean","description":"`true` when the signed copy exists. Download it with the access link once the proof is sealed."}},"required":["id","media_type","mime_type","size_bytes","label","captured_at","original_sha256","signed_sha256","signed"],"additionalProperties":false},"description":"The files of the proof."}},"required":["id","status","processing_stage","failure","mode","external_reference","party","stage","category","location_reference","dispute_status","compare_to","compared_by","skipped","credits_consumed","created_at","sealed_at","media"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/proofs":{"get":{"summary":"List proofs","tags":["Proofs"],"description":"Lists the proofs of your organization, in the mode of your key, with cursor pagination. Filter by `status`, `external_reference`, `party`, `stage` or `category`; sort with `sort`. A cursor that was altered, or that comes from the other sort order, fails with `422 invalid_cursor`. Requires the `read_proof` scope.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":100},"example":20,"in":"query","name":"limit","required":false,"description":"How many proofs to return, from 1 to 100."},{"schema":{"type":"string","maxLength":300},"in":"query","name":"cursor","required":false,"description":"The `next_cursor` of the previous page. Opaque: do not build or change it."},{"schema":{"type":"string","enum":["pending","processing","sealed","failed"]},"example":"sealed","in":"query","name":"status","required":false,"description":"Only the proofs with this status."},{"schema":{"type":"string","pattern":"^[A-Za-z0-9_.:/#=+-]{1,200}$"},"example":"booking_4471","in":"query","name":"external_reference","required":false,"description":"Only the proofs of this transaction."},{"schema":{"type":"string","enum":["provider","recipient"]},"in":"query","name":"party","required":false,"description":"Only the proofs taken by this party."},{"schema":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$"},"example":"pickup","in":"query","name":"stage","required":false,"description":"Only the proofs of this stage."},{"schema":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$"},"in":"query","name":"category","required":false,"description":"Only the proofs of this category."},{"schema":{"type":"string","enum":["true","false"]},"in":"query","name":"linked","required":false,"description":"`false`: only the proofs with no partner (not yet compared to another, and not the \"after\" of one): the ones still waiting for their \"after\". `true`: only the proofs that are part of a \"before\" and \"after\" pair."},{"schema":{"default":"-created_at","type":"string","enum":["created_at","-created_at"]},"in":"query","name":"sort","required":false,"description":"Order by creation date: `created_at` oldest first, `-created_at` newest first."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the proof.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"status":{"type":"string","enum":["pending","processing","sealed","failed"],"description":"`pending`: created, waiting to be processed. `processing`: being verified, signed and timestamped (see `processing_stage`). `sealed`: signed and timestamped, final. `failed`: see `failure`.","examples":["sealed"]},"processing_stage":{"anyOf":[{"type":"string","enum":["verifying","signing","awaiting_timestamp"]},{"type":"null"}],"description":"While `processing`: `verifying` (we re-read the files), `signing` (we sign the copies), `awaiting_timestamp` (waiting for the timestamp token). `null` otherwise."},"failure":{"anyOf":[{"type":"object","properties":{"code":{"type":"string","description":"Why it failed, for example `hash_mismatch` (the file we received is not the one declared) or `invalid_media` (not a valid photo or video). Rely on `retriable` to know whether the failure can be run again.","examples":["hash_mismatch"]},"retriable":{"type":"boolean","description":"`true` when the cause was temporary on our side. Before reporting a failure we already retry automatically (signing: up to 8 attempts; timestamping: up to 24 hours), so a failed proof is not retried again by itself: we can run it again for you on request. Do not create a new capture session, the files are kept with the proof. `false`: the failure is final and needs a new capture."}},"required":["code","retriable"],"additionalProperties":false},{"type":"null"}],"description":"Present only when `status` is `failed`."},"mode":{"type":"string","enum":["live","test"],"description":"Mode of the key that created the proof.","examples":["test"]},"external_reference":{"type":"string","description":"The identifier you gave when creating the capture session.","examples":["booking_4471"]},"party":{"type":"string","enum":["provider","recipient"],"description":"Who took the photos.","examples":["provider"]},"stage":{"description":"The moment of the transaction, as you declared it.","examples":["pickup"],"type":["string","null"]},"category":{"description":"The category, as you declared it.","examples":["vehicle"],"type":["string","null"]},"location_reference":{"description":"The place, as you declared it.","type":["string","null"]},"dispute_status":{"type":"string","enum":["none","active"],"description":"`active` while the proof is under dispute: its files are then kept until the dispute is closed."},"compare_to":{"anyOf":[{"type":"string","description":"Identifier of the proof.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},{"type":"null"}],"description":"When this proof is an \"after\", the `id` of the \"before\" it was captured to be compared with; `null` otherwise.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"compared_by":{"anyOf":[{"type":"string","description":"Identifier of the proof.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},{"type":"null"}],"description":"When this proof is a \"before\", the `id` of the \"after\" captured to be compared with it; `null` while it has none. A proof is either a \"before\" or an \"after\", and has at most one partner.","examples":["prf_01m4akapdbe8ev5xgt0hkpcn14"]},"skipped":{"type":"array","items":{"type":"object","properties":{"step_id":{"type":"string","description":"The `id` of the shot of the template.","examples":["garden"]},"reason":{"type":"string","enum":["nothing_to_report","not_applicable"],"description":"What the person declared: nothing to report, or the shot does not apply.","examples":["nothing_to_report"]}},"required":["step_id","reason"],"additionalProperties":false},"description":"The shots the person declared instead of photographing them (the template must have allowed it). These are declarations of the person who captured, not measured by us; empty when none."},"credits_consumed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount debited for this proof, in euros. It is debited when the proof is sealed, only in production: `0` for a sandbox proof or while the proof is not sealed. The movement is listed in `GET /v1/credits/transactions`.","examples":[1]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the proof was created (ISO 8601, UTC)."},"sealed_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the proof was sealed (ISO 8601, UTC); `null` until then."},"media":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the file.","examples":["med_01m4akapdbe8ev5xgt0hkpcn14"]},"media_type":{"type":"string","enum":["photo","video"],"description":"Kind of file.","examples":["photo"]},"mime_type":{"type":"string","description":"Type of the file.","examples":["image/jpeg"]},"size_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Size of the original file in bytes.","examples":[36525]},"label":{"description":"The label given when the upload was requested, if any.","examples":["front"],"type":["string","null"]},"captured_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When our service received the file (ISO 8601, UTC). It is the time we observed, not the time shown by the phone, and it is not a qualified timestamp: only the timestamp of the proof (`gen_time`) proves when it existed."},"original_sha256":{"description":"SHA-256 of the original file, as we measured it.","type":["string","null"]},"signed_sha256":{"description":"SHA-256 of the signed copy (C2PA), once it exists.","type":["string","null"]},"signed":{"type":"boolean","description":"`true` when the signed copy exists. Download it with the access link once the proof is sealed."}},"required":["id","media_type","mime_type","size_bytes","label","captured_at","original_sha256","signed_sha256","signed"],"additionalProperties":false},"description":"The files of the proof."}},"required":["id","status","processing_stage","failure","mode","external_reference","party","stage","category","location_reference","dispute_status","compare_to","compared_by","skipped","credits_consumed","created_at","sealed_at","media"],"additionalProperties":false},"description":"The proofs of this page."},"has_more":{"type":"boolean","description":"`true` when another page exists."},"next_cursor":{"description":"Give it as `cursor` to get the next page; `null` on the last page.","type":["string","null"]}},"required":["data","has_more","next_cursor"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/proofs/{id}/media/{media_id}/access-link":{"get":{"summary":"Get a download link for a signed copy","tags":["Proofs"],"description":"Returns a temporary link (15 minutes by default) to download the **signed copy** of one file. The original is never offered. Only for a `sealed` proof: otherwise `409 proof_not_sealed`. The file comes straight from storage. Requires the `read_proof` scope.","parameters":[{"schema":{"type":"string"},"example":"prf_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the proof."},{"schema":{"type":"string"},"example":"med_01m4akapdbe8ev5xgt0hkpcn14","in":"path","name":"media_id","required":true,"description":"Identifier of the file, from `media` in the proof."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"A temporary download link to the signed copy. The file comes straight from storage; do not store the link."},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the link stops working (ISO 8601, UTC). 15 minutes after it is created, by default."}},"required":["url","expires_at"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-templates":{"post":{"summary":"Create a capture template","tags":["Capture templates"],"description":"Defines what the capture page asks for: the shots to take and the welcome and completion texts. You refer to the template by its `id` (`tpl_…`), returned here: give it as `template_id` when you create a capture session. The `name` is only a label. A template with neither `stage` nor `category` is never chosen automatically: name it with `template_id`. In production, a template that has been used by a capture session can no longer be changed (`409 template_in_use`): duplicate it. Requires the `manage_templates` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Label of the template, to recognise it in a list. Lowercase letters, digits, `_`, `.` and `-`, 64 characters at most. Unique among your active templates; it is NOT how you refer to the template (use its `id`). You can change it until the template is used.","examples":["pickup_car"]},"default_locale":{"default":"en","description":"The language of your texts when a text is a plain string, and the fallback when a language is missing. A BCP 47 tag: `en`, `fr`, `de`, `pt-BR`… It cannot be changed afterwards. `en` when you leave it out.","examples":["en"],"type":"string","maxLength":35,"pattern":"^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$"},"stage":{"default":null,"description":"Use this template automatically for sessions created with this `stage`. A given pair of `stage` and `category` belongs to one template only.","examples":["pickup"],"anyOf":[{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$"},{"type":"null"}]},"category":{"default":null,"description":"Use this template automatically for sessions created with this `category` (together with `stage` when both are given).","examples":["vehicle"],"anyOf":[{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$"},{"type":"null"}]},"session_ttl_minutes":{"default":null,"description":"How long a capture link stays valid, in minutes, counted from the creation of the session: from 10 minutes to 12 hours (720). The person can close the page and come back until then. `null`: the default of the server (3 hours). A link already sent keeps its own deadline when you change the template.","examples":[180],"anyOf":[{"type":"integer","minimum":10,"maximum":720},{"type":"null"}]},"max_extra_photos":{"default":10,"description":"How many extra photos the person can add that match none of the shots (a damage nobody planned for), from 0 to 20. `0`: none. `10` when you leave it out. They are sealed like the others and listed apart from the shots of the template.","examples":[10],"type":"integer","minimum":0,"maximum":20},"theme_id":{"default":null,"description":"The capture theme this template uses: its `id` from `GET /v1/capture-themes` (`thm_…`). The capture page takes the look of this theme (logo, name, color, language). `null`: the default theme of your organization. Themes are the same in test and live.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"],"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"welcome":{"type":"object","properties":{"title":{"default":null,"description":"Title of the welcome screen, 120 characters at most, as a string or one string per language (the object must include the `default_locale`); `null` to use the page's own text.","anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}]},"body":{"default":null,"description":"Text of the welcome screen, 600 characters at most, as a string or one string per language (the object must include the `default_locale`); `null` to use the page's own text.","anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}]}},"additionalProperties":false,"description":"The welcome screen."},"completion":{"type":"object","properties":{"title":{"default":null,"description":"Title of the completion screen, 120 characters at most, as a string or one string per language (the object must include the `default_locale`); `null` to use the page's own text.","anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}]},"body":{"default":null,"description":"Text of the completion screen, 600 characters at most, as a string or one string per language (the object must include the `default_locale`); `null` to use the page's own text.","anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}]}},"additionalProperties":false,"description":"The completion screen."},"steps":{"default":[],"maxItems":30,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the shot, stable across edits.","examples":["front"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Short name of the shot, shown to the person, 80 characters at most. A string, or one string per language such as `{\"en\": \"Front\", \"fr\": \"Face avant\"}`: the object must include the `default_locale`.","examples":["Front of the vehicle"]},"instruction":{"default":null,"description":"What to do for this shot, shown under the label, 300 characters at most. A string, or one string per language, like `label`.","examples":["Stand back so the whole front is visible."],"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":300},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":300}}]},{"type":"null"}]},"required":{"default":true,"description":"`true` when the capture cannot be finished without this shot.","type":"boolean"},"min_photos":{"default":1,"description":"How many photos at least this shot needs, from 1 to 20, when `required` is `true` (ignored otherwise). `1` when you leave it out.","examples":[2],"type":"integer","minimum":1,"maximum":20},"max_photos":{"default":1,"description":"How many photos at most the person can take for this shot, from 1 to 20, and at least `min_photos`. `1` when you leave it out: one photo per shot.","examples":[6],"type":"integer","minimum":1,"maximum":20},"section":{"default":null,"description":"The step this shot belongs to, such as a room or an area (`{\"id\": \"kitchen\", \"label\": {\"en\": \"Kitchen\", \"fr\": \"Cuisine\"}}`). Shots with the same `section.id` must follow each other and share the same `label`: the page shows them together under the name of the step. `null`: a shot of its own, as before steps existed.","examples":[{"id":"kitchen","label":"Kitchen"}],"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the step, stable across edits.","examples":["kitchen"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Name of the step, shown to the person, 80 characters at most: a string, or one string per language like the label of a shot.","examples":["Kitchen"]}},"required":["id","label"],"additionalProperties":false},{"type":"null"}]},"allowed_skips":{"default":[],"description":"What the person may declare instead of taking photos of this shot: `nothing_to_report` (nothing to note there) and/or `not_applicable` (the shot does not apply to this item). Empty (default): the shot cannot be skipped. A skipped shot counts as done even when `required` is `true`, and the declaration is kept with the proof.","examples":[["nothing_to_report"]],"maxItems":2,"type":"array","items":{"type":"string","enum":["nothing_to_report","not_applicable"]}}},"required":["id","label"],"additionalProperties":false},"description":"The shots to take, in order, 30 at most, each with its own `id`. An empty list means: take photos freely."}},"required":["name"],"additionalProperties":false}}}},"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the template: how you refer to it (`template_id` when you create a capture session, and in the path of the routes below). It never changes.","examples":["tpl_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Label of the template, to recognise it in a list. Lowercase letters, digits, `_`, `.` and `-`, 64 characters at most. Unique among your active templates; it is NOT how you refer to the template (use its `id`). You can change it until the template is used.","examples":["pickup_car"]},"default_locale":{"type":"string","description":"The language of your texts when a text is a plain string, and the fallback when a language is missing. A BCP 47 tag: `en`, `fr`, `de`, `pt-BR`… It cannot be changed afterwards. `en` when you leave it out.","examples":["en"]},"locales":{"type":"array","items":{"type":"string"},"description":"The languages this template has texts for, the default one included. The capture page can be shown in any of them.","examples":[["de","en","fr"]]},"stage":{"description":"The `stage` this template is used for automatically, if any.","type":["string","null"]},"category":{"description":"The `category` this template is used for automatically, if any.","type":["string","null"]},"session_ttl_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"How long a capture link stays valid, in minutes, counted from the creation of the session: from 10 minutes to 12 hours (720). The person can close the page and come back until then. `null`: the default of the server (3 hours). A link already sent keeps its own deadline when you change the template.","examples":[180]},"max_extra_photos":{"type":"integer","minimum":0,"maximum":20,"description":"How many extra photos the person can add that match none of the shots (a damage nobody planned for), from 0 to 20. `0`: none. `10` when you leave it out. They are sealed like the others and listed apart from the shots of the template.","examples":[10]},"theme_id":{"description":"The capture theme this template uses: its `id` from `GET /v1/capture-themes` (`thm_…`). The capture page takes the look of this theme (logo, name, color, language). `null`: the default theme of your organization. Themes are the same in test and live.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"],"type":["string","null"]},"welcome":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the welcome screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the welcome screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The welcome screen."},"completion":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the completion screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the completion screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The completion screen."},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the shot, stable across edits.","examples":["front"]},"label":{"anyOf":[{"type":"string","minLength":0,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":80}}],"description":"Short name of the shot, shown to the person, 80 characters at most. A string, or one string per language such as `{\"en\": \"Front\", \"fr\": \"Face avant\"}`: the object must include the `default_locale`.","examples":["Front of the vehicle"]},"instruction":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":300},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":300}}]},{"type":"null"}],"description":"What to do for this shot, shown under the label, 300 characters at most. A string, or one string per language, like `label`.","examples":["Stand back so the whole front is visible."]},"required":{"type":"boolean","description":"`true` when the capture cannot be finished without this shot."},"min_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at least this shot needs, from 1 to 20, when `required` is `true` (ignored otherwise). `1` when you leave it out.","examples":[2]},"max_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at most the person can take for this shot, from 1 to 20, and at least `min_photos`. `1` when you leave it out: one photo per shot.","examples":[6]},"section":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the step, stable across edits.","examples":["kitchen"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Name of the step, shown to the person, 80 characters at most: a string, or one string per language like the label of a shot.","examples":["Kitchen"]}},"required":["id","label"],"additionalProperties":false},{"type":"null"}],"description":"The step this shot belongs to, such as a room or an area (`{\"id\": \"kitchen\", \"label\": {\"en\": \"Kitchen\", \"fr\": \"Cuisine\"}}`). Shots with the same `section.id` must follow each other and share the same `label`: the page shows them together under the name of the step. `null`: a shot of its own, as before steps existed.","examples":[{"id":"kitchen","label":"Kitchen"}]},"allowed_skips":{"type":"array","items":{"type":"string","enum":["nothing_to_report","not_applicable"]},"description":"What the person may declare instead of taking photos of this shot: `nothing_to_report` (nothing to note there) and/or `not_applicable` (the shot does not apply to this item). Empty (default): the shot cannot be skipped. A skipped shot counts as done even when `required` is `true`, and the declaration is kept with the proof.","examples":[["nothing_to_report"]]}},"required":["id","label","instruction","required","min_photos","max_photos","section","allowed_skips"],"additionalProperties":false},"description":"The shots to take, in order. An empty list means: take photos freely."},"in_use":{"type":"boolean","description":"`true` once at least one capture session was created from this template. A production template that is in use can no longer be changed: duplicate it and change the copy."},"archived_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the template was archived (ISO 8601, UTC), or `null` while it is active. An archived template cannot start new sessions; the sessions and proofs already made keep their copy."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the template was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."}},"required":["id","name","default_locale","locales","stage","category","session_ttl_minutes","max_extra_photos","theme_id","welcome","completion","steps","in_use","archived_at","created_at","updated_at"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"get":{"summary":"List capture templates","tags":["Capture templates"],"description":"Lists the capture templates of your organization, by label: the active ones, or the archived ones with `archived=true`. Paginated: `limit` (50 by default, 100 at most) and the `next_cursor` of the previous page; `has_more` tells whether another page exists. Requires the `manage_templates` scope.","parameters":[{"schema":{"default":"false","type":"string","enum":["true","false"]},"in":"query","name":"archived","required":false,"description":"`false` (default): your active templates. `true`: your archived templates only."},{"schema":{"default":50,"type":"integer","minimum":1,"maximum":100},"example":20,"in":"query","name":"limit","required":false,"description":"How many templates to return, from 1 to 100."},{"schema":{"type":"string","maxLength":400},"in":"query","name":"cursor","required":false,"description":"The `next_cursor` of the previous page. Opaque: do not build or change it."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the template: how you refer to it (`template_id` when you create a capture session, and in the path of the routes below). It never changes.","examples":["tpl_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Label of the template, to recognise it in a list. Lowercase letters, digits, `_`, `.` and `-`, 64 characters at most. Unique among your active templates; it is NOT how you refer to the template (use its `id`). You can change it until the template is used.","examples":["pickup_car"]},"default_locale":{"type":"string","description":"The language of your texts when a text is a plain string, and the fallback when a language is missing. A BCP 47 tag: `en`, `fr`, `de`, `pt-BR`… It cannot be changed afterwards. `en` when you leave it out.","examples":["en"]},"locales":{"type":"array","items":{"type":"string"},"description":"The languages this template has texts for, the default one included. The capture page can be shown in any of them.","examples":[["de","en","fr"]]},"stage":{"description":"The `stage` this template is used for automatically, if any.","type":["string","null"]},"category":{"description":"The `category` this template is used for automatically, if any.","type":["string","null"]},"session_ttl_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"How long a capture link stays valid, in minutes, counted from the creation of the session: from 10 minutes to 12 hours (720). The person can close the page and come back until then. `null`: the default of the server (3 hours). A link already sent keeps its own deadline when you change the template.","examples":[180]},"max_extra_photos":{"type":"integer","minimum":0,"maximum":20,"description":"How many extra photos the person can add that match none of the shots (a damage nobody planned for), from 0 to 20. `0`: none. `10` when you leave it out. They are sealed like the others and listed apart from the shots of the template.","examples":[10]},"theme_id":{"description":"The capture theme this template uses: its `id` from `GET /v1/capture-themes` (`thm_…`). The capture page takes the look of this theme (logo, name, color, language). `null`: the default theme of your organization. Themes are the same in test and live.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"],"type":["string","null"]},"welcome":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the welcome screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the welcome screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The welcome screen."},"completion":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the completion screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the completion screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The completion screen."},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the shot, stable across edits.","examples":["front"]},"label":{"anyOf":[{"type":"string","minLength":0,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":80}}],"description":"Short name of the shot, shown to the person, 80 characters at most. A string, or one string per language such as `{\"en\": \"Front\", \"fr\": \"Face avant\"}`: the object must include the `default_locale`.","examples":["Front of the vehicle"]},"instruction":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":300},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":300}}]},{"type":"null"}],"description":"What to do for this shot, shown under the label, 300 characters at most. A string, or one string per language, like `label`.","examples":["Stand back so the whole front is visible."]},"required":{"type":"boolean","description":"`true` when the capture cannot be finished without this shot."},"min_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at least this shot needs, from 1 to 20, when `required` is `true` (ignored otherwise). `1` when you leave it out.","examples":[2]},"max_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at most the person can take for this shot, from 1 to 20, and at least `min_photos`. `1` when you leave it out: one photo per shot.","examples":[6]},"section":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the step, stable across edits.","examples":["kitchen"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Name of the step, shown to the person, 80 characters at most: a string, or one string per language like the label of a shot.","examples":["Kitchen"]}},"required":["id","label"],"additionalProperties":false},{"type":"null"}],"description":"The step this shot belongs to, such as a room or an area (`{\"id\": \"kitchen\", \"label\": {\"en\": \"Kitchen\", \"fr\": \"Cuisine\"}}`). Shots with the same `section.id` must follow each other and share the same `label`: the page shows them together under the name of the step. `null`: a shot of its own, as before steps existed.","examples":[{"id":"kitchen","label":"Kitchen"}]},"allowed_skips":{"type":"array","items":{"type":"string","enum":["nothing_to_report","not_applicable"]},"description":"What the person may declare instead of taking photos of this shot: `nothing_to_report` (nothing to note there) and/or `not_applicable` (the shot does not apply to this item). Empty (default): the shot cannot be skipped. A skipped shot counts as done even when `required` is `true`, and the declaration is kept with the proof.","examples":[["nothing_to_report"]]}},"required":["id","label","instruction","required","min_photos","max_photos","section","allowed_skips"],"additionalProperties":false},"description":"The shots to take, in order. An empty list means: take photos freely."},"in_use":{"type":"boolean","description":"`true` once at least one capture session was created from this template. A production template that is in use can no longer be changed: duplicate it and change the copy."},"archived_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the template was archived (ISO 8601, UTC), or `null` while it is active. An archived template cannot start new sessions; the sessions and proofs already made keep their copy."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the template was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."}},"required":["id","name","default_locale","locales","stage","category","session_ttl_minutes","max_extra_photos","theme_id","welcome","completion","steps","in_use","archived_at","created_at","updated_at"],"additionalProperties":false},"description":"The capture templates of this page, by label."},"has_more":{"type":"boolean","description":"`true` when another page exists."},"next_cursor":{"description":"Pass it as `cursor` to get the next page; `null` on the last page.","type":["string","null"]}},"required":["data","has_more","next_cursor"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-templates/{id}":{"get":{"summary":"Get a capture template","tags":["Capture templates"],"description":"Returns one capture template by its `id`, archived or not. Requires the `manage_templates` scope.","parameters":[{"schema":{"type":"string","maxLength":80},"example":"tpl_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the template (`tpl_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the template: how you refer to it (`template_id` when you create a capture session, and in the path of the routes below). It never changes.","examples":["tpl_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Label of the template, to recognise it in a list. Lowercase letters, digits, `_`, `.` and `-`, 64 characters at most. Unique among your active templates; it is NOT how you refer to the template (use its `id`). You can change it until the template is used.","examples":["pickup_car"]},"default_locale":{"type":"string","description":"The language of your texts when a text is a plain string, and the fallback when a language is missing. A BCP 47 tag: `en`, `fr`, `de`, `pt-BR`… It cannot be changed afterwards. `en` when you leave it out.","examples":["en"]},"locales":{"type":"array","items":{"type":"string"},"description":"The languages this template has texts for, the default one included. The capture page can be shown in any of them.","examples":[["de","en","fr"]]},"stage":{"description":"The `stage` this template is used for automatically, if any.","type":["string","null"]},"category":{"description":"The `category` this template is used for automatically, if any.","type":["string","null"]},"session_ttl_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"How long a capture link stays valid, in minutes, counted from the creation of the session: from 10 minutes to 12 hours (720). The person can close the page and come back until then. `null`: the default of the server (3 hours). A link already sent keeps its own deadline when you change the template.","examples":[180]},"max_extra_photos":{"type":"integer","minimum":0,"maximum":20,"description":"How many extra photos the person can add that match none of the shots (a damage nobody planned for), from 0 to 20. `0`: none. `10` when you leave it out. They are sealed like the others and listed apart from the shots of the template.","examples":[10]},"theme_id":{"description":"The capture theme this template uses: its `id` from `GET /v1/capture-themes` (`thm_…`). The capture page takes the look of this theme (logo, name, color, language). `null`: the default theme of your organization. Themes are the same in test and live.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"],"type":["string","null"]},"welcome":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the welcome screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the welcome screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The welcome screen."},"completion":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the completion screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the completion screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The completion screen."},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the shot, stable across edits.","examples":["front"]},"label":{"anyOf":[{"type":"string","minLength":0,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":80}}],"description":"Short name of the shot, shown to the person, 80 characters at most. A string, or one string per language such as `{\"en\": \"Front\", \"fr\": \"Face avant\"}`: the object must include the `default_locale`.","examples":["Front of the vehicle"]},"instruction":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":300},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":300}}]},{"type":"null"}],"description":"What to do for this shot, shown under the label, 300 characters at most. A string, or one string per language, like `label`.","examples":["Stand back so the whole front is visible."]},"required":{"type":"boolean","description":"`true` when the capture cannot be finished without this shot."},"min_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at least this shot needs, from 1 to 20, when `required` is `true` (ignored otherwise). `1` when you leave it out.","examples":[2]},"max_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at most the person can take for this shot, from 1 to 20, and at least `min_photos`. `1` when you leave it out: one photo per shot.","examples":[6]},"section":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the step, stable across edits.","examples":["kitchen"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Name of the step, shown to the person, 80 characters at most: a string, or one string per language like the label of a shot.","examples":["Kitchen"]}},"required":["id","label"],"additionalProperties":false},{"type":"null"}],"description":"The step this shot belongs to, such as a room or an area (`{\"id\": \"kitchen\", \"label\": {\"en\": \"Kitchen\", \"fr\": \"Cuisine\"}}`). Shots with the same `section.id` must follow each other and share the same `label`: the page shows them together under the name of the step. `null`: a shot of its own, as before steps existed.","examples":[{"id":"kitchen","label":"Kitchen"}]},"allowed_skips":{"type":"array","items":{"type":"string","enum":["nothing_to_report","not_applicable"]},"description":"What the person may declare instead of taking photos of this shot: `nothing_to_report` (nothing to note there) and/or `not_applicable` (the shot does not apply to this item). Empty (default): the shot cannot be skipped. A skipped shot counts as done even when `required` is `true`, and the declaration is kept with the proof.","examples":[["nothing_to_report"]]}},"required":["id","label","instruction","required","min_photos","max_photos","section","allowed_skips"],"additionalProperties":false},"description":"The shots to take, in order. An empty list means: take photos freely."},"in_use":{"type":"boolean","description":"`true` once at least one capture session was created from this template. A production template that is in use can no longer be changed: duplicate it and change the copy."},"archived_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the template was archived (ISO 8601, UTC), or `null` while it is active. An archived template cannot start new sessions; the sessions and proofs already made keep their copy."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the template was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."}},"required":["id","name","default_locale","locales","stage","category","session_ttl_minutes","max_extra_photos","theme_id","welcome","completion","steps","in_use","archived_at","created_at","updated_at"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"patch":{"summary":"Update a capture template","tags":["Capture templates"],"description":"Changes the label, the shots, the texts, the `stage` or the `category` of a template. Send only the fields to change, at least one; a field you send replaces the previous value entirely (send all the `steps` to change one). A **production** template that capture sessions have already been created from is frozen: it fails with `409 template_in_use`; duplicate it with `POST /v1/capture-templates/{id}/duplicate` and change the copy. Sandbox templates stay editable. An archived template fails with `409 template_archived`. Requires the `manage_templates` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Label of the template, to recognise it in a list. Lowercase letters, digits, `_`, `.` and `-`, 64 characters at most. Unique among your active templates; it is NOT how you refer to the template (use its `id`). You can change it until the template is used.","examples":["pickup_car"]},"stage":{"description":"Use this template automatically for sessions created with this `stage`. A given pair of `stage` and `category` belongs to one template only.","examples":["pickup"],"anyOf":[{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$"},{"type":"null"}]},"category":{"description":"Use this template automatically for sessions created with this `category` (together with `stage` when both are given).","examples":["vehicle"],"anyOf":[{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$"},{"type":"null"}]},"session_ttl_minutes":{"description":"How long a capture link stays valid, in minutes, counted from the creation of the session: from 10 minutes to 12 hours (720). The person can close the page and come back until then. `null`: the default of the server (3 hours). A link already sent keeps its own deadline when you change the template.","examples":[180],"anyOf":[{"type":"integer","minimum":10,"maximum":720},{"type":"null"}]},"max_extra_photos":{"description":"How many extra photos the person can add that match none of the shots (a damage nobody planned for), from 0 to 20. `0`: none. `10` when you leave it out. They are sealed like the others and listed apart from the shots of the template.","examples":[10],"type":"integer","minimum":0,"maximum":20},"theme_id":{"description":"The capture theme this template uses: its `id` from `GET /v1/capture-themes` (`thm_…`). The capture page takes the look of this theme (logo, name, color, language). `null`: the default theme of your organization. Themes are the same in test and live.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"],"anyOf":[{"type":"string","maxLength":40},{"type":"null"}]},"welcome":{"type":"object","properties":{"title":{"default":null,"description":"Title of the welcome screen, 120 characters at most, as a string or one string per language (the object must include the `default_locale`); `null` to use the page's own text.","anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}]},"body":{"default":null,"description":"Text of the welcome screen, 600 characters at most, as a string or one string per language (the object must include the `default_locale`); `null` to use the page's own text.","anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}]}},"additionalProperties":false,"description":"The welcome screen."},"completion":{"type":"object","properties":{"title":{"default":null,"description":"Title of the completion screen, 120 characters at most, as a string or one string per language (the object must include the `default_locale`); `null` to use the page's own text.","anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}]},"body":{"default":null,"description":"Text of the completion screen, 600 characters at most, as a string or one string per language (the object must include the `default_locale`); `null` to use the page's own text.","anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}]}},"additionalProperties":false,"description":"The completion screen."},"steps":{"maxItems":30,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the shot, stable across edits.","examples":["front"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Short name of the shot, shown to the person, 80 characters at most. A string, or one string per language such as `{\"en\": \"Front\", \"fr\": \"Face avant\"}`: the object must include the `default_locale`.","examples":["Front of the vehicle"]},"instruction":{"default":null,"description":"What to do for this shot, shown under the label, 300 characters at most. A string, or one string per language, like `label`.","examples":["Stand back so the whole front is visible."],"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":300},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":300}}]},{"type":"null"}]},"required":{"default":true,"description":"`true` when the capture cannot be finished without this shot.","type":"boolean"},"min_photos":{"default":1,"description":"How many photos at least this shot needs, from 1 to 20, when `required` is `true` (ignored otherwise). `1` when you leave it out.","examples":[2],"type":"integer","minimum":1,"maximum":20},"max_photos":{"default":1,"description":"How many photos at most the person can take for this shot, from 1 to 20, and at least `min_photos`. `1` when you leave it out: one photo per shot.","examples":[6],"type":"integer","minimum":1,"maximum":20},"section":{"default":null,"description":"The step this shot belongs to, such as a room or an area (`{\"id\": \"kitchen\", \"label\": {\"en\": \"Kitchen\", \"fr\": \"Cuisine\"}}`). Shots with the same `section.id` must follow each other and share the same `label`: the page shows them together under the name of the step. `null`: a shot of its own, as before steps existed.","examples":[{"id":"kitchen","label":"Kitchen"}],"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the step, stable across edits.","examples":["kitchen"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Name of the step, shown to the person, 80 characters at most: a string, or one string per language like the label of a shot.","examples":["Kitchen"]}},"required":["id","label"],"additionalProperties":false},{"type":"null"}]},"allowed_skips":{"default":[],"description":"What the person may declare instead of taking photos of this shot: `nothing_to_report` (nothing to note there) and/or `not_applicable` (the shot does not apply to this item). Empty (default): the shot cannot be skipped. A skipped shot counts as done even when `required` is `true`, and the declaration is kept with the proof.","examples":[["nothing_to_report"]],"maxItems":2,"type":"array","items":{"type":"string","enum":["nothing_to_report","not_applicable"]}}},"required":["id","label"],"additionalProperties":false},"description":"The shots to take, in order, 30 at most, each with its own `id`. An empty list means: take photos freely."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","maxLength":80},"example":"tpl_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the template (`tpl_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the template: how you refer to it (`template_id` when you create a capture session, and in the path of the routes below). It never changes.","examples":["tpl_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Label of the template, to recognise it in a list. Lowercase letters, digits, `_`, `.` and `-`, 64 characters at most. Unique among your active templates; it is NOT how you refer to the template (use its `id`). You can change it until the template is used.","examples":["pickup_car"]},"default_locale":{"type":"string","description":"The language of your texts when a text is a plain string, and the fallback when a language is missing. A BCP 47 tag: `en`, `fr`, `de`, `pt-BR`… It cannot be changed afterwards. `en` when you leave it out.","examples":["en"]},"locales":{"type":"array","items":{"type":"string"},"description":"The languages this template has texts for, the default one included. The capture page can be shown in any of them.","examples":[["de","en","fr"]]},"stage":{"description":"The `stage` this template is used for automatically, if any.","type":["string","null"]},"category":{"description":"The `category` this template is used for automatically, if any.","type":["string","null"]},"session_ttl_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"How long a capture link stays valid, in minutes, counted from the creation of the session: from 10 minutes to 12 hours (720). The person can close the page and come back until then. `null`: the default of the server (3 hours). A link already sent keeps its own deadline when you change the template.","examples":[180]},"max_extra_photos":{"type":"integer","minimum":0,"maximum":20,"description":"How many extra photos the person can add that match none of the shots (a damage nobody planned for), from 0 to 20. `0`: none. `10` when you leave it out. They are sealed like the others and listed apart from the shots of the template.","examples":[10]},"theme_id":{"description":"The capture theme this template uses: its `id` from `GET /v1/capture-themes` (`thm_…`). The capture page takes the look of this theme (logo, name, color, language). `null`: the default theme of your organization. Themes are the same in test and live.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"],"type":["string","null"]},"welcome":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the welcome screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the welcome screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The welcome screen."},"completion":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the completion screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the completion screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The completion screen."},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the shot, stable across edits.","examples":["front"]},"label":{"anyOf":[{"type":"string","minLength":0,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":80}}],"description":"Short name of the shot, shown to the person, 80 characters at most. A string, or one string per language such as `{\"en\": \"Front\", \"fr\": \"Face avant\"}`: the object must include the `default_locale`.","examples":["Front of the vehicle"]},"instruction":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":300},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":300}}]},{"type":"null"}],"description":"What to do for this shot, shown under the label, 300 characters at most. A string, or one string per language, like `label`.","examples":["Stand back so the whole front is visible."]},"required":{"type":"boolean","description":"`true` when the capture cannot be finished without this shot."},"min_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at least this shot needs, from 1 to 20, when `required` is `true` (ignored otherwise). `1` when you leave it out.","examples":[2]},"max_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at most the person can take for this shot, from 1 to 20, and at least `min_photos`. `1` when you leave it out: one photo per shot.","examples":[6]},"section":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the step, stable across edits.","examples":["kitchen"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Name of the step, shown to the person, 80 characters at most: a string, or one string per language like the label of a shot.","examples":["Kitchen"]}},"required":["id","label"],"additionalProperties":false},{"type":"null"}],"description":"The step this shot belongs to, such as a room or an area (`{\"id\": \"kitchen\", \"label\": {\"en\": \"Kitchen\", \"fr\": \"Cuisine\"}}`). Shots with the same `section.id` must follow each other and share the same `label`: the page shows them together under the name of the step. `null`: a shot of its own, as before steps existed.","examples":[{"id":"kitchen","label":"Kitchen"}]},"allowed_skips":{"type":"array","items":{"type":"string","enum":["nothing_to_report","not_applicable"]},"description":"What the person may declare instead of taking photos of this shot: `nothing_to_report` (nothing to note there) and/or `not_applicable` (the shot does not apply to this item). Empty (default): the shot cannot be skipped. A skipped shot counts as done even when `required` is `true`, and the declaration is kept with the proof.","examples":[["nothing_to_report"]]}},"required":["id","label","instruction","required","min_photos","max_photos","section","allowed_skips"],"additionalProperties":false},"description":"The shots to take, in order. An empty list means: take photos freely."},"in_use":{"type":"boolean","description":"`true` once at least one capture session was created from this template. A production template that is in use can no longer be changed: duplicate it and change the copy."},"archived_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the template was archived (ISO 8601, UTC), or `null` while it is active. An archived template cannot start new sessions; the sessions and proofs already made keep their copy."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the template was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."}},"required":["id","name","default_locale","locales","stage","category","session_ttl_minutes","max_extra_photos","theme_id","welcome","completion","steps","in_use","archived_at","created_at","updated_at"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"delete":{"summary":"Archive a capture template","tags":["Capture templates"],"description":"Archives a template: it is never deleted. It no longer starts capture sessions (`422 template_not_found` for a new session that names it), it leaves the default list, and its label and its `stage` / `category` become free again. Capture sessions and proofs already made keep their copy and still work. Repeating the call changes nothing. Requires the `manage_templates` scope.","parameters":[{"schema":{"type":"string","maxLength":80},"example":"tpl_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the template (`tpl_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"204":{"description":"Default Response"},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-templates/{id}/duplicate":{"post":{"summary":"Duplicate a capture template","tags":["Capture templates"],"description":"Creates a copy of a template (used or not, archived or not) with the same content and a **new `id`**. The copy does not take over the automatic choice by `stage` and `category`: it belongs to the original while the original is active, so archive the original, then set `stage` and `category` on the copy. This is how you change a production template that is already in use. `409 template_name_taken` if the label is already used by an active template. Requires the `manage_templates` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"Label of the copy. Leave it out to get the label of the original followed by `_copy`. It must be unique among your active templates.","examples":["pickup_car_v2"],"type":"string","pattern":"^[a-z0-9_.-]{1,64}$"}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","maxLength":80},"example":"tpl_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the template (`tpl_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the template: how you refer to it (`template_id` when you create a capture session, and in the path of the routes below). It never changes.","examples":["tpl_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Label of the template, to recognise it in a list. Lowercase letters, digits, `_`, `.` and `-`, 64 characters at most. Unique among your active templates; it is NOT how you refer to the template (use its `id`). You can change it until the template is used.","examples":["pickup_car"]},"default_locale":{"type":"string","description":"The language of your texts when a text is a plain string, and the fallback when a language is missing. A BCP 47 tag: `en`, `fr`, `de`, `pt-BR`… It cannot be changed afterwards. `en` when you leave it out.","examples":["en"]},"locales":{"type":"array","items":{"type":"string"},"description":"The languages this template has texts for, the default one included. The capture page can be shown in any of them.","examples":[["de","en","fr"]]},"stage":{"description":"The `stage` this template is used for automatically, if any.","type":["string","null"]},"category":{"description":"The `category` this template is used for automatically, if any.","type":["string","null"]},"session_ttl_minutes":{"anyOf":[{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},{"type":"null"}],"description":"How long a capture link stays valid, in minutes, counted from the creation of the session: from 10 minutes to 12 hours (720). The person can close the page and come back until then. `null`: the default of the server (3 hours). A link already sent keeps its own deadline when you change the template.","examples":[180]},"max_extra_photos":{"type":"integer","minimum":0,"maximum":20,"description":"How many extra photos the person can add that match none of the shots (a damage nobody planned for), from 0 to 20. `0`: none. `10` when you leave it out. They are sealed like the others and listed apart from the shots of the template.","examples":[10]},"theme_id":{"description":"The capture theme this template uses: its `id` from `GET /v1/capture-themes` (`thm_…`). The capture page takes the look of this theme (logo, name, color, language). `null`: the default theme of your organization. Themes are the same in test and live.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"],"type":["string","null"]},"welcome":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the welcome screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the welcome screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The welcome screen."},"completion":{"type":"object","properties":{"title":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":120},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":120}}]},{"type":"null"}],"description":"Title of the completion screen: a string, or one string per language; `null` to use the page's own text."},"body":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":600},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":600}}]},{"type":"null"}],"description":"Text of the completion screen: a string, or one string per language; `null` to use the page's own text."}},"required":["title","body"],"additionalProperties":false,"description":"The completion screen."},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the shot, stable across edits.","examples":["front"]},"label":{"anyOf":[{"type":"string","minLength":0,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":80}}],"description":"Short name of the shot, shown to the person, 80 characters at most. A string, or one string per language such as `{\"en\": \"Front\", \"fr\": \"Face avant\"}`: the object must include the `default_locale`.","examples":["Front of the vehicle"]},"instruction":{"anyOf":[{"anyOf":[{"type":"string","minLength":0,"maxLength":300},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":0,"maxLength":300}}]},{"type":"null"}],"description":"What to do for this shot, shown under the label, 300 characters at most. A string, or one string per language, like `label`.","examples":["Stand back so the whole front is visible."]},"required":{"type":"boolean","description":"`true` when the capture cannot be finished without this shot."},"min_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at least this shot needs, from 1 to 20, when `required` is `true` (ignored otherwise). `1` when you leave it out.","examples":[2]},"max_photos":{"type":"integer","minimum":1,"maximum":20,"description":"How many photos at most the person can take for this shot, from 1 to 20, and at least `min_photos`. `1` when you leave it out: one photo per shot.","examples":[6]},"section":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"Identifier of the step, stable across edits.","examples":["kitchen"]},"label":{"anyOf":[{"type":"string","minLength":1,"maxLength":80},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string","minLength":1,"maxLength":80}}],"description":"Name of the step, shown to the person, 80 characters at most: a string, or one string per language like the label of a shot.","examples":["Kitchen"]}},"required":["id","label"],"additionalProperties":false},{"type":"null"}],"description":"The step this shot belongs to, such as a room or an area (`{\"id\": \"kitchen\", \"label\": {\"en\": \"Kitchen\", \"fr\": \"Cuisine\"}}`). Shots with the same `section.id` must follow each other and share the same `label`: the page shows them together under the name of the step. `null`: a shot of its own, as before steps existed.","examples":[{"id":"kitchen","label":"Kitchen"}]},"allowed_skips":{"type":"array","items":{"type":"string","enum":["nothing_to_report","not_applicable"]},"description":"What the person may declare instead of taking photos of this shot: `nothing_to_report` (nothing to note there) and/or `not_applicable` (the shot does not apply to this item). Empty (default): the shot cannot be skipped. A skipped shot counts as done even when `required` is `true`, and the declaration is kept with the proof.","examples":[["nothing_to_report"]]}},"required":["id","label","instruction","required","min_photos","max_photos","section","allowed_skips"],"additionalProperties":false},"description":"The shots to take, in order. An empty list means: take photos freely."},"in_use":{"type":"boolean","description":"`true` once at least one capture session was created from this template. A production template that is in use can no longer be changed: duplicate it and change the copy."},"archived_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the template was archived (ISO 8601, UTC), or `null` while it is active. An archived template cannot start new sessions; the sessions and proofs already made keep their copy."},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the template was created (ISO 8601, UTC)."},"updated_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When it was last changed (ISO 8601, UTC)."}},"required":["id","name","default_locale","locales","stage","category","session_ttl_minutes","max_extra_photos","theme_id","welcome","completion","steps","in_use","archived_at","created_at","updated_at"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-themes":{"post":{"summary":"Create a capture theme","tags":["Capture themes"],"description":"Creates a look for the capture page: a name, a main color and a language (the logo is added with `PUT /v1/capture-themes/{id}/logo`). Give its `id` as `theme_id` to a capture template to use it. Your first theme becomes your default theme; there is no limit on the number of themes. `409 theme_name_taken` if another active theme has this name. Themes are the same in test and live. This route requires the `manage_templates` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"locale":{"default":"en","type":"string","enum":["en","fr","es","de"],"description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]}},"required":["name"],"additionalProperties":false}}}},"security":[{"bearerAuth":[]}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the theme, to give in `theme_id` of a capture template.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"type":"string","description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","examples":["#1f6b52"]},"locale":{"type":"string","description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]},"has_logo":{"type":"boolean","description":"`true` when the theme has a logo, shown at the top of the capture page."},"is_default":{"type":"boolean","description":"`true` for the default theme: the one the capture page takes when the template of the session does not name another."}},"required":["id","name","primary_color","locale","has_logo","is_default"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"get":{"summary":"List capture themes","tags":["Capture themes"],"description":"Lists the active capture themes of your organization: the default one first, then by name. Archived themes are not listed. This route requires the `manage_templates` scope.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the theme, to give in `theme_id` of a capture template.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"type":"string","description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","examples":["#1f6b52"]},"locale":{"type":"string","description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]},"has_logo":{"type":"boolean","description":"`true` when the theme has a logo, shown at the top of the capture page."},"is_default":{"type":"boolean","description":"`true` for the default theme: the one the capture page takes when the template of the session does not name another."}},"required":["id","name","primary_color","locale","has_logo","is_default"],"additionalProperties":false},"description":"Your capture themes: the default one first, then by name."}},"required":["data"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-themes/{id}":{"get":{"summary":"Get a capture theme","tags":["Capture themes"],"description":"Returns one capture theme by its `id`. This route requires the `manage_templates` scope.","parameters":[{"schema":{"type":"string","maxLength":40},"example":"thm_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the theme (`thm_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the theme, to give in `theme_id` of a capture template.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"type":"string","description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","examples":["#1f6b52"]},"locale":{"type":"string","description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]},"has_logo":{"type":"boolean","description":"`true` when the theme has a logo, shown at the top of the capture page."},"is_default":{"type":"boolean","description":"`true` for the default theme: the one the capture page takes when the template of the session does not name another."}},"required":["id","name","primary_color","locale","has_logo","is_default"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"patch":{"summary":"Update a capture theme","tags":["Capture themes"],"description":"Changes the name, the main color or the language of a theme. Send only the fields to change, at least one. Capture sessions already created keep the look they were given. This route requires the `manage_templates` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80,"description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","type":"string","pattern":"^#[0-9a-fA-F]{6}$"},"locale":{"type":"string","enum":["en","fr","es","de"],"description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","maxLength":40},"example":"thm_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the theme (`thm_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the theme, to give in `theme_id` of a capture template.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"type":"string","description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","examples":["#1f6b52"]},"locale":{"type":"string","description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]},"has_logo":{"type":"boolean","description":"`true` when the theme has a logo, shown at the top of the capture page."},"is_default":{"type":"boolean","description":"`true` for the default theme: the one the capture page takes when the template of the session does not name another."}},"required":["id","name","primary_color","locale","has_logo","is_default"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"delete":{"summary":"Archive a capture theme","tags":["Capture themes"],"description":"Archives a theme: it is no longer listed or selectable, and capture sessions already created keep their look. The default theme cannot be archived (`409 theme_is_default`), nor a theme a capture template uses (`409 theme_in_use`: give the template another theme first). This route requires the `manage_templates` scope.","parameters":[{"schema":{"type":"string","maxLength":40},"example":"thm_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the theme (`thm_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"204":{"description":"Default Response"},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-themes/{id}/default":{"post":{"summary":"Make a capture theme the default","tags":["Capture themes"],"description":"Makes this theme the default one: the capture page takes it when the template of the session does not name another theme. This route requires the `manage_templates` scope.","parameters":[{"schema":{"type":"string","maxLength":40},"example":"thm_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the theme (`thm_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the theme, to give in `theme_id` of a capture template.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"type":"string","description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","examples":["#1f6b52"]},"locale":{"type":"string","description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]},"has_logo":{"type":"boolean","description":"`true` when the theme has a logo, shown at the top of the capture page."},"is_default":{"type":"boolean","description":"`true` for the default theme: the one the capture page takes when the template of the session does not name another."}},"required":["id","name","primary_color","locale","has_logo","is_default"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-themes/{id}/logo":{"put":{"summary":"Set the logo of a capture theme","tags":["Capture themes"],"description":"Sets or replaces the logo of a theme, shown at the top of the capture page. A PNG image only (`data:image/png;base64,…`), 64 KB at most, 512 × 512 pixels at most, without any extra data: otherwise `422` with the reason in `code` (`logo_invalid`, `logo_too_large`, `logo_too_big_dimensions`…). This route requires the `manage_templates` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"logo":{"type":"string","minLength":30,"maxLength":90000,"description":"The logo, as a `data:image/png;base64,…` URL. A PNG image only, 64 KB at most and 512 × 512 pixels at most."}},"required":["logo"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string","maxLength":40},"example":"thm_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the theme (`thm_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the theme, to give in `theme_id` of a capture template.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"type":"string","description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","examples":["#1f6b52"]},"locale":{"type":"string","description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]},"has_logo":{"type":"boolean","description":"`true` when the theme has a logo, shown at the top of the capture page."},"is_default":{"type":"boolean","description":"`true` for the default theme: the one the capture page takes when the template of the session does not name another."}},"required":["id","name","primary_color","locale","has_logo","is_default"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"delete":{"summary":"Remove the logo of a capture theme","tags":["Capture themes"],"description":"Removes the logo of a theme: the capture page shows no logo for it. This route requires the `manage_templates` scope.","parameters":[{"schema":{"type":"string","maxLength":40},"example":"thm_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the theme (`thm_…`)."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the theme, to give in `theme_id` of a capture template.","examples":["thm_01m4akapdbe8e8qq3er9r5qwyj"]},"name":{"type":"string","description":"The name of the theme, 1 to 80 characters, unique among the active themes of your organization (the case does not matter). The capture page shows it as the name of your brand.","examples":["Gîte du Lac"]},"primary_color":{"type":"string","description":"The main color of the capture page, `#rrggbb`. It must be dark enough to be read on the page: a color that is too light is refused with `422 color_not_readable`.","examples":["#1f6b52"]},"locale":{"type":"string","description":"The language the capture page starts in when the session does not ask for another one: `en`, `fr`, `es` or `de`.","examples":["fr"]},"has_logo":{"type":"boolean","description":"`true` when the theme has a logo, shown at the top of the capture page."},"is_default":{"type":"boolean","description":"`true` for the default theme: the one the capture page takes when the template of the session does not name another."}},"required":["id","name","primary_color","locale","has_logo","is_default"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/settings":{"get":{"summary":"Get your settings","tags":["Settings"],"description":"Returns the settings of your organization for the mode of your key: the sites a capture session may send the person back to, and the language of your organization. The return sites are separate for test and live: a test key reads and changes the test ones only; the language is the same for both. Requires the `manage_settings` scope.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"allowed_return_origins":{"type":"array","items":{"type":"string"},"description":"The sites a capture session may send the person back to once the capture is finished (`return_url`), as origins: `https://app.example.com`, without a path. At most 20. `http://localhost` is accepted for development, and only for sandbox keys when a session is created. An empty list means no return URL is accepted.","examples":[["https://app.example.com"]]},"locale":{"type":"string","enum":["en","fr"],"description":"The language of your organization: the language of the e-mails and of the customer area for the people of your team who have not chosen their own. `en` or `fr`; any other language is English. It is the same in test and live.","examples":[["fr"]]}},"required":["allowed_return_origins","locale"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}},"patch":{"summary":"Update your settings","tags":["Settings"],"description":"Changes the settings of your organization for the mode of your key (a test key changes the test return sites only, never the live ones; the language is shared). Send only the fields to change, at least one; a list you send replaces the previous list entirely. `locale` (`en` or `fr`) is the language of the e-mails and of the customer area for the people of your team who have not chosen their own. `allowed_return_origins` must be sites (`https://app.example.com`, no path): a capture session can only return the person to one of them. Requires the `manage_settings` scope.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"allowed_return_origins":{"maxItems":20,"type":"array","items":{"type":"string","maxLength":255},"description":"The sites a capture session may send the person back to once the capture is finished (`return_url`), as origins: `https://app.example.com`, without a path. At most 20. `http://localhost` is accepted for development, and only for sandbox keys when a session is created. An empty list means no return URL is accepted.","examples":[["https://app.example.com"]]},"locale":{"type":"string","enum":["en","fr"],"description":"The language of your organization: the language of the e-mails and of the customer area for the people of your team who have not chosen their own. `en` or `fr`; any other language is English. It is the same in test and live.","examples":[["fr"]]}},"additionalProperties":false}}}},"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"allowed_return_origins":{"type":"array","items":{"type":"string"},"description":"The sites a capture session may send the person back to once the capture is finished (`return_url`), as origins: `https://app.example.com`, without a path. At most 20. `http://localhost` is accepted for development, and only for sandbox keys when a session is created. An empty list means no return URL is accepted.","examples":[["https://app.example.com"]]},"locale":{"type":"string","enum":["en","fr"],"description":"The language of your organization: the language of the e-mails and of the customer area for the people of your team who have not chosen their own. `en` or `fr`; any other language is English. It is the same in test and live.","examples":[["fr"]]}},"required":["allowed_return_origins","locale"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/credits":{"get":{"summary":"Get your balance","tags":["Credits"],"description":"Returns the balance of your account in euros, with the total added and the total debited. The balance belongs to the account, not to a mode: a sandbox key (`sk_test_…`) shows the same balance, but only proofs sealed in production debit it. Requires the `read_proof` scope.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"balance":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Balance in euros: everything added minus everything debited. It can be negative: we do not block you when it reaches zero.","examples":[940]},"granted":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Total added to your account, in euros.","examples":[1000]},"consumed":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Total debited, in euros (a positive number): the price of each proof sealed in production.","examples":[60]}},"required":["balance","granted","consumed"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/credits/transactions":{"get":{"summary":"List balance movements","tags":["Credits"],"description":"Lists the funds added to your account and the debits, in euros, with cursor pagination. Filter by `type`; sort with `sort`. Each consumption points to the proof that caused it. A cursor that was altered, or that comes from the other sort order, fails with `422 invalid_cursor`. Requires the `read_proof` scope.","parameters":[{"schema":{"default":50,"type":"integer","minimum":1,"maximum":100},"example":20,"in":"query","name":"limit","required":false,"description":"How many movements to return, from 1 to 100."},{"schema":{"type":"string","maxLength":300},"in":"query","name":"cursor","required":false,"description":"The `next_cursor` of the previous page. Opaque: do not build or change it."},{"schema":{"type":"string","enum":["grant","consumption"]},"example":"consumption","in":"query","name":"type","required":false,"description":"Only the movements of this type."},{"schema":{"default":"-created_at","type":"string","enum":["created_at","-created_at"]},"in":"query","name":"sort","required":false,"description":"Order by date: `created_at` oldest first, `-created_at` newest first."}],"security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the movement.","examples":["cre_01m4akapdbe8e8qq3er9r5qwyj"]},"type":{"type":"string","enum":["grant","consumption"],"description":"`grant`: funds added. `consumption`: a debit.","examples":["consumption"]},"amount":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Amount of this movement, in euros: positive for a `grant`, negative for a `consumption`.","examples":[-1]},"reason":{"type":"string","description":"Why. For a `grant`: `purchase`, `gift` or `adjustment`. For a `consumption`: what was used, for example `proof_sealed`, or `refund` / `dispute` when credits were taken back after a refund or a payment dispute.","examples":["proof_sealed"]},"proof_id":{"description":"The proof that caused the debit, for a `consumption`; `null` otherwise.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"],"type":["string","null"]},"created_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the movement was recorded (ISO 8601, UTC)."}},"required":["id","type","amount","reason","proof_id","created_at"],"additionalProperties":false},"description":"The movements of this page."},"has_more":{"type":"boolean","description":"`true` when another page exists."},"next_cursor":{"description":"Give it as `cursor` to get the next page; `null` on the last page.","type":["string","null"]}},"required":["data","has_more","next_cursor"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/me":{"get":{"summary":"Check your API key","tags":["Account"],"description":"Returns the organization, the mode and the scopes of the key used for the call. A quick way to check that a key works.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"organization_id":{"type":"string","description":"Identifier of the organization the key belongs to.","examples":["org_01m4akapdbe8e8qq3er9r5qwyj"]},"mode":{"type":"string","enum":["live","test"],"description":"Mode of the key.","examples":["test"]},"key":{"type":"object","properties":{"prefix":{"type":"string","description":"The first characters of the key, to recognize it. Never enough to use it.","examples":["sk_test_AbCd"]},"label":{"description":"The name given to the key, if any.","type":["string","null"]},"scopes":{"type":"array","items":{"type":"string"},"description":"What the key may do: `create_proof`, `read_proof`, `manage_webhooks`, `manage_templates`.","examples":[["create_proof","read_proof"]]}},"required":["prefix","label","scopes"],"additionalProperties":false,"description":"The key you are using."}},"required":["organization_id","mode","key"],"additionalProperties":false}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-sessions/{token}/uploads":{"post":{"summary":"Request upload links","tags":["Capture page"],"description":"Declares the files about to be sent and returns, for each one, a temporary link to send it to **directly** (a single `PUT` for a photo, one `PUT` per part for a video). The files never go through the API. The token in the URL is the credential. Refused with `413 file_too_large` if a file is over the limit, and with `422` for a type that is not accepted or too many files.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"files":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"media_type":{"type":"string","enum":["photo","video"],"description":"Kind of file.","examples":["photo"]},"mime_type":{"type":"string","minLength":1,"maxLength":100,"description":"Type of the file. It must be one of the types listed in `constraints` of the capture session, and it is checked against the file itself.","examples":["image/jpeg"]},"size_bytes":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"Exact size of the file in bytes. A file whose size differs from this declaration is rejected when the proof is processed.","examples":[183422]},"label":{"type":"string","pattern":"^[a-z0-9_.-]{1,64}$","description":"A short identifier for the shot (`front`, `rear_left`…). Lowercase letters, digits, `_`, `.` and `-`.","examples":["front"]}},"required":["media_type","mime_type","size_bytes"],"additionalProperties":false},"description":"The files you are about to send, from 1 to 100."}},"required":["files"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"example":"3f9aXq…","in":"path","name":"token","required":true,"description":"The session token: the last part of `capture_url`."}],"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"uploads":{"type":"array","items":{"oneOf":[{"type":"object","properties":{"upload_id":{"type":"string","description":"Identifier of this upload. Give it back when you finalize.","examples":["upl_01m4akapdbe8e8qq3er9r5qwyj"]},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the upload link stops working (ISO 8601, UTC)."},"method":{"type":"string","description":"Send the whole file in one `PUT` request. Used for photos.","enum":["PUT"]},"url":{"type":"string","description":"Where to send the file. It carries its own authorization: do not add an `Authorization` header."},"headers":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"string"},"description":"Headers to send with the `PUT`, exactly as given (the `Content-Type` is part of the signature).","examples":[{"Content-Type":"image/jpeg"}]}},"required":["upload_id","expires_at","method","url","headers"],"additionalProperties":false},{"type":"object","properties":{"upload_id":{"type":"string","description":"Identifier of this upload. Give it back when you finalize.","examples":["upl_01m4akapdbe8e8qq3er9r5qwyj"]},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the upload link stops working (ISO 8601, UTC)."},"method":{"type":"string","description":"Send the file in parts, each with a `PUT`. Used for videos.","enum":["MULTIPART"]},"part_size_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Size of each part in bytes, except the last one which may be smaller."},"parts":{"type":"array","items":{"type":"object","properties":{"part_number":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Number of the part, starting at 1."},"url":{"type":"string","description":"Where to `PUT` this part. Keep the `ETag` header of the answer: you need it to finalize."}},"required":["part_number","url"],"additionalProperties":false},"description":"One link per part."}},"required":["upload_id","expires_at","method","part_size_bytes","parts"],"additionalProperties":false}]},"description":"One entry per file, in the order you declared them."}},"required":["uploads"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"410":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"413":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-sessions/{token}/uploads/{upload_id}":{"delete":{"summary":"Remove an upload","tags":["Capture page"],"description":"Removes an upload that is still open in this session, for example when the person retakes a photo: the file is deleted right away, it no longer counts toward the limit of files, and it can no longer be finalized. The `upload_id` is the one returned when you requested the upload links. `404 upload_not_found` for any other value (unknown, already finalized, or from another session).","parameters":[{"schema":{"type":"string"},"example":"3f9aXq…","in":"path","name":"token","required":true,"description":"The session token: the last part of `capture_url`."},{"schema":{"type":"string"},"example":"upl_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"upload_id","required":true,"description":"The identifier of the upload, as returned when you requested the upload links."}],"responses":{"204":{"description":"Default Response"},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"410":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-sessions/{token}/finalize":{"post":{"summary":"Finalize a capture","tags":["Capture page"],"description":"Call this once every file has been sent. It checks that the files are in storage and creates the proof, which starts as `pending`; we then verify the files, sign them and obtain a timestamp for the proof. The answer is `202`: the sealing happens right afterwards, usually within seconds, and is announced by the `proof.sealed` webhook.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"files":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"object","properties":{"upload_id":{"type":"string","maxLength":40,"description":"The `upload_id` you received for this file.","examples":["upl_01m4akapdbe8e8qq3er9r5qwyj"]},"sha256":{"type":"string","pattern":"^[0-9a-f]{64}$","description":"SHA-256 of the file, as 64 lowercase hexadecimal characters. It is a transfer check: we recompute it from the stored file and never trust this value alone.","examples":["8061db5cea33116b0b1210a18998d1005efc128ac2d93a33000a8b0cdddd7145"]},"size_bytes":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991,"description":"Exact size of the file in bytes, as declared when requesting the upload.","examples":[183422]},"parts":{"maxItems":10000,"type":"array","items":{"type":"object","properties":{"part_number":{"type":"integer","minimum":1,"maximum":10000,"description":"Number of the part, starting at 1."},"etag":{"type":"string","minLength":1,"maxLength":200,"description":"The `ETag` header returned when this part was sent."}},"required":["part_number","etag"],"additionalProperties":false},"description":"Required for a video sent in parts: every part with its `ETag`. Leave it out for a photo."}},"required":["upload_id","sha256","size_bytes"],"additionalProperties":false},"description":"Every file of the capture, once sent."},"skipped":{"default":[],"description":"The shots the person declares instead of photographing. A skipped shot counts as done even if it is required, has no photo, and is kept with the proof (`skipped` on the proof). `422 skip_not_allowed` when the template does not allow it.","maxItems":30,"type":"array","items":{"type":"object","properties":{"step_id":{"type":"string","maxLength":64,"description":"The `id` of the shot of the template that is left without photos.","examples":["garden"]},"reason":{"type":"string","enum":["nothing_to_report","not_applicable"],"description":"Why: `nothing_to_report` (nothing to note there) or `not_applicable` (the shot does not apply to this item). The template must allow it for this shot (`allowed_skips`).","examples":["nothing_to_report"]}},"required":["step_id","reason"],"additionalProperties":false}}},"required":["files"],"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"example":"3f9aXq…","in":"path","name":"token","required":true,"description":"The session token: the last part of `capture_url`."}],"responses":{"202":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"proof_id":{"type":"string","description":"Identifier of the proof being created. Read it with `GET /v1/proofs/{id}`.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"status":{"type":"string","enum":["pending","processing","sealed","failed"],"description":"Status of the proof: `pending` right after finalization. Sealing takes a little while and is announced by the `proof.sealed` webhook.","examples":["pending"]}},"required":["proof_id","status"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"410":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-sessions/{token}/before":{"get":{"summary":"Read the \"before\" photos of a capture","tags":["Capture page"],"description":"Used by the capture page when the session completes an earlier proof (`compare_to`): returns temporary links to the photos of that \"before\", so the person can take the same ones. Only the photos, never the reference or any other data of the \"before\". The token in the URL is the credential. `404 no_before_photos` for an ordinary session, `410` once expired, `409` once used, `403 organization_suspended` when the organization is suspended or closed.","parameters":[{"schema":{"type":"string"},"example":"3f9aXq…","in":"path","name":"token","required":true,"description":"The session token: the last part of `capture_url`."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"photos":{"type":"array","items":{"type":"object","properties":{"step_id":{"description":"The `id` of the shot of the template this photo answers (`other`: an extra photo); `null` if the photo had no shot.","examples":["front"],"type":["string","null"]},"url":{"type":"string","description":"A temporary link to the photo of the \"before\", to show next to the camera so the person can take the same one. It stops working at `expires_at`.","examples":["https://storage.example.com/signed/…?X-Amz-Signature=…"]},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the link stops working (ISO 8601, UTC)."}},"required":["step_id","url","expires_at"],"additionalProperties":false},"description":"The photos of the \"before\", in the order they were taken."}},"required":["photos"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"410":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/public/proofs/{id}":{"get":{"summary":"Get the public status of a proof","tags":["Public verification"],"description":"Public, no API key, limited per IP address. Returns the status of a proof and its timestamp, so anyone holding the identifier can check it. Never the files, never the name of the organization, never the external reference.","parameters":[{"schema":{"type":"string"},"example":"prf_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the proof."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the proof.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"status":{"type":"string","enum":["pending","processing","sealed","failed"],"description":"Same meanings as on `GET /v1/proofs/{id}`.","examples":["sealed"]},"mode":{"type":"string","enum":["live","test"],"description":"`test`: the timestamp is simulated and has no legal value.","examples":["test"]},"sealed_at":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"},{"type":"null"}],"description":"When the proof was sealed (ISO 8601, UTC); `null` until then."},"timestamp":{"anyOf":[{"type":"object","properties":{"mode":{"type":"string","enum":["direct","merkle_batch"],"description":"`direct`: the proof has its own timestamp token. `merkle_batch`: the token certifies a batch of proofs, with a Merkle path for each.","examples":["direct"]},"authority":{"type":"string","description":"Who issued the timestamp (`simulated` in test mode)."},"qualified":{"type":"boolean","description":"Whether the timestamp is a qualified one under eIDAS. Always `false` for a simulated timestamp."},"gen_time":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"The time certified by the authority: the proof existed at the latest at this time (ISO 8601, UTC). With `qualified: true` it is an eIDAS qualified timestamp, to the second. It is not the time of capture."},"serial":{"description":"Serial number of the timestamp token.","type":["string","null"]}},"required":["mode","authority","qualified","gen_time","serial"],"additionalProperties":false},{"type":"null"}],"description":"The timestamp of the proof; `null` until the proof is sealed."}},"required":["id","status","mode","sealed_at","timestamp"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/public/proofs/{id}/bundle":{"get":{"summary":"Get the verification bundle of a proof","tags":["Public verification"],"description":"Public, no API key. Returns everything independent software needs to verify a **sealed** proof without trusting us: the fingerprints, the Merkle proof and the timestamp token (RFC 3161, base64). For a proof that exists but is not sealed yet: `409 proof_not_sealed`.","parameters":[{"schema":{"type":"string"},"example":"prf_01m4akapdbe8e8qq3er9r5qwyj","in":"path","name":"id","required":true,"description":"Identifier of the proof."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"version":{"type":"number","description":"Version of the bundle format.","enum":[1]},"proof_id":{"type":"string","description":"Identifier of the proof."},"organization_id":{"type":"string","description":"Identifier of the organization that created the proof."},"mode":{"type":"string","enum":["live","test"],"description":"Mode of the proof."},"external_reference_commitment":{"type":"string","description":"A cryptographic commitment to the external reference. The reference itself is never public; with the reference and salt you were given, anyone can check it matches."},"declared_by_platform":{"type":"object","properties":{"party":{"type":"string","enum":["provider","recipient"],"description":"Who the platform said was capturing."},"stage":{"description":"The stage the platform declared.","type":["string","null"]}},"required":["party","stage"],"additionalProperties":false,"description":"What the platform declared. It is reported as declared, never as verified."},"capture":{"type":"object","properties":{"method":{"type":"string","enum":["hosted_live","direct_upload"],"description":"How the files were captured: on the hosted capture page, or uploaded directly."},"session_id":{"description":"The capture session, if there was one.","type":["string","null"]}},"required":["method","session_id"],"additionalProperties":false,"description":"How the capture happened."},"generator":{"type":"object","properties":{"name":{"type":"string","description":"Name of the software that produced the proof."},"version":{"type":"string","description":"Its version."}},"required":["name","version"],"additionalProperties":false,"description":"The software that produced the proof, and its version."},"media":{"type":"array","items":{"type":"object","properties":{"media_type":{"type":"string","enum":["photo","video"],"description":"Kind of file."},"mime_type":{"type":"string","description":"Type of the file.","examples":["image/jpeg"]},"byte_size":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Size of the original file in bytes."},"captured_at":{"type":"string","description":"When our service observed the file (ISO 8601, UTC). Not a qualified timestamp."},"original_sha256":{"type":"string","description":"SHA-256 of the original file. Compare it with the file you hold."},"signed_sha256":{"type":"string","description":"SHA-256 of the signed copy (C2PA)."},"manifest_id":{"type":"string","description":"Identifier of the C2PA manifest embedded in the signed copy."},"key_version":{"type":"string","description":"Version of the signing key that signed the copy."}},"required":["media_type","mime_type","byte_size","captured_at","original_sha256","signed_sha256","manifest_id","key_version"],"additionalProperties":false},"description":"The files of the proof, in order."},"manifest_sha256":{"type":"string","description":"Hash of the manifest that describes the proof. In `direct` mode the timestamp token certifies this value; in `merkle_batch` mode it is the leaf of the Merkle tree."},"timestamp":{"anyOf":[{"type":"object","properties":{"mode":{"type":"string","description":"Always `direct`: the proof has its own timestamp token.","enum":["direct"]},"tsr_base64":{"type":"string","description":"The RFC 3161 timestamp token, in base64. It certifies `manifest_sha256` itself: check it with `openssl ts -verify -digest <manifest_sha256> -in token.tsr -CAfile chain.pem`."},"authority":{"type":"string","description":"Who issued the timestamp (`simulated` in test mode)."},"qualified":{"type":"boolean","description":"Declared by the service. A verifier recomputes it and never trusts this field."},"gen_time":{"type":"string","description":"The time certified by the authority (ISO 8601, UTC): the proof existed at the latest at this time."},"serial":{"type":"string","description":"Serial number of the timestamp token."},"policy_oid":{"description":"Policy identifier of the timestamp authority, if given.","type":["string","null"]}},"required":["mode","tsr_base64","authority","qualified","gen_time","serial","policy_oid"],"additionalProperties":false},{"type":"null"}],"description":"The timestamp of the proof, in `direct` mode (the default). `null` for a proof timestamped in a batch (see `batch`) and until the proof is sealed. Once the proof is sealed, exactly one of `timestamp` and `batch` is set."},"batch":{"anyOf":[{"type":"object","properties":{"merkle_root":{"type":"string","description":"Root of the Merkle tree of the batch. The timestamp token certifies this value."},"leaf_index":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Position of this proof among the leaves of the tree."},"merkle_path":{"type":"array","items":{"type":"object","properties":{"hash":{"type":"string","description":"Hash of the neighbouring node in the Merkle tree."},"position":{"type":"string","enum":["left","right"],"description":"Side on which that hash is combined with yours."}},"required":["hash","position"],"additionalProperties":false},"description":"The hashes to combine, from the leaf up to the root, to prove this proof belongs to the batch."},"tsr_base64":{"type":"string","description":"The RFC 3161 timestamp token, in base64."},"authority":{"type":"string","description":"Who issued the timestamp (`simulated` in test mode)."},"qualified":{"type":"boolean","description":"Declared by the service. A verifier recomputes it and never trusts this field."},"gen_time":{"type":"string","description":"The time certified by the authority (ISO 8601, UTC)."},"serial":{"type":"string","description":"Serial number of the timestamp token."},"policy_oid":{"description":"Policy identifier of the timestamp authority, if given.","type":["string","null"]}},"required":["merkle_root","leaf_index","merkle_path","tsr_base64","authority","qualified","gen_time","serial","policy_oid"],"additionalProperties":false},{"type":"null"}],"description":"The timestamp of a proof timestamped in a batch (`merkle_batch` mode, off by default): the batch token and the Merkle path from this proof to its root. `null` in `direct` mode."}},"required":["version","proof_id","organization_id","mode","external_reference_commitment","declared_by_platform","capture","generator","media","manifest_sha256","timestamp","batch"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}},"/v1/capture-sessions/{token}":{"get":{"summary":"Read a capture session","tags":["Capture page"],"description":"Used by the capture page: returns what it needs to run (who captures, the look of the page, the template texts in the language of the person, the accepted file types and sizes). The token in the URL is the credential, no API key is needed. Fails with `404` for an unknown token, `410` once expired, `409` once the session has been used and `403 organization_suspended` once the organization is suspended or closed.","parameters":[{"schema":{"type":"string","maxLength":35,"pattern":"^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$"},"example":"es","in":"query","name":"locale","required":false,"description":"Show the template texts in this language instead of the language chosen when the session was created, for example when the person switches language on the page. A text that does not exist in this language falls back to the base language (`pt` for `pt-BR`), then to the default language of the template, then to English."},{"schema":{"type":"string"},"example":"3f9aXq…","in":"path","name":"token","required":true,"description":"The session token: the last part of `capture_url`."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the capture session.","examples":["cps_01m4akapdbe8e8qq3er9r5qwyj"]},"status":{"type":"string","description":"Always `pending`: an expired or used session is refused with an error instead.","enum":["pending"]},"mode":{"type":"string","enum":["live","test"],"description":"Mode of the key that created the session.","examples":["test"]},"expires_at":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$","description":"When the session stops working (ISO 8601, UTC)."},"party":{"type":"string","enum":["provider","recipient"],"description":"Who is capturing.","examples":["provider"]},"stage":{"description":"The moment of the transaction declared when the session was created, if any.","examples":["pickup"],"type":["string","null"]},"theme":{"type":"object","properties":{"name":{"type":"string","description":"Name to show on the capture page."},"logo_url":{"description":"Logo to show, if the organization has one.","type":["string","null"]},"primary_color":{"type":"string","description":"Main color of the page, as a hexadecimal code.","examples":["#1F6B52"]},"locale":{"type":"string","description":"Language of the page.","examples":["en"]}},"required":["name","logo_url","primary_color","locale"],"additionalProperties":false,"description":"How the capture page looks. It never includes the external reference or the organization."},"has_before":{"type":"boolean","description":"`true` when this capture completes an earlier proof (`compare_to`): the page then reads the photos of that \"before\" with `GET /v1/capture-sessions/{token}/before` to show them to the person. `false` for an ordinary capture."},"return_url":{"description":"Where to take the person once the capture is finished, as chosen when the session was created, or `null`. The page adds `proof_id` and `session_id` to it.","examples":["https://app.example.com/bookings/4471/capture-done"],"type":["string","null"]},"locale":{"type":"string","description":"The language the page and the template texts are shown in: the one asked for in the query, else the one chosen when the session was created, else the one of the theme.","examples":["de"]},"available_locales":{"type":"array","items":{"type":"string"},"description":"The languages the template has texts for, so the page can offer a language switch. Empty when no template applies.","examples":[["de","en","fr"]]},"template":{"anyOf":[{"type":"object","properties":{"name":{"type":"string","description":"Name of the template that applies to this session.","examples":["pickup_car"]},"welcome":{"type":"object","properties":{"title":{"description":"Title of the welcome screen, or `null` to use the page's own text.","type":["string","null"]},"body":{"description":"Text of the welcome screen, or `null` to use the page's own text.","type":["string","null"]}},"required":["title","body"],"additionalProperties":false,"description":"The welcome screen."},"completion":{"type":"object","properties":{"title":{"description":"Title of the completion screen, or `null` to use the page's own text.","type":["string","null"]},"body":{"description":"Text of the completion screen, or `null` to use the page's own text.","type":["string","null"]}},"required":["title","body"],"additionalProperties":false,"description":"The completion screen."},"steps":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the shot, stable across edits.","examples":["front"]},"label":{"type":"string","description":"Short name of the shot, shown to the person.","examples":["Front of the vehicle"]},"instruction":{"description":"What to do for this shot, shown under the label, if the template gives one.","examples":["Stand back so the whole front is visible."],"type":["string","null"]},"required":{"type":"boolean","description":"`true` when the capture cannot be finished without this shot."},"min_photos":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many photos at least this shot needs when `required` is `true` (ignored otherwise).","examples":[2]},"max_photos":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many photos at most the person can take for this shot.","examples":[6]},"allowed_skips":{"type":"array","items":{"type":"string","enum":["nothing_to_report","not_applicable"]},"description":"What the person may declare instead of taking photos of this shot (`nothing_to_report`, `not_applicable`); empty: the shot cannot be skipped.","examples":[["nothing_to_report"]]},"section":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","description":"Identifier of the step.","examples":["kitchen"]},"label":{"type":"string","description":"Name of the step, shown above its shots.","examples":["Kitchen"]}},"required":["id","label"],"additionalProperties":false},{"type":"null"}],"description":"The step (a room, an area) this shot belongs to; consecutive shots with the same `section.id` are shown together under its name. `null`: a shot of its own."}},"required":["id","label","instruction","required","min_photos","max_photos","allowed_skips","section"],"additionalProperties":false},"description":"The shots to take, in order. An empty list means: take photos freely."},"max_extra_photos":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"How many extra photos, matching none of the shots, the person can add. `0`: none.","examples":[10]}},"required":["name","welcome","completion","steps","max_extra_photos"],"additionalProperties":false,"description":"What the page asks the person to do. A copy is made when the session is created, so editing the template later does not change a link already sent."},{"type":"null"}],"description":"The capture template that applies, or `null` when none does: the page then shows its default screens."},"constraints":{"type":"object","properties":{"photo":{"type":"object","properties":{"mime_types":{"type":"array","items":{"type":"string"},"description":"File types accepted for a photo."},"max_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Largest accepted size of one photo, in bytes."}},"required":["mime_types","max_bytes"],"additionalProperties":false,"description":"What the page may send as a photo."},"video":{"type":"object","properties":{"mime_types":{"type":"array","items":{"type":"string"},"description":"File types accepted for a video."},"max_bytes":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991,"description":"Largest accepted size of one video, in bytes."}},"required":["mime_types","max_bytes"],"additionalProperties":false,"description":"What the page may send as a video."}},"required":["photo","video"],"additionalProperties":false,"description":"What the page may send. Anything else is refused."}},"required":["id","status","mode","expires_at","party","stage","theme","has_before","return_url","locale","available_locales","template","constraints"],"additionalProperties":false}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"410":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}},"429":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"},"title":{"type":"string"},"status":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"code":{"type":"string"},"field":{"type":"string"}},"required":["type","title","status","code"],"additionalProperties":false}}}}}}}},"servers":[{"url":"https://api.tryvidimus.com","description":"The API. The key you use decides the mode: sk_test_… for the sandbox, sk_live_… for production."}],"tags":[{"name":"Capture sessions","description":"Start here. A capture session is a one-time link for one person to take the photos or videos of a transaction."},{"name":"Capture templates","description":"Define what the capture page asks for: the shots to take and the welcome and completion texts. Requires the `manage_templates` scope."},{"name":"Capture themes","description":"Define the look of the capture page: a name, a main color, a language and a logo. You can have several themes (one per brand, for example) and choose one per capture template with `theme_id`. Requires the `manage_templates` scope."},{"name":"Capture page","description":"Routes used by the capture page itself, on the phone of the person who captures. They use the session token from the capture URL instead of an API key. You only need them if you build your own capture page."},{"name":"Proofs","description":"Read the proofs of your organization: status, files, and a temporary link to the signed copy."},{"name":"Webhook endpoints","description":"Get notified the moment a proof is sealed or fails. Requires the `manage_webhooks` scope."},{"name":"Webhook events","description":"The messages we send to your webhook endpoints, one entry per event, with the exact JSON body and the headers of each message. You do not call these: you receive them."},{"name":"Credits","description":"See your balance in euros and what debited it. Requires the `read_proof` scope."},{"name":"Settings","description":"Settings of your organization: the sites a capture session may send the person back to, and the language of your organization. Requires the `manage_settings` scope."},{"name":"Public verification","description":"Anyone can check a proof without an account or an API key: its status, and the verification bundle that independent software can verify offline."},{"name":"Account","description":"Check which key you are using: its organization, its mode and its scopes."},{"name":"Health","description":"Check that the API is up and which version is running."}],"webhooks":{"proof.sealed":{"post":{"summary":"A proof is sealed","description":"Sent when a proof is sealed: its files are signed (C2PA) and timestamped (RFC 3161). From now on the proof can be read with `GET /v1/proofs/{id}` and verified by anyone. It follows `capture_session.completed` of the same capture, usually by a few seconds.","tags":["Webhook events"],"parameters":[{"name":"X-Signature","in":"header","required":true,"description":"The signature of the message: `t=<unix seconds>,v1=<signature>` (one `v1` per active secret). The signature is the HMAC-SHA256, in lowercase hexadecimal, of the timestamp `t`, a dot and the raw body, computed with the secret of your endpoint (the whole string, `whsec_` included). Compare it with each `v1` value, and reject the call when `t` is more than 5 minutes old. See the Webhooks section of the introduction for a complete example.","schema":{"type":"string","examples":["t=1791906492,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd"]}},{"name":"X-Webhook-Id","in":"header","required":true,"description":"Identifier of this delivery attempt (`whd_…`). It is the one you find in `GET /v1/webhook-deliveries`.","schema":{"type":"string","examples":["whd_01m4akapdbe8e8qq3er9r5qwyj"]}},{"name":"X-Event-Id","in":"header","required":true,"description":"Identifier of the event (`evt_…`). It is **identical on every retry** of the same event: use it to ignore duplicates.","schema":{"type":"string","examples":["evt_01m4akapdbe8e8qq3er9r5qwyj"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"proof.sealed","description":"Always `proof.sealed`: the proof is sealed (signed and timestamped).","examples":["proof.sealed"]},"proof_id":{"type":"string","description":"Identifier of the proof (`prf_…`). Read it with `GET /v1/proofs/{id}`.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"external_reference":{"type":"string","description":"The reference your platform gave when it created the capture session (`external_reference`), returned unchanged.","examples":["booking_4471"]},"party":{"type":"string","enum":["provider","recipient"],"description":"Who took the photos: the `party` given when the capture session was created.","examples":["provider"]},"stage":{"description":"The `stage` given when the capture session was created (`pickup`, `return`…), or `null` when there was none.","examples":["pickup"],"type":["string","null"]},"status":{"type":"string","const":"sealed","description":"Always `sealed`.","examples":["sealed"]},"sealed_at":{"type":"string","description":"When the proof was sealed, in ISO 8601 UTC.","examples":["2026-10-13T15:48:12.000Z"]},"verify_url":{"description":"Public page where anyone can check the proof, without an account. Always present on the hosted service.","examples":["https://verify.tryvidimus.com/prf_01m4akapdbe8e8qq3er9r5qwyj"],"type":"string"},"test":{"description":"Present, and `true`, only on a test event sent with `POST /v1/webhook-endpoints/{id}/test`. Real events never carry this field.","examples":[true],"type":"boolean"}},"required":["event","proof_id","external_reference","party","stage","status","sealed_at"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Any `2xx` status acknowledges the message. The body of your answer is ignored, but the beginning of it (4096 characters at most) is kept so you can read it in your account and with `GET /v1/webhook-deliveries/{id}`."},"default":{"description":"Anything else (another status, a redirect (we never follow one), no answer within 10 seconds, a connection or certificate error) is a failure: we retry after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then give up (`abandoned`)."}}}},"proof.failed":{"post":{"summary":"A proof could not be sealed","description":"Sent when a proof could not be sealed. Check `retriable` to know whether the failure can be run again or is final.","tags":["Webhook events"],"parameters":[{"name":"X-Signature","in":"header","required":true,"description":"The signature of the message: `t=<unix seconds>,v1=<signature>` (one `v1` per active secret). The signature is the HMAC-SHA256, in lowercase hexadecimal, of the timestamp `t`, a dot and the raw body, computed with the secret of your endpoint (the whole string, `whsec_` included). Compare it with each `v1` value, and reject the call when `t` is more than 5 minutes old. See the Webhooks section of the introduction for a complete example.","schema":{"type":"string","examples":["t=1791906492,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd"]}},{"name":"X-Webhook-Id","in":"header","required":true,"description":"Identifier of this delivery attempt (`whd_…`). It is the one you find in `GET /v1/webhook-deliveries`.","schema":{"type":"string","examples":["whd_01m4akapdbe8e8qq3er9r5qwyj"]}},{"name":"X-Event-Id","in":"header","required":true,"description":"Identifier of the event (`evt_…`). It is **identical on every retry** of the same event: use it to ignore duplicates.","schema":{"type":"string","examples":["evt_01m4akapdbe8e8qq3er9r5qwyj"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"proof.failed","description":"Always `proof.failed`: the proof could not be sealed.","examples":["proof.failed"]},"proof_id":{"type":"string","description":"Identifier of the proof (`prf_…`). Read it with `GET /v1/proofs/{id}`.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"external_reference":{"type":"string","description":"The reference your platform gave when it created the capture session (`external_reference`), returned unchanged.","examples":["booking_4471"]},"party":{"type":"string","enum":["provider","recipient"],"description":"Who took the photos: the `party` given when the capture session was created.","examples":["provider"]},"stage":{"description":"The `stage` given when the capture session was created (`pickup`, `return`…), or `null` when there was none.","examples":["pickup"],"type":["string","null"]},"status":{"type":"string","const":"failed","description":"Always `failed`.","examples":["failed"]},"failure_code":{"type":"string","enum":["hash_mismatch","invalid_media","signing_failed","timestamp_failed"],"description":"Why it failed. `hash_mismatch`: the file we received is not the one declared. `invalid_media`: not a valid photo or video. `signing_failed`: the seal could not be applied. `timestamp_failed`: the independent timestamp could not be obtained.","examples":["timestamp_failed"]},"retriable":{"type":"boolean","description":"`true` when the failure can be run again; `false` when it is final.","examples":[true]},"test":{"description":"Present, and `true`, only on a test event sent with `POST /v1/webhook-endpoints/{id}/test`. Real events never carry this field.","examples":[true],"type":"boolean"}},"required":["event","proof_id","external_reference","party","stage","status","failure_code","retriable"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Any `2xx` status acknowledges the message. The body of your answer is ignored, but the beginning of it (4096 characters at most) is kept so you can read it in your account and with `GET /v1/webhook-deliveries/{id}`."},"default":{"description":"Anything else (another status, a redirect (we never follow one), no answer within 10 seconds, a connection or certificate error) is a failure: we retry after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then give up (`abandoned`)."}}}},"capture_session.completed":{"post":{"summary":"A capture is finished","description":"Sent when the person has finished the capture, a few seconds after the files are saved and **before** the proof is sealed. It is the reliable signal that the capture is done, because the person may close the page before being sent back to your application. Wait for `proof.sealed` before relying on the proof.","tags":["Webhook events"],"parameters":[{"name":"X-Signature","in":"header","required":true,"description":"The signature of the message: `t=<unix seconds>,v1=<signature>` (one `v1` per active secret). The signature is the HMAC-SHA256, in lowercase hexadecimal, of the timestamp `t`, a dot and the raw body, computed with the secret of your endpoint (the whole string, `whsec_` included). Compare it with each `v1` value, and reject the call when `t` is more than 5 minutes old. See the Webhooks section of the introduction for a complete example.","schema":{"type":"string","examples":["t=1791906492,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd"]}},{"name":"X-Webhook-Id","in":"header","required":true,"description":"Identifier of this delivery attempt (`whd_…`). It is the one you find in `GET /v1/webhook-deliveries`.","schema":{"type":"string","examples":["whd_01m4akapdbe8e8qq3er9r5qwyj"]}},{"name":"X-Event-Id","in":"header","required":true,"description":"Identifier of the event (`evt_…`). It is **identical on every retry** of the same event: use it to ignore duplicates.","schema":{"type":"string","examples":["evt_01m4akapdbe8e8qq3er9r5qwyj"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"capture_session.completed","description":"Always `capture_session.completed`: the person finished the capture and the files are saved. The proof is not sealed yet: wait for `proof.sealed`.","examples":["capture_session.completed"]},"session_id":{"type":"string","description":"Identifier of the capture session (`cps_…`).","examples":["cps_01m4akapdbe8e8qq3er9r5qwyj"]},"proof_id":{"type":"string","description":"Identifier of the proof (`prf_…`). Read it with `GET /v1/proofs/{id}`.","examples":["prf_01m4akapdbe8e8qq3er9r5qwyj"]},"external_reference":{"type":"string","description":"The reference your platform gave when it created the capture session (`external_reference`), returned unchanged.","examples":["booking_4471"]},"party":{"type":"string","enum":["provider","recipient"],"description":"Who took the photos: the `party` given when the capture session was created.","examples":["provider"]},"stage":{"description":"The `stage` given when the capture session was created (`pickup`, `return`…), or `null` when there was none.","examples":["pickup"],"type":["string","null"]},"completed_at":{"type":"string","description":"When the capture was finished, in ISO 8601 UTC.","examples":["2026-10-13T15:47:58.000Z"]},"test":{"description":"Present, and `true`, only on a test event sent with `POST /v1/webhook-endpoints/{id}/test`. Real events never carry this field.","examples":[true],"type":"boolean"}},"required":["event","session_id","proof_id","external_reference","party","stage","completed_at"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Any `2xx` status acknowledges the message. The body of your answer is ignored, but the beginning of it (4096 characters at most) is kept so you can read it in your account and with `GET /v1/webhook-deliveries/{id}`."},"default":{"description":"Anything else (another status, a redirect (we never follow one), no answer within 10 seconds, a connection or certificate error) is a failure: we retry after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then give up (`abandoned`)."}}}},"capture_session.rejected":{"post":{"summary":"A capture is refused","description":"Sent when a capture that completes a \"before\" is refused because another capture already completed it (the first one finished wins). Nothing was saved, no proof exists and no credit was used; the person who finished second received `409 compare_to_already_used`.","tags":["Webhook events"],"parameters":[{"name":"X-Signature","in":"header","required":true,"description":"The signature of the message: `t=<unix seconds>,v1=<signature>` (one `v1` per active secret). The signature is the HMAC-SHA256, in lowercase hexadecimal, of the timestamp `t`, a dot and the raw body, computed with the secret of your endpoint (the whole string, `whsec_` included). Compare it with each `v1` value, and reject the call when `t` is more than 5 minutes old. See the Webhooks section of the introduction for a complete example.","schema":{"type":"string","examples":["t=1791906492,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd"]}},{"name":"X-Webhook-Id","in":"header","required":true,"description":"Identifier of this delivery attempt (`whd_…`). It is the one you find in `GET /v1/webhook-deliveries`.","schema":{"type":"string","examples":["whd_01m4akapdbe8e8qq3er9r5qwyj"]}},{"name":"X-Event-Id","in":"header","required":true,"description":"Identifier of the event (`evt_…`). It is **identical on every retry** of the same event: use it to ignore duplicates.","schema":{"type":"string","examples":["evt_01m4akapdbe8e8qq3er9r5qwyj"]}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"event":{"type":"string","const":"capture_session.rejected","description":"Always `capture_session.rejected`: a capture was refused because another capture already completed the same \"before\".","examples":["capture_session.rejected"]},"session_id":{"type":"string","description":"Identifier of the capture session (`cps_…`).","examples":["cps_01m4akapdbe8e8qq3er9r5qwyj"]},"code":{"type":"string","const":"compare_to_already_used","description":"Why it was refused. `compare_to_already_used`: another capture already completed the \"before\" this one compared to. Nothing was saved and no credit was used.","examples":["compare_to_already_used"]},"compare_to":{"type":"string","description":"The \"before\" proof (`prf_…`) this capture wanted to complete.","examples":["prf_01m4akapdbe8ev5xgt0hkpcn14"]},"external_reference":{"type":"string","description":"The reference your platform gave when it created the capture session (`external_reference`), returned unchanged.","examples":["booking_4471"]},"party":{"type":"string","enum":["provider","recipient"],"description":"Who took the photos: the `party` given when the capture session was created.","examples":["provider"]},"stage":{"description":"The `stage` given when the capture session was created (`pickup`, `return`…), or `null` when there was none.","examples":["pickup"],"type":["string","null"]},"rejected_at":{"type":"string","description":"When the capture was refused, in ISO 8601 UTC.","examples":["2026-10-13T15:49:03.000Z"]},"test":{"description":"Present, and `true`, only on a test event sent with `POST /v1/webhook-endpoints/{id}/test`. Real events never carry this field.","examples":[true],"type":"boolean"}},"required":["event","session_id","code","compare_to","external_reference","party","stage","rejected_at"],"additionalProperties":false}}}},"responses":{"2XX":{"description":"Any `2xx` status acknowledges the message. The body of your answer is ignored, but the beginning of it (4096 characters at most) is kept so you can read it in your account and with `GET /v1/webhook-deliveries/{id}`."},"default":{"description":"Anything else (another status, a redirect (we never follow one), no answer within 10 seconds, a connection or certificate error) is a failure: we retry after 1 minute, 5 minutes, 30 minutes, 2 hours and 12 hours, then give up (`abandoned`)."}}}}}}