{
  "openapi": "3.0.3",
  "info": {
    "title": "ProofSnap API",
    "version": "2.0.0",
    "license": {
      "name": "Proprietary",
      "url": "https://getproofsnap.com/terms.html"
    },
    "description": "ProofSnap API načte webovou stránku v serverovém prohlížeči Chromium a vrátí balíček důkazů (ZIP).\n\nKaždý balíček záznamu obsahuje snímek obrazovky, HTML stránky, extrahovaný text stránky, metadata.json, forensic_log.json, chain_of_custody.json, evidence.pdf a manifest.json, který uvádí SHA-256 každého souboru. manifest.json je podepsán klíčem RSA-4096 vygenerovaným pro daný záznam (veřejný klíč je přiložen jako publickey.pem, soukromý klíč se zahodí) a SHA-256 souboru manifest.json se odesílá do kalendářů OpenTimestamps k ukotvení v Bitcoinu (manifest.json.ots). Pokud požadavek na kalendář selže, balíček se dodá bez důkazu a manifest.json ho neuvádí, takže offline skripty i ověřovač ho hlásí jako nepřítomný, nikoli jako chybějící. S `include_eidas` u ostrého klíče získá stejný hash také kvalifikované elektronické časové razítko eIDAS (RFC 3161, manifest.json.tsr). Snímky obrazovky JPEG se podle možností podepisují pomocí C2PA Content Credentials: když podpis selže, záznam se dokončí bez nich. Složka verification/ obsahuje skripty, které balíček ověří offline. Každý manifest.json uvádí `ots_listed_only_when_present: true` (manifest.json.ots je uveden, jen když je v balíčku) a `eidas_marker_version: 1`. Hodnotu `eidas_requested: true` zaznamená jen tehdy, když se balíček dodává s kvalifikovaným časovým razítkem. Pokud token nelze získat, manifest se zapečetí znovu bez něj. Balíček, který uvádí `eidas_requested: true`, ale nemá manifest.json.tsr, tedy o svůj token přišel a offline skripty hlásí FAIL. chain_of_custody.json zaznamenává `bitcoin_ots_included` a v `page_modifications.items[]` uvádí každou změnu stránky provedenou před zachycením. manifest.json obsahuje sealed_at (kdy byl sestaven, po hashi každého souboru) a odchylky hodin serveru, který záznam pořídil, změřené přes SNTP; chain_of_custody.json uvádí kroky záznamu v pořadí, v jakém proběhly, každý s časem dokončení, a končí krokem custody_record_written (hashování, podpis a časová razítka následují po něm a dokládají je manifest.json a důkazy).\n\nmetadata.json zaznamenává:\n\n- `browser_identity`: skutečně odeslaný user agent a Client Hints.\n- `dns`: nezávislou kontrolu DNS adresy, ke které se prohlížeč připojil, s odpověďmi dns.google a cloudflare-dns.com a výsledkem: confirmed, not_confirmed, resolvers_unavailable, connected_ip_unknown, skipped_ip_literal (URL uvádí IP adresu, takže není co vyhledat) nebo skipped_internal_host (interní název hostitele, který se nikdy neodesílá veřejným resolverům).\n- `url_at_load` a `url_at_screenshot`: adresu hned po načtení stránky a v okamžiku pořízení jejího snímku (stránka může svou adresu změnit sama, nejčastěji část za #).\n- `redirect_chain`: přesměrování hlavního dokumentu od nejstaršího, každé s HTTP stavem. Požadovaná a konečná adresa jsou uvedeny celé; u každého mezikroku jsou hodnoty dotazu nahrazeny [redacted] (`query_values_redacted`).\n- `tls.source`: odkud pochází každé pole TLS, buď `browser_connection`, nebo `browser_connection_and_separate_handshake`, u druhé varianty s `at`, `ip` a `port` samostatného handshaku, který po načtení stránky stáhl certificate_chain.pem.\n\nKdyž požadovaný krok nebyl proveden (časové razítko eIDAS, podpis C2PA, požadavek na archiv, WHOIS, druhé čtení hodin, WARC zkrácený časovým limitem nebo čekání či rozbalení obsahu vynechané kvůli časovému limitu), evidence.pdf ho uvede se stručným důvodem a certifikát původu ho zmíní na jednom řádku.\n\nZáznamy jsou asynchronní. POST /captures vrátí 202 s capture_id; dotazujte se přes GET /captures/{capture_id} nebo předejte `options.webhook_url`. Dokončený záznam vrátí předem podepsaný package_url platný až 24 hodin (viz package_url_expires_at); nový odkaz získáte opětovným načtením záznamu.\n\nCesty níže jsou relativní k URL serveru, která již obsahuje stage /v1. Hodnoty `poll_path` vracené API obsahují /v1.",
    "contact": {
      "email": "support@getproofsnap.com"
    }
  },
  "servers": [
    {
      "url": "https://api.getproofsnap.com/v1",
      "description": "ProofSnap API (EU)"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Záznamy",
      "description": "Vytváření, výpis, čtení, mazání a ověřování záznamů.\n\n**Limity počtu požadavků.** `POST /captures`, `POST /captures/batch`, `POST /compare`, `POST /captures/{capture_id}/redact` a `POST /certify-hash` mají limit počtu požadavků na účet v pevných 60sekundových oknech: všechny klíče API účtu i jeho relace v dashboardu sdílejí jedno okno (přidáním klíčů se limit nezvýší). Dávka nebo certifikace více hashů spotřebuje jednu jednotku za každou URL nebo hash. Výchozí limity na okno podle tarifu:\n\n| Tarif | Požadavků za 60 s |\n| --- | --- |\n| sandbox | 10 |\n| developer | 60 |\n| startup | 120 |\n| growth | 300 |\n| custom | 1200 |\n| legal_solo | 60 |\n| legal_seats | 120 |\n| website_archive | 60 |\n| archive_only | 30 |\n| jakýkoli jiný tarif | 30 |\n\nZe stejného okna čerpají také tyto požadavky, není-li uvedeno jinak, jednu jednotku za požadavek: `POST /captures/{capture_id}/verify`, `PATCH /captures/{capture_id}` s akcí legal_hold, `GET /captures/hosts` (jen když se seznam přepočítává, ne když se vrací výsledek z mezipaměti), `POST /legal-holds` (jedna jednotka za 10 záznamů), `POST /captures/export-jobs` a `POST /imports`, `POST /imports/{import_id}/complete` a `GET /imports/{import_id}?upload=true`.\n\nPři překročení limitu vrací API 429 RATE_LIMITED s hlavičkami `Retry-After`, `X-RateLimit-Limit`, `X-RateLimit-Remaining` a `X-RateLimit-Reset` a polem `error.details.retry_after_seconds`. Požadavek, který potřebuje více jednotek, než jedno okno dovoluje (certifikace více hashů nad limit okna), nemůže nikdy uspět a vrací 400 RATE_LIMIT_COST_TOO_HIGH s `error.details` `{ max_per_window, window_seconds, requested }`. Rozdělte jej na menší požadavky. Odmítnutý požadavek žádné jednotky nespotřebuje a hlavičky uvádějí skutečný zbývající rozpočet.\n\n**Měsíční limity.** Záznamy, porovnání, začernění a certifikace přes ostré klíče se započítávají do měsíčního maxima účtu (kalendářní měsíc UTC). Přijatá odpověď nese hlavičky `X-Quota-*`. Po dosažení maxima se vrací 402 QUOTA_EXCEEDED s `error.details` `{ reason, used, limit, max_limit, cap, org_member }`, kde `cap` je `plan_max`, `customer`, `member_owner` nebo `org`. Dokud je ostré předplatné po splatnosti nebo nezaplacené, vracejí zpoplatněné požadavky 402 PAYMENT_REQUIRED; u takového účtu se záznamy (jednotlivé i dávkové) odmítají s touto chybou bez ohledu na prostředí klíče, tedy i u testovacích klíčů.\n\n**Běžící záznamy a testovací režim.** Každý účet může současně provádět jen omezený počet záznamů (developer 10, startup 25, growth 100, legal_solo a legal_seats 25, custom 200, website_archive 25, sandbox 5). Nad tento limit vrací API 429 CONCURRENT_CAPTURE_LIMIT; dávka spustí URL, které se vejdou, a ostatní uvede v `not_admitted` (každou s `code` CONCURRENT_CAPTURE_LIMIT a `in_flight_limit`), takže je pošlete později znovu. Práce v testovacím režimu (testovací klíč nebo relace bez propojené fakturace) je omezena na 200 jednotek na účet a den UTC (429 TEST_MODE_DAILY_LIMIT; hlavičky `X-Test-Daily-*`) a testovací záznam se nikdy neposílá do Internet Archive (`external_archive.skip_reason` \"test_mode\")."
    },
    {
      "name": "Porovnání a začernění",
      "description": "Odvození nového zapečetěného balíčku z existujících záznamů: porovnání dvou záznamů, nebo začerněná kopie jednoho z nich."
    },
    {
      "name": "Certifikace hashe",
      "description": "Certifikujte hashe SHA-256 souborů, které uchováváte. Odesílají se pouze hashe; samotné soubory ProofSnap nikdy neobdrží."
    },
    {
      "name": "Automatické záznamy",
      "description": "Opakované záznamy (interval nebo cron) a sledování změn (on_change). Každý běh, který pořídí záznam, je běžný záznam: měří se a započítává do měsíčních limitů."
    },
    {
      "name": "Spisy",
      "description": "Pracovní prostory právních spisů s logem řetězce úschovy zřetězeným pomocí hashů. K dispozici na tarifech Legal (legal_solo, legal_seats); ostatní tarify dostanou 403 MATTERS_NOT_ENABLED, se dvěma výjimkami. Vlastník firmy, jejíž předplatné skončilo, může spisy této firmy dál vypisovat, otevírat a exportovat až do data smazání dat firmy (data_delete_after); tento přístup je jen pro čtení a export a GET /matters pak přidá read_only: true. Účet na tarifu Archive only může vypisovat, otevírat a exportovat své spisy. Jen vlastník spisu ho smí přejmenovat, archivovat, spravovat jeho členy, zapečetit, sdílet nebo exportovat. Vlastníkem spisu je ten, kdo ho vytvořil. U firemního spisu se vlastník firmy stane vlastníkem spisu až poté, co jeho tvůrce z firmy odejde. Vlastník firmy, který byl přidán jako člen, má jen práva člena. Členové u těchto operací dostanou 403 FORBIDDEN. Každý zápis do spisu (vytvoření, PATCH, přiřazení záznamů, sdílení a jeho zrušení, zapečetění, export) vyžaduje potvrzenou e-mailovou adresu (403 EMAIL_NOT_VERIFIED, pro relaci dashboardu i pro klíč API účtu, jehož adresa není potvrzená) a u ostrého volajícího (ostrý klíč API nebo relace s propojenou fakturací) se odmítne s 402 PAYMENT_REQUIRED, dokud je předplatné (nebo předplatné firmy) po splatnosti nebo nezaplacené. Archivovaný spis odmítá přejmenování, nové členy, nové záznamy, sdílení a export (409 MATTER_ARCHIVED), dokud není znovu otevřen; volající, který ho znovu otevřít nemůže (vlastník ukončené firmy, účet Archive only), ho přesto smí exportovat."
    },
    {
      "name": "Webhooky",
      "description": "ProofSnap odešle (POST) událost JSON na `webhook_url`, který předáte se záznamem, certifikací, začerněním nebo automatickým záznamem. URL musí používat https, nesmí obsahovat přihlašovací údaje (`user:password@`, 400 INVALID_URL) a nesmí směřovat na privátní, loopback, link-local, carrier-grade NAT, multicastovou, rezervovanou ani cloudovou metadatovou adresu, včetně forem IPv6, které takovou adresu IPv4 obsahují. Kontroluje se to při přijetí požadavku (422 SSRF_BLOCKED) a znovu při každém doručení: název hostitele se přeloží, zkontroluje se každá adresa a doručení se připojí jen k adrese, která kontrolou prošla, takže hostitel, který se později přeloží na blokovanou adresu, se nekontaktuje. Pokud název hostitele nelze přeložit, doručení se neodešle. Na všech cestách se prázdný webhook_url nebo webhook_url jen z bílých znaků považuje za žádný webhook. /compare webhooky neposílá.\n\n**Odběry účtu.** Místo webhook_url u jednotlivých požadavků (nebo navíc k němu) přihlaste endpoint k odběru událostí účtu přes `POST /webhook-subscriptions`: dostane každou odpovídající událost účtu bez ohledu na to, který klíč, automatický záznam nebo relace dashboardu ji způsobily. Každý odběr má vlastní tajný kód (vrací se jednou, při vytvoření), uvádí typy událostí, které chce dostávat, a může filtrovat podle `host` nebo `schedule_id`; ostrý odběr dostává události jen ostrých záznamů a testovací odběr jen testovacích záznamů. Klíč API vypisuje a mění jen odběry svého prostředí; relace dashboardu vidí všechny. Doručení odběru nesou `subscription_id` na nejvyšší úrovni a žádný předem podepsaný odkaz (package_url, package_url_expires_at, upgraded_proof_url a compare.package_url jsou odstraněny; monitor.change_detected nese compare.compare_id): balíček stáhněte přes GET /captures/{capture_id}. Události záznamů nesou na nejvyšší úrovni i `capture_id`. webhook-id doručení odběru je odvozen z odběru, záznamu (nebo automatického záznamu) a události. Platí pravidla doručování a opakování popsaná níže. Kromě toho odpověď 410 odběr okamžitě vypne (disabled_reason gone), doručení, která selhávají 5 dní bez jediného úspěchu (a alespoň jeden celý cyklus opakování neúspěšných pokusů), ho vypnou (failing) a zneplatnění klíče API, který ho vytvořil, ho vypne (key_revoked); PATCH se status \"active\" ho znovu aktivuje. Každá událost se také 30 dní uchovává v `GET /events`.\n\n**Hlavičky**\n\nKaždé doručení je podepsáno podle specifikace [Standard Webhooks](https://www.standardwebhooks.com/), takže ho ověří kterákoli oficiální knihovna Standard Webhooks:\n\n| Hlavička | Hodnota |\n| --- | --- |\n| `Content-Type` | `application/json` |\n| `webhook-id` | `msg_<delivery id>`: stejné pro stejnou událost stejného záznamu, takže duplicitní doručení nese stejné id. Použijte ho k deduplikaci: každé webhook-id zpracujte jen jednou. `GET /webhook-events/{capture_id}` vrací stejné id bez předpony `msg_` jako `delivery_id` |\n| `webhook-timestamp` | Unixový čas v sekundách, kdy bylo doručení odesláno. Je pokrytý podpisem |\n| `webhook-signature` | `v1,<base64>`: HMAC-SHA256 nad `<webhook-id>.<webhook-timestamp>.<raw body>`. Během rotace tajného kódu webhooku obsahuje dvě položky oddělené mezerou, `v1,<new> v1,<previous>`; doručení přijměte, pokud odpovídá kterákoli z nich |\n| `User-Agent` | `ProofSnap-Webhook/2.0` |\n\n**Ověření doručení.** Ověřujte nad přesně přijatými bajty, ještě před parsováním. Odmítněte doručení, jehož webhook-timestamp se od vašich hodin liší o víc než 5 minut (oficiální knihovny to dělají), a deduplikujte podle webhook-id. Podpisový klíč je část tajného kódu za `whsec_`, dekódovaná z base64. `webhook_secret` je `whsec_` následované standardním base64, tedy tvar, který oficiální knihovny očekávají, takže jim ho předejte beze změny.\n\n```js\n// npm install standardwebhooks\nimport { Webhook } from \"standardwebhooks\";\nconst wh = new Webhook(process.env.PROOFSNAP_WEBHOOK_SECRET); // whsec_... (webhook_secret)\n// rawBody: the request body as received (string or Buffer), headers: the request headers\nconst event = wh.verify(rawBody, headers); // throws on a bad signature or a timestamp outside 5 minutes\n```\n\nBez knihovny (Node):\n\n```js\nconst key = Buffer.from(secret.slice(\"whsec_\".length), \"base64\");\nconst signed = `${headers[\"webhook-id\"]}.${headers[\"webhook-timestamp\"]}.${rawBody}`;\nconst expected = crypto.createHmac(\"sha256\", key).update(signed).digest(\"base64\");\nconst ok = headers[\"webhook-signature\"].split(\" \").some((part) => {\n  const [version, sig] = part.split(\",\");\n  return version === \"v1\" && sig && sig.length === expected.length\n    && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));\n});\n// and: Math.abs(Date.now() / 1000 - Number(headers[\"webhook-timestamp\"])) <= 300\n```\n\n**Tajný kód webhooku.** Každý klíč API má vlastní tajný kód (`whsec_...`). Zobrazí se jednou, při vytvoření klíče v dashboardu v sekci Pro vývojáře (pole `webhook_secret` v odpovědi, která klíč vytváří). Později ho už nelze přečíst: výpis klíčů ho nikdy nevrací. Pokud ho ztratíte nebo mohl uniknout, vygenerujte nový v dashboardu v sekci Pro vývojáře (Nový tajný kód webhooku u klíče). I nový tajný kód se zobrazí jen jednou. **Překryv při rotaci:** 24 hodin po rotaci (do `previous_secret_expires_at` v odpovědi na rotaci) je každé doručení podepsáno novým i předchozím tajným kódem (dvě položky `v1,` ve webhook-signature), takže můžete endpoint přepnout na nový tajný kód bez ztráty doručení. Druhá rotace během běžícího překryvu se odmítne s 409 WEBHOOK_SECRET_ROTATION_PENDING a `error.details.previous_secret_expires_at` (kdy můžete rotovat znovu), takže nikdy nejsou aktivní víc než dva tajné kódy současně a tajný kód, na který se příjemci ještě mohou spoléhat, se nikdy nevyřadí předčasně. Pokud tajný kód unikl, klíč zneplatněte a vytvořte nový. Zneplatnění klíče smaže oba. Doručení používají tajné kódy klíče platné v okamžiku odeslání, i u doručení pro práci zahájenou před rotací. Požadavek z přihlášené relace dashboardu nemá klíč API, a tedy ani tajný kód webhooku, takže se `webhook_url` v něm odmítne s 400 `WEBHOOK_REQUIRES_API_KEY` (záznamy, dávky, začernění, certifikace hashů, vytvoření nebo úprava automatického záznamu). Spuštění automatických záznamů používají tajný kód klíče, který automatický záznam vytvořil. Pokud byl klíč zneplatněn nebo jeho tajný kód nelze v okamžiku doručení přečíst, událost se neodešle a pokus se zaznamená s důvodem (přečtěte ho přes `GET /webhook-events/{capture_id}`).\n\n**Doručování.** Každý pokus má časový limit 10 sekund. Přesměrování se nikdy nesledují: odpověď 3xx se počítá jako selhání, stejně jako odpověď mimo 2xx nebo vypršení časového limitu. Tělo odpovědi se nečte. **Opakování:** doručení, u kterého vyprší časový limit, nepodaří se připojit nebo dostane odpověď mimo 2xx (kromě 410 Gone), se odešle znovu přibližně po 5 minutách, 30 minutách, 2 hodinách, 8 hodinách a 24 hodinách (pokusy 2 až 6, celkem asi 35 hodin), pokaždé se stejným `webhook-id` a novým `webhook-timestamp`. Poté se doručování vzdá. Opakované doručení nese stejný obsah BEZ 24hodinového odkazu ke stažení (`package_url`, `package_url_expires_at`): balíček stáhněte přes GET /captures/{capture_id}. Doručení pro záznam, který byl mezitím vymazán, se zahodí. Přechodné selhání čtení podpisového tajného kódu na naší straně se opakuje stejně. 410 Gone, přesměrování, blokovaná adresa ani chybějící či zneplatněný klíč se neopakují. Tělo opakovaného pokusu se může od prvního pokusu lišit (bez odkazu ke stažení): deduplikujte podle webhook-id, ne podle hashe těla. Odpovídejte rychle kódem 2xx. Protokol pokusů zaznamenává obecnou třídu chyby (connection_failed, timeout, blocked_address, redirect_not_followed, http_<status>), nikdy surovou síťovou chybu. certify.completed a redaction.completed se odesílají asynchronně, krátce po vrácení odpovědi. Každý pokus se zaznamenává; protokol přečtete přes `GET /webhook-events/{capture_id}`.\n\n**Události**\n\n`capture.completed`: záznam (jednotlivý, položka dávky nebo spuštění automatického záznamu s intervalem či cron) byl dokončen. Odběry webhooků účtu ho dostávají i pro výchozí a změnové záznamy automatického záznamu on_change (vlastní webhook_url automatického záznamu pro ně dostává monitor.change_detected). `capture` má stejná pole jako dokončený `GET /captures/{capture_id}`, plus `timestamps.eidas`, pokud bylo přidáno kvalifikované časové razítko, `schedule_id` (mimo automatický záznam null), `test_mode` a `completed_at`.\n\n```json\n{ \"event\": \"capture.completed\",\n  \"capture\": { \"capture_id\": \"cap_...\", \"status\": \"completed\", \"url\": \"https://example.com\", \"schedule_id\": null, \"test_mode\": false, \"captured_at\": \"...\", \"completed_at\": \"...\",\n    \"package_url\": \"https://...\", \"package_url_expires_at\": \"...\", \"verification_url\": \"https://...\",\n    \"manifest_hash\": \"sha256:...\", \"timestamps\": { \"bitcoin_ots\": { \"status\": \"pending_confirmation\", \"block_height\": null } },\n    \"c2pa\": { \"included\": true, \"signed_screenshot_sha256\": \"sha256:...\" }, \"file_count\": 21, \"size_bytes\": 1234567, \"metadata\": {} } }\n```\n\n`capture.failed`: záznam se nepodařilo dokončit. `error.message` je krátký veřejný důvod (u neočekávaného selhání \"The capture could not be completed.\"); interní podrobnosti chyby se nikdy neposílají. Patří sem i spuštění, které spadlo nebo vypršelo: asi 30 minut po startu ho kontrolní průchod označí jako failed a tehdy se odešle capture.failed (zpráva \"Capture did not finish (timed out).\"). Stejný průchod odešle certify.failed nebo redaction.failed pro certifikaci hashe nebo začernění, které nedoběhly. Spuštění, které doběhne až poté, co bylo nahlášeno jako failed, se neúčtuje a capture.completed neposílá.\n\n```json\n{ \"event\": \"capture.failed\",\n  \"capture\": { \"capture_id\": \"cap_...\", \"status\": \"failed\", \"url\": \"https://example.com\", \"schedule_id\": null, \"test_mode\": false, \"failed_at\": \"...\",\n    \"error\": { \"code\": \"CAPTURE_FAILED\", \"message\": \"...\" }, \"metadata\": {} } }\n```\n\n`certify.completed`: certifikace hashe byla dokončena. `certificate` má stejná pole jako synchronní odpověď `POST /certify-hash`. Doručuje se asynchronně, krátce po vrácení odpovědi.\n\n`certify.failed`: certifikaci hashe se nepodařilo dokončit.\n\n```json\n{ \"event\": \"certify.failed\",\n  \"certificate\": { \"certify_id\": \"cert_...\", \"status\": \"failed\", \"failed_at\": \"...\",\n    \"error\": { \"code\": \"CERTIFY_FAILED\", \"message\": \"The certification could not be completed. Retry the request.\" } } }\n```\n\n`redaction.completed`: začernění bylo dokončeno. `redaction` má stejná pole jako odpověď `POST /captures/{capture_id}/redact`.\n\n`redaction.failed`: začernění se nepodařilo dokončit. `error.code` je kód, který by vrátil požadavek (například REDACTION_LEAK_DETECTED), s `details`, pokud nějaké jsou; začernění, které kontrolní průchod označil jako failed, nese REDACTION_FAILED.\n\n```json\n{ \"event\": \"redaction.failed\",\n  \"redaction\": { \"redaction_id\": \"red_...\", \"status\": \"failed\", \"redacted_from\": \"cap_...\", \"failed_at\": \"...\",\n    \"error\": { \"code\": \"REDACTION_LEAK_DETECTED\", \"message\": \"...\", \"details\": { \"files\": [\"page.html\"], \"rule_indexes\": [0], \"metadata_fields\": [], \"in_capture_url\": false } } } }\n```\n\n`monitor.change_detected`: automatický záznam `on_change` zjistil změnu textu stránky a pořídil nový záznam.\n\n```json\n{ \"event\": \"monitor.change_detected\", \"schedule_id\": \"sch_...\",\n  \"before_capture_id\": \"cap_...\", \"after_capture_id\": \"cap_...\", \"url\": \"https://example.com\",\n  \"compare\": { \"package_url\": \"https://...\", \"diff_summary\": { } },\n  \"diff_status\": \"ok\", \"verdict\": \"changed\", \"text_verdict\": \"changed\", \"images_verdict\": \"unchanged\", \"metadata_verdict\": \"unchanged\",\n  \"detected_at\": \"...\", \"test_mode\": false }\n```\n\n`verdict`, `text_verdict`, `images_verdict` a `metadata_verdict` (od 2026-10-14) odpovídají výsledkům porovnání podle kategorií v compare.diff_summary (bez porovnání null). Automatický záznam s `alert_on: \"text\"` posílá monitor.change_detected jen tehdy, když je text_verdict changed (nebo když výsledek porovnání neexistuje).\n\n`capture.anchor_confirmed` (jen odběry a GET /events): ukotvení důkazu OpenTimestamps z balíčku v Bitcoinu bylo potvrzeno, obvykle několik hodin po pořízení záznamu.\n\n```json\n{ \"event\": \"capture.anchor_confirmed\", \"capture_id\": \"cap_...\", \"schedule_id\": null, \"url\": \"https://example.com\",\n  \"confirmed_at\": \"...\", \"bitcoin_block_height\": 968549, \"upgraded_proof_available\": true, \"test_mode\": false }\n```\n\n`schedule.paused` (jen odběry a GET /events): ProofSnap pozastavil automatický záznam. `reason` je `no_billing` (bez přístupu k API), `plan_downgrade` (plán povoluje méně automatických záznamů, žádné on_change nebo žádnou novou práci), `failures` (pět neúspěšných spuštění za sebou), `key_revoked` nebo `invalid_cron`. Pozastavení, které provedete sami, událostí není.\n\n```json\n{ \"event\": \"schedule.paused\", \"schedule_id\": \"sch_...\", \"url\": \"https://example.com\", \"reason\": \"failures\",\n  \"paused_at\": \"...\", \"test_mode\": false }\n```\n\n`diff_status` je `ok` (compare obsahuje porovnání), `no_baseline` (není starší záznam k porovnání) nebo `failed` (porovnání selhalo; compare je null)."
    },
    {
      "name": "Veřejné",
      "description": "Operace, které nepotřebují klíč API."
    },
    {
      "name": "Import balíčku",
      "description": "Importujte existující balíčky důkazů ProofSnap (soubory ZIP vytvořené rozšířením ProofSnap: záznamy webu, relace s více kartami, certifikace jednotlivých i kombinovaných souborů; nebo tímto API: záznamy, certifikace, porovnání, začernění) do svého účtu, aby se s nimi zacházelo stejně jako s vašimi záznamy z API: uchovávají se 10 let a lze u nich použít právní blokaci, spisy a exporty.\n\nJen tarify Legal (legal_solo, legal_seats), s ostrým klíčem API nebo relací dashboardu s propojenou fakturací (testovací klíč, relace bez fakturace a sandbox dostanou 403 IMPORT_NOT_ALLOWED). Nepotvrzená e-mailová adresa dostane 403 EMAIL_NOT_VERIFIED, předplatné po splatnosti 402 PAYMENT_REQUIRED. Import není záznam: nezapočítává se do měsíčních limitů a nemá poplatek za import; účtuje se pouze jako uložená data.\n\n**Postup.** 1. `POST /imports` s názvem souboru a jeho přesnou velikostí v bajtech (nejvýše 2 GiB): odpověď obsahuje jednu předem podepsanou URL pro každou část o velikosti 32 MiB (poslední část je menší), platnou 1 hodinu. 2. Bajty každé části odešlete metodou PUT na její URL a u každé si uschovejte hlavičku odpovědi `ETag`. 3. `POST /imports/{import_id}/complete` se všemi čísly částí a jejich ETagy. 4. Dotazujte se na `GET /imports/{import_id}`, dokud stav není konečný.\n\n**Stavy.** `uploading` (čeká se na nahrání částí a volání complete; nahrávání nedokončené do 24 hodin přejde do stavu `expired`), `verifying` (balíček se kontroluje), `accepted` (ověření prošlo: `capture_id` je nový záznam se stejným id jako import), `rejected` (ověření neprošlo: `reasons` uvádí kódy; kromě záznamu o importu se nic neuchovává), `duplicate` (Váš účet už obsahuje záznam se stejným manifestem: `duplicate_of`), `expired`.\n\n**Ověření.** Přísné: podpis RSA nad manifest.json, každý uvedený soubor přítomen s uvedeným SHA-256 (a SHA-512 a velikostí, pokud jsou uvedeny), žádné soubory, které manifest neuvádí (kromě souborů, které přidává operační systém, například .DS_Store, a důkazů odvozených z manifestu), alespoň jeden hashovaný soubor, konzistentní evidence id, přepočítaný hashový řetězec forenzního logu, důkaz OpenTimestamps vůči manifestu (offline) a kvalifikované elektronické časové razítko eIDAS vůči pevně nastavenému kořenovému certifikátu Disig s validačními daty obsaženými v balíčku. Struktura ZIP se kontroluje dříve, než se cokoli čte (žádné šifrování, žádný ZIP64, žádné odkazy, bezpečné názvy, žádné duplicitní názvy, velikosti a CRC-32 každé položky). Testovací balíček API (s vodoznakem) se odmítne. Balíčky API zapečetěné dříve, než se začal hashovat evidence.pdf, se přijmou s tímto souborem uvedeným ve `verification.checks.files.unhashed`.\n\n**Úrovně** (`summary`): `integrity` (verified nebo failed), `time_anchor` (eidas_qualified, eidas_qualified_revocation_unknown, ots_bitcoin_attested_unconfirmed, ots_pending, none) a `provenance`: u balíčků API `issued_by_proofsnap` (manifest je v registru balíčků vydaných API) nebo `unverified`; u balíčků rozšíření `registered_by_extension_account` (přihlášený uživatel rozšíření tento manifest zaregistroval při jeho vytvoření) nebo `not_registered`; `unknown`, pokud vyhledání nebylo možné provést. Kvůli úrovni provenance import nikdy neselže.\n\n**Záznam.** Přijatý import je záznam se `source` \"import\": lze ho stáhnout (nahraný ZIP bajt po bajtu) a ověřit (POST /captures/{capture_id}/verify znovu spustí stejné kontroly), lze na něj nastavit právní blokaci, přesunout ho do koše a vymazat, objevuje se ve spisech (při importu s `matter_id` zapíše log řetězce úschovy spisu `package.imported`) a v exportech a uchovává se 10 let od importu. Jeho `captured_at` je čas, který uvádí samotný balíček (`import.captured_at_basis` \"package_claim\"), nikdy čas zjištěný ProofSnapem; `created_at` je okamžik vytvoření nahrávání. Porovnání a začernění importovaného balíčku se odmítají (422 IMPORT_NOT_SUPPORTED).\n\n**Limity.** Nejvýše 3 probíhající importy (uploading nebo verifying) na účet (409 IMPORT_LIMIT), 50 vytvořených importů na účet a den UTC (429 RATE_LIMITED, `details.action` \"import_create\"; počítá se každý požadavek na vytvoření, i ten, který je později odmítnut) a minutový limit počtu požadavků tarifu pro create a complete. Objem importu: nejvýše 5 GiB za den UTC a 20 GiB za měsíc UTC ohlášených velikostí balíčků na účet, počítáno při create (a u staršího nahrávání při complete); při překročení 429 IMPORT_DAILY_BYTES_LIMIT nebo IMPORT_MONTHLY_BYTES_LIMIT s `Retry-After`; zrušené nahrávání se nezapočítává."
    }
  ],
  "paths": {
    "/captures": {
      "post": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "createCapture",
        "summary": "Pořídit záznam URL",
        "description": "Přijme záznam a ihned vrátí 202; záznam se pořizuje na pozadí. Dotazujte se na `GET /captures/{capture_id}` nebo předejte `options.webhook_url`. Název hostitele v URL se před přijetím záznamu přeloží a zkontroluje.\n\nLimit počtu požadavků platí pro každý účet zvlášť v 60sekundových oknech (všechny klíče API účtu a jeho relace v dashboardu sdílejí jedno okno). Jakmile omezovač proběhne, obsahují odpovědi této cesty hlavičky `RateLimit-Policy` a `RateLimit` (podle IETF draft-ietf-httpapi-ratelimit-headers) a navíc starší `X-RateLimit-Limit`, `X-RateLimit-Remaining` a `X-RateLimit-Reset`. Odpověď 429 přidává `Retry-After`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CaptureRequest"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Přijato. Idempotentní opakování dřívějšího požadavku se stejným Idempotency-Key vrátí také 202 s `Idempotent-Replay: true` a původním tělem.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/IdempotentReplay"
              },
              "X-Quota-Limit": {
                "$ref": "#/components/headers/QuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-Quota-Used": {
                "$ref": "#/components/headers/QuotaUsed"
              },
              "X-Quota-Cap": {
                "$ref": "#/components/headers/QuotaCap"
              },
              "X-Quota-Org-Limit": {
                "$ref": "#/components/headers/QuotaOrgLimit"
              },
              "X-Quota-Org-Used": {
                "$ref": "#/components/headers/QuotaOrgUsed"
              },
              "X-Sandbox-Limit": {
                "$ref": "#/components/headers/SandboxLimit"
              },
              "X-Sandbox-Remaining": {
                "$ref": "#/components/headers/SandboxRemaining"
              },
              "X-Sandbox-Used": {
                "$ref": "#/components/headers/SandboxUsed"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaptureAccepted"
                },
                "example": {
                  "capture_id": "cap_a1B2c3D4e5F6g7H8",
                  "status": "processing",
                  "url": "https://example.com",
                  "poll_path": "/v1/captures/cap_a1B2c3D4e5F6g7H8",
                  "message": "Capture accepted. Poll GET /v1/captures/{capture_id} (or use webhook_url) for completion.",
                  "metadata": {}
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST, MISSING_FIELD, INVALID_URL, INVALID_TIMESTAMP_TYPE, INVALID_VIEWPORT, METADATA_TOO_LARGE nebo INVALID_EVIDENCE_PACK_OPTIONS. WEBHOOK_REQUIRES_API_KEY: webhook_url odeslané z relace dashboardu (webhooky vyžadují klíč API).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "QUOTA_EXCEEDED (měsíční maximum nebo příděl sandboxu; nese hlavičky X-Quota-* nebo X-Sandbox-*) nebo PAYMENT_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "403": {
            "description": "EIDAS_REQUIRES_LIVE_KEY: include_eidas s testovacím klíčem (klíč ps_live_ účtu bez propojeného fakturačního účtu běží jako testovací klíč). EMAIL_NOT_VERIFIED: relace v dashboardu, jejíž e-mailová adresa není potvrzena. PLAN_ARCHIVE_ONLY: tarif jen uchovává archiv a nevytváří žádnou novou práci. PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard). PLAN_API_READ_ONLY s details.reason \"session_outside_dashboard\": relace v dashboardu účtu Website Archive, jejíž požadavek nemá hlavičku Origin nebo ji má s adresou, která není adresou dashboardu ProofSnap (novou práci na tomto tarifu lze vytvářet jen v dashboardu; měkká brána, nikoli bezpečnostní hranice).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "409": {
            "description": "IDEMPOTENCY_IN_PROGRESS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "422": {
            "description": "SSRF_BLOCKED, TARGET_UNREACHABLE nebo IDEMPOTENCY_KEY_REUSED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED: příliš mnoho požadavků v aktuálním 60sekundovém okně. `error.details.retry_after_seconds` opakuje Retry-After. RateLimit hlásí r=0 a počet sekund do resetu okna. RATE_LIMITED také pro relaci dashboardu Website Archive: její denní strop 100 jednotek za den v UTC, sdílený jednotlivými i dávkovými záznamy (jedna jednotka za URL), porovnáním, začerněním a certify-hash (jedna jednotka za požadavek); požadavek, který se nevejde, se odmítne celý (details.daily_limit, details.remaining, details.action \"wa_session_captures\"; Retry-After a details.retry_after_seconds udávají počet sekund do dalšího dne v UTC a minutové hlavičky RateLimit a X-RateLimit-* se vynechají). Krátké odmítnutí jen s details.retry_after_seconds a Retry-After: 1 znamená souběžnou aktualizaci počítadla: opakujte požadavek. Odmítnutí, které nezavinil volající, jednotky vrací; práce přijatá s 202, která později selže, svou jednotku ponechává. Jde o měkkou bránu, ne o bezpečnostní hranici. Jednotlivý záznam, jehož Idempotency-Key se obslouží z úložiště (opakování, 409 nebo 422), se obslouží před denním stropem a nestojí žádnou jednotku.\n\nCONCURRENT_CAPTURE_LIMIT: současně běží příliš mnoho záznamů účtu (developer 10, startup 25, growth 100, legal_solo a legal_seats 25, custom 200, website_archive 25, sandbox 5); `details.limit`, `details.in_flight`, `details.requested` a Retry-After udávají, kdy to zkusit znovu.\n\nTEST_MODE_DAILY_LIMIT: práce v testovacím režimu (testovací klíč nebo relace bez propojené fakturace) je omezena na 200 jednotek na účet a den v UTC; `details.used`, `details.limit`, `details.reset_at`, hlavičky `X-Test-Daily-*` a Retry-After.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMITED",
                    "message": "Too many requests. See Retry-After header.",
                    "details": {
                      "retry_after_seconds": 42
                    }
                  },
                  "request_id": "..."
                }
              }
            }
          },
          "500": {
            "description": "CAPTURE_FAILED (záznam se nepodařilo spustit; details.capture_id) nebo INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/EidasOrAuthUnavailable"
          }
        }
      },
      "get": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "listCaptures",
        "summary": "Výpis vašich záznamů",
        "description": "Řádky, které jste vytvořili, od nejnovějších, ve všech stavech (včetně smazaných, tedy koše; filtrujte pomocí status). Každý řádek nese source, redacted_from, label a compared, takže jeho typ lze zobrazit bez dalšího načítání. Záznam pořízený pro firmu se vypíše jen tehdy, když s ním stále smíte pracovat (máte místo v dané firmě nebo ji vlastníte); stránka proto může obsahovat méně řádků, než je limit, a next_cursor pokračuje za posledním načteným řádkem. Zahrnuty jsou certifikáty, porovnání a začernění.\n\nVyhledání (jen ve vlastním seznamu): url, host nebo schedule_id v kombinaci s from / to a status najdou záznam stránky z daného dne. Chybný filtr, dva z parametrů url / host / schedule_id nebo from, který není dřívější než to, vrací 400 MALFORMED_REQUEST.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Velikost stránky, 1 až 200 (výchozí 50). Hodnota mimo rozsah vrátí 400 MALFORMED_REQUEST.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 200,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "next_cursor z předchozí stránky (tvar created_at|capture_id, nebo completed_at|capture_id při order=completed_at). Předejte ho beze změny.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Jen řádky v tomto stavu: processing, completed, failed nebo deleted (koš). Jiná hodnota vrátí 400 MALFORMED_REQUEST.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "url",
            "in": "query",
            "required": false,
            "description": "Jen záznamy přesně této URL, jak byla zachycena (http nebo https). Nejvýše jeden z parametrů url, host a schedule_id.",
            "schema": {
              "type": "string",
              "maxLength": 2048
            }
          },
          {
            "name": "host",
            "in": "query",
            "required": false,
            "description": "Jen záznamy, jejichž URL je na tomto hostiteli (bez ohledu na velikost písmen, např. www.example.com; subdomény jsou samostatní hostitelé). Nejvýše jeden z parametrů url, host a schedule_id. Řádky vytvořené před 2026-10-05 mají host vyplněný až po proběhnutí zpětného doplnění dat.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "schedule_id",
            "in": "query",
            "required": false,
            "description": "Jen záznamy pořízené tímto automatickým záznamem. Nejvýše jeden z parametrů url, host a schedule_id.",
            "schema": {
              "type": "string",
              "pattern": "^sch_[A-Za-z0-9]{8,32}$"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Vytvořeno v tomto okamžiku nebo později: datum (YYYY-MM-DD, půlnoc UTC) nebo časový údaj ISO 8601.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Vytvořeno před tímto okamžikem (bez něj): datum (YYYY-MM-DD, půlnoc UTC) nebo časový údaj ISO 8601. Musí být pozdější než from. Se schedule_id nebo url je nejnovější řádek před daným okamžikem tou verzí, která tehdy platila.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "description": "created_at (výchozí: nejnovější vytvořené jako první) nebo completed_at (nejnověji dokončené jako první; jen se status=completed, jinak 400 MALFORMED_REQUEST). Při completed_at omezují from a to hodnotu completed_at a next_cursor má tvar completed_at|capture_id. Funguje s url, host i schedule_id.",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "completed_at"
              ],
              "default": "created_at"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stránka záznamů.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "captures": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "capture_id": {
                            "type": "string"
                          },
                          "url": {
                            "type": "string",
                            "nullable": true
                          },
                          "status": {
                            "type": "string",
                            "nullable": true
                          },
                          "created_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "completed_at": {
                            "type": "string",
                            "nullable": true,
                            "description": "Kdy byl záznam dokončen (null během zpracování nebo po selhání)."
                          },
                          "batch_id": {
                            "type": "string",
                            "nullable": true
                          },
                          "schedule_id": {
                            "type": "string",
                            "nullable": true
                          },
                          "test_mode": {
                            "type": "boolean",
                            "nullable": true
                          },
                          "external_archive": {
                            "allOf": [
                              {
                                "$ref": "#/components/schemas/ExternalArchive"
                              }
                            ],
                            "description": "Jen u řádků ve stavu completed. Stejné jako external_archive v GET /captures/{capture_id}."
                          },
                          "label": {
                            "type": "string",
                            "nullable": true,
                            "description": "Štítek řádku (certifikáty: zadaný štítek; začernění: který záznam začerňují)."
                          },
                          "compared": {
                            "type": "array",
                            "nullable": true,
                            "items": {
                              "type": "string"
                            },
                            "description": "Jen u porovnání: ID obou zdrojových záznamů."
                          },
                          "source": {
                            "type": "string",
                            "nullable": true,
                            "description": "Jak řádek vznikl: api (záznam webu), schedule, certify-hash (certifikát), compare (porovnání) nebo redact (začernění); null u řádků starších než toto pole."
                          },
                          "redacted_from": {
                            "type": "string",
                            "nullable": true,
                            "description": "Jen začernění: záznam, ze kterého začernění vzniklo."
                          },
                          "captured_at": {
                            "type": "string",
                            "nullable": true,
                            "format": "date-time",
                            "description": "Kdy byla stránka zachycena (dokončené řádky). U začernění čas pořízení jeho zdrojového záznamu (redacted_at udává, kdy bylo začernění provedeno)."
                          },
                          "redacted_at": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Jen začernění: kdy začernění vzniklo. captured_at začernění je čas pořízení jeho zdrojového záznamu."
                          },
                          "compared_at": {
                            "type": "string",
                            "nullable": true,
                            "format": "date-time",
                            "description": "Jen u porovnání: kdy bylo porovnání provedeno. Pole captured_at nese stejnou hodnotu (ponecháno kvůli starším klientům); používejte compared_at."
                          },
                          "manifest_hash": {
                            "type": "string",
                            "nullable": true,
                            "description": "sha256:<hex> souboru manifest.json balíčku (řádky ve stavu completed)."
                          },
                          "private_note": {
                            "type": "string",
                            "nullable": true,
                            "description": "Vaše soukromá poznámka k záznamu (viz PrivateNote), nikdy není součástí balíčku důkazů."
                          },
                          "legal_hold": {
                            "type": "boolean",
                            "description": "Záznam je pod právní blokací (dokud je true, nesmaže se; zruší se automaticky, když předplatné skončilo a uplynulo jeho 30 dní). Viz PATCH /captures/{capture_id}."
                          }
                        }
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "description": "null, pokud má tato stránka méně řádků než limit.",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: neplatný cursor, status (jedna z hodnot processing, completed, failed, deleted), limit (1 až 200) nebo vyhledávací filtr (url, host, schedule_id, from, to; nejvýše jeden z url / host / schedule_id; from dříve než to).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/captures/batch": {
      "post": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "createBatch",
        "summary": "Pořídit záznam více URL",
        "description": "Spustí jeden záznam pro každou URL se stejnými volbami. Každý záznam je samostatný: dotazujte se na každé capture_id zvlášť, nebo přijímejte jeden webhook za každý záznam. Za každou URL se spotřebuje jedna jednotka limitu počtu požadavků a jedna jednotka měsíčního limitu. Dávka s více URL, než kolik dovoluje jedno okno limitu počtu požadavků, nemůže nikdy uspět, proto je odmítnuta s 400 RATE_LIMIT_COST_TOO_HIGH místo 429. Rozdělte ji na menší požadavky. Opakování dokončené dávky (stejný Idempotency-Key a tělo) se obslouží ještě před uplatněním limitu počtu požadavků a nespotřebuje žádnou jednotku limitu.\n\nLimit počtu požadavků platí pro účet v 60sekundových oknech (všechny klíče API účtu a jeho relace v dashboardu sdílejí jedno okno). Jakmile limiter proběhne, obsahují odpovědi této routy hlavičky `RateLimit-Policy` a `RateLimit` (podle IETF draft-ietf-httpapi-ratelimit-headers) a navíc starší `X-RateLimit-Limit`, `X-RateLimit-Remaining` a `X-RateLimit-Reset`. Odpověď 429 přidává `Retry-After`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BatchRequest"
              },
              "example": {
                "urls": [
                  "https://example.com/a",
                  "https://example.com/b"
                ],
                "options": {
                  "case_reference": "Smith v. Jones"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Přijato. Idempotentní opakování dokončené dávky se stejným Idempotency-Key a tělem vrátí také 202 s `Idempotent-Replay: true`; obslouží se ještě před uplatněním limitu počtu požadavků, takže z limitu nic nespotřebuje.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/IdempotentReplay"
              },
              "X-Quota-Limit": {
                "$ref": "#/components/headers/QuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-Quota-Used": {
                "$ref": "#/components/headers/QuotaUsed"
              },
              "X-Quota-Cap": {
                "$ref": "#/components/headers/QuotaCap"
              },
              "X-Quota-Org-Limit": {
                "$ref": "#/components/headers/QuotaOrgLimit"
              },
              "X-Quota-Org-Used": {
                "$ref": "#/components/headers/QuotaOrgUsed"
              },
              "X-Sandbox-Limit": {
                "$ref": "#/components/headers/SandboxLimit"
              },
              "X-Sandbox-Remaining": {
                "$ref": "#/components/headers/SandboxRemaining"
              },
              "X-Sandbox-Used": {
                "$ref": "#/components/headers/SandboxUsed"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BatchResult"
                }
              }
            }
          },
          "400": {
            "description": "INVALID_BATCH (details: reason a received, nebo index, url a vnořený objekt reason pro neplatnou URL), MALFORMED_REQUEST nebo chyba voleb. WEBHOOK_REQUIRES_API_KEY: webhook_url odeslané z relace dashboardu (webhooky vyžadují klíč API). RATE_LIMIT_COST_TOO_HIGH: více URL, než povoluje jedno okno limitu počtu požadavků; details { reason, max_per_window, window_seconds, requested }.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "QUOTA_EXCEEDED nebo PAYMENT_REQUIRED. Dávka se odmítne s QUOTA_EXCEEDED také tehdy, když v danou chvíli nelze načíst měsíční využití; opakujte požadavek.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "403": {
            "description": "EIDAS_REQUIRES_LIVE_KEY: include_eidas s testovacím klíčem. EMAIL_NOT_VERIFIED: relace v dashboardu, jejíž e-mailová adresa není potvrzena. PLAN_ARCHIVE_ONLY: tarif jen uchovává archiv a nevytváří žádnou novou práci. PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard). PLAN_API_READ_ONLY s details.reason \"session_outside_dashboard\": relace v dashboardu účtu Website Archive, jejíž požadavek nemá hlavičku Origin nebo ji má s adresou, která není adresou dashboardu ProofSnap (novou práci na tomto tarifu lze vytvářet jen v dashboardu; měkká brána, nikoli bezpečnostní hranice).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "409": {
            "description": "IDEMPOTENCY_IN_PROGRESS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "422": {
            "description": "IDEMPOTENCY_KEY_REUSED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED: příliš mnoho požadavků v aktuálním 60sekundovém okně. `error.details.retry_after_seconds` opakuje Retry-After. RateLimit hlásí r=0 a počet sekund do resetu okna. RATE_LIMITED také pro relaci dashboardu Website Archive: její denní strop 100 jednotek za den v UTC, sdílený jednotlivými i dávkovými záznamy (jedna jednotka za URL), porovnáním, začerněním a certify-hash (jedna jednotka za požadavek); požadavek, který se nevejde, se odmítne celý (details.daily_limit, details.remaining, details.action \"wa_session_captures\"; Retry-After a details.retry_after_seconds udávají počet sekund do dalšího dne v UTC a minutové hlavičky RateLimit a X-RateLimit-* se vynechají). Krátké odmítnutí jen s details.retry_after_seconds a Retry-After: 1 znamená souběžnou aktualizaci počítadla: opakujte požadavek. Odmítnutí, které nezavinil volající, jednotky vrací; práce přijatá s 202, která později selže, svou jednotku ponechává. Jde o měkkou bránu, ne o bezpečnostní hranici.\n\nCONCURRENT_CAPTURE_LIMIT: žádná URL dávky se nemohla spustit, protože účet už má spuštěno tolik záznamů, kolik smí (developer 10, startup 25, growth 100, legal_solo a legal_seats 25, custom 200, website_archive 25, sandbox 5); `details.limit`, `details.in_flight`, `details.requested` a Retry-After. Když se vejdou jen některé, dávka se přijme s 202 a zbytek uvede v `not_admitted`.\n\nTEST_MODE_DAILY_LIMIT: práce v testovacím režimu (testovací klíč nebo relace bez propojené fakturace) je omezena na 200 jednotek na účet a den v UTC, jedna za URL; `details.used`, `details.limit`, `details.reset_at`, hlavičky `X-Test-Daily-*` a Retry-After.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMITED",
                    "message": "Too many requests. See Retry-After header.",
                    "details": {
                      "retry_after_seconds": 42
                    }
                  },
                  "request_id": "..."
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/EidasOrAuthUnavailable"
          }
        }
      }
    },
    "/captures/hosts": {
      "get": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "listCaptureHosts",
        "summary": "Výpis zachycených názvů hostitelů",
        "description": "Všechny názvy hostitelů z vašeho vlastního seznamu záznamů, s počtem záznamů a časem posledního záznamu pro každého hostitele, pro filtr podle domény: hostitele předejte zpět jako GET /captures?host=. count je počet řádků, které vrátí GET /captures?host=<host> bez status (mezi načtenými záznamy): testovací i ostré záznamy, všechny stavy včetně záznamů v koši (status deleted), tak jak je zobrazuje seznam; trvale vymazané záznamy a řádky bez URL stránky (certifikáty) se nezapočítávají. Záznam se započítá, jakmile nese uložený název hostitele (záznamy vytvořené před 2026-10-05 ho nesou po doběhnutí zpětného doplnění). Firemní záznam se započítá jen tehdy, pokud s ním ještě smíte pracovat (máte místo v dané firmě nebo ji vlastníte). host je malými písmeny. Řazeno podle count (od nejvyššího), pak podle host (A až Z). Nejvýše 1000 hostitelů. Načte se nejnovějších 5000 záznamů; truncated je true, pokud je hostitelů více než 1000 nebo existují záznamy starší než těchto 5000, takže hostitel zachycený jen před nimi může chybět. Seznam se pro každý účet počítá nejvýše jednou za 30 sekund a může být až 30 sekund starý (o něco starší, pokud ho právě počítá jiný požadavek téhož účtu). Výpočet stojí jednu jednotku vašeho minutového limitu počtu požadavků; odpověď z této mezipaměti nestojí nic. K dispozici na každém tarifu, pro klíče API i relaci dashboardu.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Názvy hostitelů.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "hosts",
                    "truncated"
                  ],
                  "properties": {
                    "hosts": {
                      "type": "array",
                      "maxItems": 1000,
                      "items": {
                        "type": "object",
                        "required": [
                          "host",
                          "count",
                          "last_captured_at"
                        ],
                        "properties": {
                          "host": {
                            "type": "string",
                            "example": "www.example.com",
                            "description": "Název hostitele malými písmeny, hodnota, kterou přijímá GET /captures?host=."
                          },
                          "count": {
                            "type": "integer",
                            "minimum": 1,
                            "example": 12,
                            "description": "Záznamy tohoto hostitele mezi načtenými záznamy: řádky, které vrací GET /captures?host= bez status, včetně těch v koši."
                          },
                          "last_captured_at": {
                            "type": "string",
                            "format": "date-time",
                            "nullable": true,
                            "example": "2026-10-05T07:48:38Z",
                            "description": "Čas posledního záznamu tohoto hostitele (kdy byla stránka zachycena, jinak kdy byl záznam vyžádán), UTC, s přesností na sekundy."
                          }
                        }
                      }
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "true, pokud seznam nemusí být úplný: více než 1000 hostitelů, nebo více záznamů než nejnovějších 5000, které byly načteny."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: scope není podporován (jen vlastní záznamy).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "description": "RATE_LIMITED: minutový limit počtu požadavků je vyčerpán (výpočet seznamu stojí jednu jednotku), nebo seznam vašeho účtu právě počítá jiný požadavek a žádný dřívější výsledek není uložen; opakujte po Retry-After sekundách.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMITED",
                    "message": "Too many requests. See Retry-After header.",
                    "details": {
                      "retry_after_seconds": 42
                    }
                  },
                  "request_id": "..."
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/captures/{capture_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CaptureId"
        }
      ],
      "get": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "getCapture",
        "summary": "Získání záznamu",
        "description": "Stav a po dokončení nový package_url platný až 24 hodin (viz package_url_expires_at). Funguje pro ID záznamů, certifikátů, porovnání a začernění. Číst ho může účet, který ho vytvořil, členové spisu, do kterého patří, a vlastník firmy, pro kterou byl pořízen (pokud předplatné firmy skončilo, do uzavření jejího okna pro stažení).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "event",
            "in": "query",
            "required": false,
            "description": "Pošlete download, když balíček stahujete: u záznamu ve spisu se tím do logu přístupů spisu zapíše capture.downloaded. Běžné dotazy na stav ho vynechávají.",
            "schema": {
              "type": "string",
              "enum": [
                "download"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Záznam.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CaptureResult"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "FORBIDDEN: záznam vám nepatří.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "CAPTURE_NOT_FOUND: neznámé nebo chybně formátované ID, smazaný záznam, nebo se nepodařilo najít soubor balíčku.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "deleteCapture",
        "summary": "Smazání záznamu",
        "description": "Výchozí chování: přesune záznam do koše. Lze jej obnovit přes PATCH do restorable_until (30 dní); poté se trvale odstraní. S permanent=true se uložený balíček smaže okamžitě a ze záznamu zůstane jen náhrobek; to nelze vrátit. Ani jedno neodstraní balíčky, které jste už stáhli, ani důkaz OpenTimestamps. Záznam v otevřeném nebo archivovaném spisu se nejprve ze spisu odebere (zapíše se do jeho protokolu řetězce úschovy), pokud volající smí daný spis otevřít; volající, který nesmí (jeho autor poté, co byl ze spisu odebrán), dostane 409 MATTER_LINKED, pro koš i pro permanent=true, dokud jej vlastník spisu ze spisu neodebere; záznam v zapečetěném spisu smazat nelze. Záznam, který se stále zpracovává, smazat nelze (409 CAPTURE_PROCESSING); smažte jej, až skončí stavem completed nebo failed. Smazáním záznamu, který nikdy nebyl dokončen, se vrací jeho měsíční započtení.\n\nOchranná lhůta po zrušení právní blokace: 14 dní po zrušení právní blokace (`deletion_blocked_until` v GET) se záznam trvale nesmaže (409 CAPTURE_HOLD_GRACE s `details.until`), ať jde o člověka, o čištění koše, nebo o retenci (mazání účtu a firmy po skončení předplatného na ni nečeká). Přesun do koše je povolen; jeho vyčištění počká na konec lhůty. Trvalé smazání nejprve uvolní právní blokaci S3 Object Lock, která na uložených objektech případně zůstala; pokud ji úložiště odmítne uvolnit, požadavek vrátí 409 CAPTURE_LEGAL_HOLD (\"still locked in storage\", zkuste to později) a nic se nesmaže. Každý přesun do koše, obnovení a trvalé smazání se zapisuje do řetězce událostí záznamů účtu (GET /captures/events). Začernění nebo porovnání, jehož zdrojový záznam je pod právní blokací, vrací `source_under_legal_hold: true`, když se přesune do koše nebo smaže.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "permanent",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "true"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Smazáno. Koš: { capture_id, status: \"deleted\", restorable: true, restorable_until }. Trvale: { capture_id, status: \"deleted\", permanent: true }. Již v koši: { capture_id, status }.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "capture_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "restorable": {
                      "type": "boolean"
                    },
                    "restorable_until": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "permanent": {
                      "type": "boolean"
                    },
                    "source_under_legal_hold": {
                      "type": "boolean",
                      "description": "Uvádí se jen (true), pokud jde o začernění nebo porovnání vytvořené ze záznamu s právní blokací."
                    },
                    "deletion_blocked_until": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Koš během ochranné lhůty po zrušení blokace: vysypání koše počká do tohoto času."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "FORBIDDEN: záznam vám nepatří. FORBIDDEN také tehdy, když záznam patří do spisu, který není zapečetěný, a volající (vlastník firmy, který pracuje se záznamem některého místa, nikoli jeho autor) tento spis nemůže otevřít. PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "CAPTURE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "MATTER_SEALED: záznam je přílohou zapečetěného spisu. MATTER_LINKED: záznam je přílohou spisu, jehož členem volající už není; vlastník spisu ho musí nejprve odebrat. CAPTURE_PROCESSING: záznam se stále zpracovává (error.details.status). CAPTURE_LEGAL_HOLD: na záznamu je právní blokace a nikdo ho nemůže smazat (přesunout do koše ani trvale vymazat). CAPTURE_HOLD_GRACE: trvalé smazání během ochranné lhůty po zrušení právní blokace záznamu (LEGAL_HOLD_RELEASE_GRACE_DAYS, 14 dní); error.details.until uvádí, odkdy bude možné. Přesun do koše je během ochranné lhůty povolen.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "INTERNAL_ERROR: uložený balíček se nepodařilo vymazat; nic nebylo smazáno.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "patch": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "restoreCapture",
        "summary": "Obnovit smazaný záznam, nastavit jeho soukromou poznámku nebo nastavit či zrušit jeho právní blokaci",
        "description": "Obnoví záznam z koše. Pokud byl při smazání odebrán ze spisu, přidá se zpět, když je tento spis stále otevřený a volající ho stále může otevřít; matter_id a matter_relinked jsou v odpovědi jen v takovém případě (matter_id je null, když se opětovné propojení neprovedlo). Volající, který už daný spis otevřít nemůže, dostane záznam zpět bez něj, do logu řetězce úschovy spisu se nic nezapíše a odpověď spis nezmiňuje. Záznam, který není v koši, se vrátí beze změny.\n\nSoukromá poznámka: tělo s `private_note` (řetězec o nejvýše 200 znacích, nebo null pro smazání) místo toho nastaví soukromou poznámku záznamu a nic dalšího nedělá; nelze ho kombinovat s `action`. Poznámka se ukládá jen v evidenčním záznamu, mimo zapečetěný balíček důkazů, takže její změna nikdy nemění důkazy ani jejich hashe. Nastavit ji smí jen autor záznamu (vlastník firmy a členové spisu dostanou 403), u záznamu v jakémkoli stavu kromě trvale smazaného (404). Odpověď je { capture_id, status, private_note }.\n\nPrávní blokace: tělo `{ \"action\": \"legal_hold\", \"enabled\": true|false, \"reason\"?: string }` nastaví (true) nebo zruší (false) právní blokaci záznamu a nic dalšího nedělá. Záznam pod právní blokací se nesmaže: DELETE (do koše i trvale) vrací všem 409 CAPTURE_LEGAL_HOLD a nesáhne na něj ani vysypání koše, ani mazání po uplynutí doby uchování; GET ukazuje `storage.retention.earliest_deletion_at` jako null. Blokace trvá jen po dobu, kdy má účet plán, který data uchovává (jakýkoli placený plán včetně Archive only; u firemního záznamu: firma je aktivní nebo vedená jako firemní archiv). Po skončení předplatného zůstávají záznamy dostupné 30 dní; pokud se do té doby takový plán nezakoupí, všechny právní blokace účtu (nebo firmy) se k tomuto datu automaticky zruší (aktér system, důvod subscription_ended, zaznamenáno jako každé jiné zrušení, bez ochranné lhůty po zrušení) a záznamy se smažou spolu s ostatními. Chcete-li blokované záznamy zachovat, přejděte před tímto datem na Archive only (nebo kupte firemní archiv), případně je stáhněte. Během těchto 30 dní nelze nastavit novou blokaci (účet nemá placený plán), stávající blokace lze stále zrušit. Blokace se ukládá jen v evidenčním záznamu, mimo zapečetěný balíček důkazů. `reason` je nepovinný prostý text o nejvýše 200 znacích (bez řídicích, neviditelných znaků a znaků pro směr textu; mezery se slučují, prázdná hodnota znamená žádný důvod); ukládá se s blokací a při jejím zrušení se smaže.\n\nKdo: blokaci může nastavit každý, kdo smí se záznamem pracovat (jeho autor, u firemního záznamu jen dokud má místo v dané firmě, a vlastník firmy, a to i u firmy, jejíž předplatné skončilo, dokud trvá doba uchování nebo je vedená jako firemní archiv; archiv jen přes relaci dashboardu). Zrušit ji může: u osobního záznamu jeho autor, u firemního záznamu jen vlastník firmy (držitel místa dostane 403 LEGAL_HOLD_OWNER_ONLY). Nastavení blokace vyžaduje placený plán (každý placený plán včetně Archive only): bezplatný sandbox i účet, jehož předplatné skončilo, dostane 403 LEGAL_HOLD_NOT_AVAILABLE s details.reason \"plan\" (běžící firemní archiv se pro záznamy dané firmy počítá jako placený, přes relaci dashboardu jejího vlastníka), a záznam v testovacím režimu (s vodoznakem, pořízený testovacím klíčem nebo bez propojené fakturace) dostane 403 LEGAL_HOLD_NOT_AVAILABLE s details.reason \"test_capture\". Zrušení blokace funguje na každém plánu, i po skončení předplatného. U Website Archive je klíč API jen pro čtení (403 PLAN_API_READ_ONLY), relace dashboardu to smí. Předplatné po splatnosti nebo nezaplacené to neblokuje. Relace dashboardu nebo klíč, jehož e-mailová adresa není potvrzená, dostane 403 EMAIL_NOT_VERIFIED.\n\nOdmítne se u záznamu v koši (409 CAPTURE_IN_TRASH: nejdřív ho obnovte) nebo u záznamu, který se ještě zpracovává (409 CAPTURE_PROCESSING); trvale smazaný záznam nebo záznam, jehož trvalé smazání probíhá, vrací 404. Každý požadavek na právní blokaci stojí jednu jednotku minutového limitu počtu požadavků účtu (po jeho vyčerpání 429 RATE_LIMITED s Retry-After). Odeslání stavu, který záznam už má, nic nemění a vrací 200 s uloženými poli a `changed: false`. Každá změna se zapíše do auditního logu jako capture.legal_hold (u firemního záznamu v tenantu firmy), zaznamená se v historii přístupů k záznamu (`legal_hold_on` / `legal_hold_off`, zůstává i po pozdějším výmazu záznamu) a když záznam patří do spisu, zapíše se do logu řetězce úschovy spisu jako capture.legal_hold_placed nebo capture.legal_hold_released s ID záznamu jako cílem (důvod jde do logu přístupů spisu, nikdy do hashovaného řetězce; řetězec zapečetěného spisu se nemění). Odpověď je { capture_id, legal_hold, legal_hold_set_at, legal_hold_reason, changed }.\n\nPrávní blokace v2: nastavení nebo zrušení blokace zároveň nastaví nebo zruší právní blokaci S3 Object Lock na každé verzi uloženého balíčku, jeho povýšeném důkazu OpenTimestamps a samostatně uložené duplicitní kopii (`s3_legal_hold` v GET; když úložiště požadavek odmítne nebo nemá konfiguraci Object Lock, blokace v evidenčním záznamu přesto platí a neúspěšný pokus server zopakuje). Zrušení spouští ochrannou lhůtu 14 dní, během níž se záznam trvale nesmaže (neplatí po skončení předplatného: tam ji nahrazuje 30 dní po skončení). Blokace nastavená právní blokací spisu (`legal_hold_source` \"matter:<id>\") se ruší na spisu, dokud tato blokace trvá: zrušení zde vrací 409 LEGAL_HOLD_MATTER (error.details.matter_id pro čtenáře spisu). Každá změna se zaznamená v řetězci událostí záznamů účtu (GET /captures/events).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "description": "restore (výchozí pro tělo bez private_note) nebo legal_hold (s enabled a nepovinným reason).",
                    "enum": [
                      "restore",
                      "legal_hold"
                    ]
                  },
                  "private_note": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/PrivateNote"
                      }
                    ],
                    "description": "Nastaví (řetězec) nebo smaže (null nebo prázdný řetězec) soukromou poznámku. Nelze kombinovat s action."
                  },
                  "enabled": {
                    "type": "boolean",
                    "description": "S action legal_hold (tam povinné): true nastaví právní blokaci, false ji zruší."
                  },
                  "reason": {
                    "type": "string",
                    "nullable": true,
                    "maxLength": 200,
                    "description": "S action legal_hold, nepovinné: proč je záznam blokován, prostý text o délce nejvýše 200 znaků. Ukládá se s blokací mimo balíček důkazů; při rušení se ignoruje (pak jde jen do auditního protokolu)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Obnoveno ({ capture_id, status, restored: true, matter_id?, matter_relinked? }), beze změny ({ capture_id, status }), soukromá poznámka nastavena ({ capture_id, status, private_note }) nebo právní blokace nastavena ({ capture_id, legal_hold, legal_hold_set_at, legal_hold_reason, changed }).",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "capture_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "restored": {
                      "type": "boolean"
                    },
                    "matter_id": {
                      "type": "string",
                      "nullable": true
                    },
                    "matter_relinked": {
                      "type": "boolean"
                    },
                    "private_note": {
                      "type": "string",
                      "nullable": true
                    },
                    "legal_hold": {
                      "type": "boolean",
                      "description": "Akce právní blokace: stav právní blokace záznamu po požadavku."
                    },
                    "legal_hold_set_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Akce právní blokace: kdy byla aktuální právní blokace nastavena (null, pokud žádná není)."
                    },
                    "legal_hold_reason": {
                      "type": "string",
                      "nullable": true,
                      "description": "Akce právní blokace: důvod uložený u aktuální právní blokace, nebo null."
                    },
                    "changed": {
                      "type": "boolean",
                      "description": "Akce právní blokace: false, pokud záznam už měl požadovaný stav (nic se nezměnilo ani nezaznamenalo)."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: neplatný JSON, tělo, které není objekt, action jiná než restore nebo legal_hold, private_note v kombinaci s action, nebo private_note, který není řetězec ani null, je delší než 200 znaků nebo obsahuje řídicí, neviditelné nebo znaky směru textu. Pro legal_hold: chybějící enabled nebo enabled, které není boolean, reason, který není řetězec, je delší než 200 znaků nebo není prostý text, nebo neznámé pole.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "FORBIDDEN: záznam vám nepatří. FORBIDDEN také tehdy, když záznam patří do spisu, který není zapečetěný, a volající (vlastník firmy, který pracuje se záznamem některého místa, nikoli jeho autor) tento spis nemůže otevřít. PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard). Pro private_note: FORBIDDEN pro kohokoli kromě autora záznamu (který s ním přitom stále musí smět pracovat). Pro legal_hold: FORBIDDEN, pokud volající se záznamem nesmí pracovat; LEGAL_HOLD_OWNER_ONLY, pokud právní blokaci firemního záznamu ruší místo (ne vlastník firmy); LEGAL_HOLD_NOT_AVAILABLE při nastavení právní blokace bez placeného tarifu (details.reason plan) nebo u záznamu v testovacím režimu (details.reason test_capture); EMAIL_NOT_VERIFIED u nepotvrzené e-mailové adresy. Výše uvedené pravidlo pro spisy se na právní blokaci nevztahuje.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "CAPTURE_NOT_FOUND, včetně záznamu, který byl trvale smazán.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Pouze právní blokace. CAPTURE_IN_TRASH: záznam je v koši; nejdřív ho obnovte. CAPTURE_PROCESSING: záznam se stále zpracovává (error.details.status). LEGAL_HOLD_MATTER: právní blokaci záznamu nastavila právní blokace jeho spisu, která stále trvá; zrušte ji u spisu. LEGAL_HOLD_SOURCE: právní blokace začernění nebo porovnání, která se řídí záznamem, ze kterého vzniklo (u porovnání kterýmkoli z porovnávaných záznamů), a ten je stále pod právní blokací (nastavenou přímo na něm nebo prostřednictvím jeho spisu): balíček zůstane blokovaný, dokud se tato blokace nezruší (`details.source_capture_id`). Porovnání je blokované, dokud je blokovaný kterýkoli z porovnávaných záznamů, a uvolní se, až když není blokovaný žádný (`legal_hold_source` \"derived:<capture id>\" uvádí ten blokovaný).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Pouze právní blokace. RATE_LIMITED: minutový limit počtu požadavků účtu je vyčerpán. `error.details.retry_after_seconds` opakuje Retry-After.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/captures/{capture_id}/verify": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CaptureId"
        }
      ],
      "post": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "verifyCapture",
        "summary": "Ověření uloženého balíčku",
        "description": "Načte uložený balíček a ověří RSA podpis manifest.json a SHA-256 každého souboru, který uvádí. Balíčky větší než 256 MiB vrací 413 VERIFY_PACKAGE_TOO_LARGE; ty ověřte offline přiloženými skripty. Každý požadavek stojí jednu jednotku minutového limitu počtu požadavků účtu (429 RATE_LIMITED). Když balíček obsahuje manifest.json.tsr, ProofSnap ověří také token časového razítka eIDAS (checks.eidas): podpis tokenu a podepsané atributy, že nese SHA-256 souboru manifest.json, extendedKeyUsage certifikátu TSA, jeho řetězec certifikátů ke stanovené kořenové CA Disig QCA4 k času tokenu (genTime) a stav certifikátu TSA z odpovědi OCSP nebo CRL zaznamenané při vydání v eidas_validation.json (ověřeno podpisem, nestahuje se živě). Tato kontrola nikdy nežádá nové časové razítko. Uvádí také, zda je přítomen manifest.json.ots a zda je hash manifestu v evidenci vydaných balíčků ProofSnap. Výsledek závisí jen na podpisu manifestu a uvedených souborech; token, který kontrolou neprojde, se uvede v checks.eidas a ve warnings (EIDAS_TOKEN_FAILED), do výsledku se nezapočítá. Balíček vydaný s kvalifikovaným časovým razítkem zaznamenává eidas_requested: true ve svém podepsaném manifest.json; když takový balíček už neobsahuje manifest.json.tsr, checks.eidas a checks.eidas_disig se uvedou jako missing s varováním EIDAS_TOKEN_MISSING (přiložené ověřovací skripty u stejného balíčku hlásí FAIL). Povoleno vlastníkovi záznamu, členům jeho spisu a vlastníkovi firmy, pro kterou byl pořízen. Pro nezávislé ověření časových razítek spusťte skripty ze složky verification/ v balíčku.\n\nImportované balíčky (source import): uložený ZIP se znovu ověří kontrolami importu (podpis, každý soubor, řetězec úschovy, forenzní řetězec, časová razítka; původ se u balíčků API znovu dohledá v evidenci API a u balíčků z rozšíření se převezme ze záznamu o importu). Odpověď je { capture_id, source, type: \"import\", package_kind, verifier: \"package-verify\", verdict (match, modified, invalid), rechecked: true, manifest_sha256, zip_sha256, zip_matches_import, kind, summary, levels, checks, reasons, provenance }. Balíček nad 512 MiB nebo kontrola, která neskončí zhruba do 20 sekund, vrací rechecked: false s důvodem (too_large_for_synchronous_check, time_budget, storage_error), verdict: null a stored_verification (zpráva zaznamenaná při importu).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Výsledek ověření.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerifyResult"
                },
                "example": {
                  "verdict": "match",
                  "capture_id": "cap_a1B2c3D4e5F6g7H8",
                  "source": "s3",
                  "checks": {
                    "manifest_signature": {
                      "status": "valid",
                      "algorithm": "RSA-4096"
                    },
                    "declared_files": {
                      "status": "all_match"
                    },
                    "bitcoin_ots": {
                      "status": "present"
                    },
                    "eidas_disig": null,
                    "proofsnap_issuance": {
                      "status": "issued_by_proofsnap",
                      "manifest_sha256": "3f2a...",
                      "issued_at": "2026-09-01T10:00:00.000Z",
                      "type": "capture"
                    },
                    "eidas": null
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "FORBIDDEN.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "CAPTURE_NOT_FOUND: neznámý, smazaný, nebo bez uloženého balíčku.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "VERIFY_PACKAGE_TOO_LARGE: uložený balíček je větší než 256 MiB.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED: minutový limit počtu požadavků účtu je vyčerpán.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "CONFIGURATION_ERROR: uložený balíček se nepodařilo přečíst.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/captures/{capture_id}/redact": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CaptureId"
        }
      ],
      "post": {
        "tags": [
          "Porovnání a začernění"
        ],
        "operationId": "redactCapture",
        "summary": "Vytvoření začerněné kopie",
        "description": "Sestaví z dokončeného záznamu nový balíček s odstraněným vybraným obsahem, znovu ho podepíše (nový klíč RSA-4096) a odešle k ukotvení v OpenTimestamps. Originál se nemění. Synchronní: vrátí 201, jakmile je balíček připravený. Započítá se jako jeden záznam.\n\n- Začernění oblastí (boxes) zakryje černou části snímku obrazovky. Snímek ve formátu JPEG v té podobě, v jaké ho záznam zapisuje (sekvenční, ve stupních šedi nebo YCbCr), se začerní bez dekódování na pixely: komprimované bloky (MCU, o straně 8 až 32 pixelů), kterých se oblast dotkne, se nahradí černými bloky a všechny ostatní bloky zůstanou beze změny, takže se zbytek obrazu znovu nekomprimuje (`screenshot_method` `jpeg_dct_blocks`, až 150 megapixelů). Začerněná plocha je každá oblast zaokrouhlená navenek na celé bloky (`painted_rects`), takže oblast vždy obsahuje. Snímek ve formátu PNG nebo JPEG jiného druhu se dekóduje, přemaluje a znovu zakóduje jako screenshot.jpeg, a v novém souboru se pak začerní bloky 8 x 8, kterých se oblast dotkne (`screenshot_method` `decode_repaint_jpeg`, až 60 megapixelů). Snímek nad svým limitem nebo s nečitelnými obrazovými daty se odmítne s 422 REDACTION_SCREENSHOT_UNREADABLE dříve, než se cokoli naúčtuje. Je-li hlavička čitelná, ale obrazová data ne, chyba se zjistí až po rezervaci měsíční jednotky a ta se uvolní. Začernění textu a metadat funguje i bez oblastí. redaction_manifest.json (`screenshot_boxes`) zaznamenává metodu, `painted_rects`, mřížku bloků a vysvětlující poznámku pro soudní znalce.\n- Začernění textu odstraní shody z page.html a domtextcontent.txt, ze všech volných textových hodnot v metadata.json (titulek stránky a hodnoty meta, záznamy WHOIS / RDAP, subjekt TLS, hodnoty hlaviček odpovědi HTTP) a ze všech volných textových hodnot v forensic_log.json a chain_of_custody.json (case_reference, case_id, case_note, vaše hodnoty metadat, vložený kód a jeho chyby, popisky zavřených překryvných oken, legal_context.note). Identifikátory, hashe, časy a URL v těchto záznamech zůstávají beze změny. Odstraní se i zakódované výskyty: znakové entity HTML (pojmenované, desítkové, šestnáctkové, například M&uuml;ller nebo jan&#64;firma.cz), procentové kódování (mailto:jan%40firma.cz) a escape sekvence JavaScriptu (@, \\x40), včetně kódování vnořených až do dvou úrovní; značka nahradí přímo zakódované znaky. Kontrola zachovaných shod po začernění čte soubory JSON hodnotu po hodnotě a prohledává každý text v zapsané i dekódované podobě, takže selže při shodě v kterékoli z těchto podob. Začernění textu také zakryje černou ta místa snímku obrazovky, kam text_layout.json zdrojového záznamu umisťuje výskyt (`text_rule_rects`): začerní se odhadnuté řádky textového bloku, které shodu obsahují, a celý blok jen tehdy, když je odhad nejistý (počítá se v `screenshot_boxes.from_text_rules.rects_whole_block` v redaction_manifest.json); výskyty, které neumístí, se počítají v `text_occurrences_not_located`. Pravidla rozlišují velikost písmen, pokud není nastaveno `case_insensitive`.\n- Začernění metadat odstraní pole z metadata.json. Dva názvy sahají dál. `ip_dns` (přijímá se také `ip`, `dns`, `resolved_ips`) odstraní IP adresy a odpovědi DNS cílového webu z metadata.json, forensic_log.json a chain_of_custody.json (vlastní adresy stroje, který záznam pořizuje, zůstávají) a jako automatická textová pravidla je odstraní také, pouze celé adresy, z page.html, domtextcontent.txt a snímku obrazovky (zaznamenává se pouze se zdrojem ip_dns, nikdy adresa ani její hash, a nezapočítává se do limitu text_redactions). `cookie_names` (také `cookie`, `cookies`, `http_headers.cookie`) odstraní hlavičky Cookie a Set-Cookie a všechny seznamy názvů cookies v těchto záznamech; počty zůstávají. Hodnoty cookies jsou začerněné v každém záznamu už předem.\n\nOblast zakrývá pouze pixely. Text pod oblastí zůstává v page.html, domtextcontent.txt a metadata.json, pokud nepřidáte i začernění textu, a obrázek pod oblastí může být dál odkazován nebo vložen v page.html (img src nebo srcset, CSS url(), URI data:); začernění textu, které se shoduje s jeho adresou, tento odkaz odstraní. Začerněný balíček přebírá z originálu pouze screenshot.jpeg (nebo screenshot.png, když ho žádná oblast nenahradila), page.html, domtextcontent.txt, metadata.json a forensic_log.json, a k tomu soubory, které zapisuje nově (evidence.pdf, chain_of_custody.json, redaction_manifest.json, soubory pro ověření a soubory manifestu). Všechny ostatní soubory originálu, například images/, image_inventory.json, text_layout.json, page.mhtml, network.har a capture.warc, se vynechají a uvedou v redaction_manifest.json pod dropped_for_leak_protection. Začernění textu se uplatní i na tyto názvy souborů, protože kopie obrázku je pojmenovaná podle jeho URL. chain_of_custody.json si ponechává události originálu, které se jich týkají, označené artifact_removed_in_redaction a bez hashů souborů, které začerněný balíček neobsahuje. Odstraní se i rule_902_certification.pdf originálu, protože uvádí soubory a hashe originálu; odstranění je uvedeno v redaction_manifest.json (removed_as_stale) a v chain_of_custody.json. URL záznamu se nikdy nezačerňuje, protože je součástí podepsaného manifestu: začernění textu, jehož text je také v URL záznamu nebo ve výsledné URL, se uplatní všude jinde, text v této URL zůstane a pravidlo se uvede v `rules_in_capture_url` a v redaction_manifest.json (leakage_check.capture_url). Začernit lze pouze záznamy webových stránek (porovnání, certifikace nebo začernění se odmítne s 422 REDACTION_SOURCE_UNSUPPORTED).\n\nZačernění testovacího záznamu (pořízeného testovacím klíčem, v sandboxu nebo účtem bez propojeného fakturačního účtu) je testovací balíček bez ohledu na to, jakým klíčem se o něj žádá: s vodoznakem, `test_mode: true` v manifest.json, testovací řádek (key_env test), který se neúčtuje a nespotřebuje měsíční jednotku. include_eidas u takového začernění se odmítne s 403 EIDAS_REQUIRES_LIVE_KEY (details.reason).\n\nZpráva o začernění (evidence.pdf) se vykreslí v jazyce `language` (výchozí: jazyk zdrojového záznamu), včetně těla, titulní strany a testovacího pruhu.\n\nNež se cokoli začerní, znovu se spočítá hash každého souboru, který začernění čte nebo přebírá (snímek obrazovky, page.html, domtextcontent.txt, metadata.json, forensic_log.json, chain_of_custody.json, text_layout.json) a který zdrojový manifest uvádí se SHA-256 (redaction_manifest.json derived_from.source_files_rehashed); neshoda nebo chybějící soubor vrátí 422 REDACTION_SOURCE_INTEGRITY_FAILED a nic se nevydá, takže poškozený nebo pozměněný zdroj se nikdy znovu nezapečetí pod novým podpisem. Soubory, které začerněný balíček vynechává, se nečtou. Synchronní začernění, jehož zdroj se četl příliš dlouho, se zastaví dříve, než se cokoli rezervuje, s 500 CAPTURE_TIME_BUDGET_EXCEEDED.\n\nZačernění záznamu pod právní blokací je blokované také (legal_hold_source \"derived:<capture id>\"), stejně jako každé začernění záznamu, na který se blokace nastaví; zrušení blokace záznamu zruší i tyto blokace a dokud záznam zůstává blokovaný, nelze je zrušit samostatně (409 LEGAL_HOLD_SOURCE). captured_at řádku začernění je čas pořízení jeho zdroje; redacted_at je čas vytvoření začernění.\n\nZačernění při pochybnosti selže (fail closed): když kontrola po začernění stále najde začerněný výraz kdekoli v balíčku mimo URL záznamu a výslednou URL, žádný balíček se nevydá a požadavek vrátí 422 REDACTION_LEAK_DETECTED (`error.details` `{ files, rule_indexes, metadata_fields, in_capture_url }`; samotný výraz se nikdy nevrací). redaction_manifest.json zaznamenává `leakage_check.fail_closed: true`.\n\nHodnoty se zkracují na hranici znaku (znak se nikdy nerozdělí): hledané texty na 2000 znaků, důvody na 200, reason_summary na 500, pole správce (custodian) na 200. Důvody, reason_summary a pole správce se tisknou na certifikát začernění a musí být prostý text: řídicí, neviditelný znak nebo znak směru textu se odmítne s 400.\n\nČasový rozpočet a opakování: požadavek se vrátí v rámci 29sekundového limitu API Gateway. Pečetění běží v časovém rozpočtu počítaném od přijetí požadavku; pokud by se kvalifikované časové razítko (include_eidas) do rozpočtu nevešlo, nevyžádá se a balíček se dodá pouze s ukotvením OpenTimestamps (timestamps.eidas stav not_obtained, důvod time_budget, neúčtuje se), a požadavek na OpenTimestamps, který se nevejde, se vynechá (chain_of_custody.json zaznamená ots_skipped s důvodem time_budget). Posílejte Idempotency-Key, aby opakovaný pokus (například po chybě 504 z brány nebo chybě sítě) vrátil totéž začernění, místo aby vytvořil a vyúčtoval druhé. Opakování, zatímco první požadavek ještě běží, vrátí 409 IDEMPOTENCY_IN_PROGRESS s ID začernění v `error.details.capture_id` (s ním se dotazujte na GET /captures/{capture_id}). Pozdější opakování vrátí 201 s původním tělem a `Idempotent-Replay: true`. Začernění, které selže, svůj klíč uvolní, takže opakování se stejným klíčem proběhne znovu.\n\nLimit počtu požadavků platí pro každý účet zvlášť v 60sekundových oknech (všechny klíče API účtu a jeho relace v dashboardu sdílejí jedno okno). Jakmile omezovač proběhne, obsahují odpovědi této cesty hlavičky `RateLimit-Policy` a `RateLimit` (podle IETF draft-ietf-httpapi-ratelimit-headers) a navíc starší `X-RateLimit-Limit`, `X-RateLimit-Remaining` a `X-RateLimit-Reset`. Odpověď 429 přidává `Retry-After`.\n\nImportovaný balíček důkazů (zdroj import, ID s předponou `imp_`) nelze začernit: 422 IMPORT_NOT_SUPPORTED.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "boxes": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "x": {
                          "type": "number",
                          "minimum": 0
                        },
                        "y": {
                          "type": "number",
                          "minimum": 0
                        },
                        "w": {
                          "type": "number",
                          "minimum": 0
                        },
                        "h": {
                          "type": "number",
                          "minimum": 0
                        },
                        "reason": {
                          "type": "string",
                          "maxLength": 200
                        }
                      },
                      "required": [
                        "x",
                        "y",
                        "w",
                        "h"
                      ]
                    },
                    "maxItems": 200,
                    "description": "Obdélníky v pixelech snímku obrazovky zdrojového záznamu (x a y od jeho levého horního rohu, w a h šířka a výška). Když jsou všechny čtyři hodnoty obdélníku mezi 0 a 1, čtou se jako zlomky šířky a výšky snímku. Obdélník, který leží celý mimo snímek, nic nezačerní a uvede se v ignored_boxes; obdélník přesahující okraj se na okraji ořízne a uvede v clipped_boxes. Když všechny obdélníky leží mimo a žádné začernění textu ani metadat nic nezmění, požadavek se odmítne s 400 REDACTION_NO_OPS dřív, než se cokoli zaúčtuje."
                  },
                  "text_redactions": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "match": {
                          "oneOf": [
                            {
                              "type": "string",
                              "description": "Doslovný text.",
                              "minLength": 1
                            },
                            {
                              "type": "object",
                              "properties": {
                                "pattern": {
                                  "type": "string",
                                  "description": "Regulární výraz, 1 až 500 znaků. Vzory s vnořenými kvantifikátory, například (a+)+, se odmítnou s 400.",
                                  "minLength": 1,
                                  "maxLength": 500
                                },
                                "flags": {
                                  "type": "string",
                                  "description": "Libovolné z g, i, m, s, u, každé nejvýše jednou. y (sticky) se odmítne s 400: hledal by shodu jen na jedné pozici a ostatní výskyty by ponechal.",
                                  "pattern": "^[gimsu]*$"
                                }
                              },
                              "required": [
                                "pattern"
                              ]
                            }
                          ]
                        },
                        "case_insensitive": {
                          "type": "boolean",
                          "default": false,
                          "description": "Hledá doslovný řetězec bez ohledu na velikost písmen (u regulárního výrazu použijte příznak i)."
                        },
                        "reason": {
                          "type": "string",
                          "maxLength": 200,
                          "description": "Prostý text, tiskne se na certifikát začernění."
                        }
                      },
                      "required": [
                        "match"
                      ]
                    },
                    "maxItems": 200
                  },
                  "metadata_fields": {
                    "type": "array",
                    "description": "Cesty k polím v metadata.json (segment `*` odpovídá všem prvkům pole), nebo názvy `ip_dns`, `cookie_names` a `authorization` (viz výše).",
                    "items": {
                      "oneOf": [
                        {
                          "type": "string",
                          "description": "Cesta k poli v metadata.json."
                        },
                        {
                          "type": "object",
                          "properties": {
                            "field": {
                              "type": "string"
                            },
                            "reason": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "field"
                          ]
                        }
                      ]
                    },
                    "maxItems": 100
                  },
                  "reason_summary": {
                    "type": "string",
                    "maxLength": 500,
                    "description": "Prostý text, tiskne se na certifikát začernění."
                  },
                  "custodian": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string"
                      },
                      "title": {
                        "type": "string"
                      }
                    },
                    "description": "Tiskne se na zprávu o začernění. name a title se řídí pravidlem pro prostý text (viz PlainText)."
                  },
                  "language": {
                    "type": "string",
                    "description": "Jazyk PDF čitelných pro člověka. Jedna z hodnot: en, de, it, fr, es, pt_BR, cs, el, hi, hu, id, ja, ko, nl, pl, ro, ru, sv, tr, vi, zh_CN, zh_TW, ar, he, da, fi, nb, sk, uk. Velikost písmen, spojovník a region se tolerují (\"DE\", \"fr-FR\" a \"PT-BR\" se přijmou); samotné \"pt\" a \"zh\" se odmítnou. Nepodporovaná hodnota vrátí 400 MALFORMED_REQUEST. Nepovinné: bez něj (nebo když je prázdný) je zpráva v jazyce zdrojového záznamu."
                  },
                  "include_eidas": {
                    "type": "boolean",
                    "description": "Stejně jako v CaptureOptions.include_eidas.",
                    "default": false
                  },
                  "webhook_url": {
                    "type": "string",
                    "description": "https URL, na kterou přichází redaction.completed. Odesílá se hned po odpovědi 201, ne před ní. URL musí být https a nesmí směřovat na privátní, loopback, link-local, carrier-grade NAT ani cloudovou metadatovou adresu (stejná pravidla jako u URL záznamu; jinak 422 SSRF_BLOCKED). Prázdná hodnota nebo hodnota jen z mezer znamená bez webhooku. Vyžaduje klíč API: při odeslání z relace dashboardu je odmítnuta s 400 WEBHOOK_REQUIRES_API_KEY, protože webhooky se podepisují tajným kódem webhooku daného klíče.",
                    "format": "uri"
                  },
                  "rule_commitment_salt": {
                    "type": "string",
                    "description": "Nepovinné. Vlastní 32bajtová sůl pro závazky pravidel (redaction_manifest.json rule_commitments) jako 64 hexadecimálních číslic nebo base64 / base64url; sůl z jednoho opakovaného bajtu se odmítne (400). Pošlete ji, pokud chcete mít sůl k dispozici už před voláním: bez ní ji vytvoří server a vrátí ji jen v odpovědi 201, takže když se odpověď ztratí kvůli vypršení časového limitu (504 z brány, přestože začernění doběhlo), ztratí se i sůl, a opakování s Idempotency-Key ji neobsahuje. ProofSnap ji neuchovává."
                  }
                },
                "description": "Alespoň jedno z boxes, text_redactions nebo metadata_fields."
              },
              "example": {
                "text_redactions": [
                  {
                    "match": "jane.doe@example.com",
                    "reason": "personal data"
                  }
                ],
                "reason_summary": "Personal data of a third party"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Začerněný balíček je připraven. Idempotentní opakování dřívějšího začernění se stejným Idempotency-Key vrací také 201 s `Idempotent-Replay: true`: původní tělo s aktuálním stavem a nově předpodepsanou package_url (vynechá se, když balíček nelze předpodepsat; načtěte ho přes GET /captures/{capture_id}).",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replay": {
                "$ref": "#/components/headers/IdempotentReplay"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "redaction_id": {
                      "type": "string",
                      "example": "red_a1B2c3D4e5F6g7H8"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "completed"
                      ]
                    },
                    "redacted_from": {
                      "type": "string"
                    },
                    "redaction_count": {
                      "type": "integer",
                      "description": "Počet použitých akcí začernění."
                    },
                    "original_signature_verified": {
                      "type": "boolean",
                      "description": "Zda byl původní podpis manifestu před začerněním úspěšně ověřen."
                    },
                    "leakage_warnings": {
                      "type": "integer",
                      "description": "Vždy 0: začernění, u něhož kontrola po začernění najde zachovaný výraz, se místo vydání odmítne s 422 REDACTION_LEAK_DETECTED. Ponecháno kvůli kompatibilitě."
                    },
                    "package_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "package_url_expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "verify_url": {
                      "type": "string",
                      "description": "Odkaz na veřejný ověřovač ProofSnap.",
                      "format": "uri"
                    },
                    "ignored_boxes": {
                      "type": "array",
                      "items": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "description": "Indexy (od nuly) do obdélníků z požadavku pro obdélníky, které ležely zcela mimo snímek obrazovky a nic nezačernily. Zaznamenáno také v redaction_manifest.json (screenshot_boxes)."
                    },
                    "clipped_boxes": {
                      "type": "array",
                      "items": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "description": "Indexy (od nuly) do obdélníků z požadavku pro obdélníky, které přesahovaly okraj snímku obrazovky a byly na něm oříznuty. Zaznamenáno také v redaction_manifest.json (screenshot_boxes)."
                    },
                    "screenshot_method": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "jpeg_dct_blocks",
                        "decode_repaint_jpeg",
                        null
                      ],
                      "description": "Jak byly oblasti začerněny: jpeg_dct_blocks (komprimované bloky JPEG pod každou oblastí nahrazeny černými bloky, všechny ostatní bloky beze změny) nebo decode_repaint_jpeg (snímek obrazovky dekódován, přebarven a znovu zakódován). null, pokud žádná oblast nic nepřebarvila. Zaznamenává se také v redaction_manifest.json (screenshot_boxes.method)."
                    },
                    "painted_rects": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "x": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "y": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "w": {
                            "type": "integer",
                            "minimum": 0
                          },
                          "h": {
                            "type": "integer",
                            "minimum": 0
                          }
                        },
                        "required": [
                          "x",
                          "y",
                          "w",
                          "h"
                        ]
                      },
                      "description": "Skutečně začerněné oblasti v pixelech snímku obrazovky, jedna za každý použitý obdélník v pořadí obdélníků z požadavku bez ignorovaných. U jpeg_dct_blocks je každá oblast obdélník zaokrouhlený navenek na celé bloky, takže ho obsahuje; u decode_repaint_jpeg je to obdélník oříznutý na snímek obrazovky a zaokrouhlený navenek na celé bloky 8 x 8 nového souboru, které se začerní až po novém zakódování, aby komprese nemohla do obdélníku zanést barvu ze sousedství. Zaznamenáno také v redaction_manifest.json (screenshot_boxes.painted_rects)."
                    },
                    "text_rule_rects": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Samostatné oblasti snímku obrazovky začerněné jen kvůli textovým začerněním, bez oblastí, které obsahuje rámeček (oblast, které odpovídají dvě pravidla, se počítá jednou): v textových blocích souboru text_layout.json zdroje, jejichž textu odpovídá některé pravidlo, odhadnuté řádky se shodou, nebo celý blok, když je odhad nejistý. Uvedeno v redaction_manifest.json (screenshot_boxes.from_text_rules)."
                    },
                    "text_occurrences_not_located": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Výskyty textových začernění v textu stránky, které se nepodařilo najít na snímku obrazovky, a proto tam nebyly začerněny (text, který text_layout.json zdroje neuvádí, například text uvnitř obrázku; blok příliš velký na to, aby se kvůli jednomu výrazu začernil; oblasti nad limit jednoho začernění; snímek obrazovky, do kterého nešlo kreslit). Výskyty v bloku zcela mimo snímek obrazovky (není tam co začernit) se sem nepočítají; redaction_manifest.json je uvádí jako occurrences_not_on_screenshot. Nikdy víc než výskytů v textu stránky. Zkontrolujte snímek obrazovky a doplňte oblasti. Počty podle pravidel uvádí redaction_manifest.json (leakage_check.screenshot_text_advisory)."
                    },
                    "text_variants_remaining": {
                      "type": "object",
                      "description": "Pouze informativní, nikdy chyba: pro každé pravidlo s doslovným textem výskyty, které zůstaly v domtextcontent.txt a v textu page.html tohoto balíčku, pravidlo je nezachytilo, ale shodují se při ignorování velikosti písmen a diakritiky (například \"boskovické\" pro pravidlo \"Boskovic\" citlivé na velikost písmen), a zda je výraz v URL záznamu nebo ve výsledné URL, které se nikdy nezačerňují. `total` sčítá za každé pravidlo vyšší z obou počtů (oba soubory obsahují stejný text stránky). Pouze počty, nikdy text. Pravidla s regulárními výrazy se nepočítají. Uvedeno také v redaction_manifest.json (leakage_check.text_variants_advisory). Přítomno, když požadavek obsahuje textová začernění.",
                      "properties": {
                        "total": {
                          "type": "integer",
                          "minimum": 0
                        },
                        "per_rule": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "rule_index": {
                                "type": "integer",
                                "minimum": 0
                              },
                              "in_domtextcontent": {
                                "type": "integer",
                                "minimum": 0
                              },
                              "in_page_html_text": {
                                "type": "integer",
                                "minimum": 0
                              },
                              "in_capture_url": {
                                "type": "boolean"
                              }
                            }
                          }
                        }
                      }
                    },
                    "rules_in_capture_url": {
                      "type": "array",
                      "items": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "description": "Uvádí se, pokud požadavek obsahuje textová začernění. Indexy (od nuly) textových pravidel, jejichž text je také v URL záznamu nebo ve výsledné URL. Tyto URL se nikdy nemění: text byl odstraněn všude jinde a v nich zůstává viditelný. Prázdné, pokud jim žádné pravidlo neodpovídá. Také v redaction_manifest.json (leakage_check.capture_url, `remains_in_capture_url: true` u každého pravidla) a ve zprávě o začernění."
                    },
                    "rule_commitment_salt": {
                      "type": "string",
                      "pattern": "^[0-9a-f]{64}$",
                      "description": "Uvádí se, pokud požadavek obsahuje textová začernění. 32bajtová sůl (hex; rule_commitment_salt z požadavku, pokud byla poslána) pro rule_commitments v redaction_manifest.json: pro každé textové pravidlo SHA-256 ze soli pravidla, za kterou následují bajty UTF-8 kanonického JSON pravidla {\"match\": <text, or {\"pattern\", \"flags\"}>, \"case_insensitive\": <bool>}, kde sůl pravidla je HMAC-SHA256 s touto solí jako klíčem nad textem UTF-8 \"rule:<rule_index>\" (takže jedno pravidlo lze doložit zveřejněním jeho vlastní soli, bez ostatních). Pravidla se neukládají a sůl se vrací jen v této odpovědi: ne v opakování s Idempotency-Key, ve webhooku, v protokolu událostí ani v GET /captures/{capture_id}, a ProofSnap ji neuchovává. Uložte si ji ke svým záznamům: s ní můžete doložit, která pravidla začernění použilo."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (details.reason; například důvod, který není prostý text, nebo příznak regulárního výrazu y), REDACTION_NO_OPS (nic nebylo zadáno nebo nic neodpovídalo) nebo INVALID_URL (webhook_url není https). WEBHOOK_REQUIRES_API_KEY: webhook_url odeslané z relace dashboardu (webhooky vyžadují klíč API).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "QUOTA_EXCEEDED nebo PAYMENT_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "403": {
            "description": "FORBIDDEN: záznam vám nepatří. EIDAS_REQUIRES_LIVE_KEY: include_eidas s testovacím klíčem nebo u začernění testovacího záznamu (pak s details.reason). EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená. PLAN_ARCHIVE_ONLY: tarif uchovává pouze archiv a nevytváří žádnou novou práci. PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard). PLAN_API_READ_ONLY s details.reason \"session_outside_dashboard\": relace dashboardu účtu Website Archive, jejíž požadavek nemá hlavičku Origin nebo má takovou, která není adresou dashboardu ProofSnap (nová práce se na tomto tarifu vytváří jen v dashboardu; jde o měkkou bariéru, ne o bezpečnostní hranici).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "404": {
            "description": "CAPTURE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "409": {
            "description": "REDACTION_NOT_READY: zdrojový záznam není ve stavu completed. IDEMPOTENCY_IN_PROGRESS: požadavek se stejným Idempotency-Key stále běží (details.capture_id je ID začernění, které se dotazuje přes GET /captures/{capture_id}). COMPANY_READ_ONLY: zdroj patří firmě vedené jako firemní archiv.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "422": {
            "description": "REDACTION_SCREENSHOT_UNREADABLE: obrazová data snímku obrazovky nelze přečíst nebo snímek přesahuje limit pro začernění obdélníky (150 megapixelů u JPEG tak, jak ho zapisuje záznam, 60 megapixelů u PNG nebo jiného JPEG); začernění textu a metadat fungují i bez obdélníků. REDACTION_LEAK_DETECTED: začerněný výraz zůstal mimo URL záznamu (details { files, rule_indexes, metadata_fields, in_capture_url }; in_capture_url je true, když je text odmítnutého pravidla také v URL záznamu nebo ve výsledné URL, kde se nikdy nepočítá). REDACTION_SOURCE_UNSUPPORTED: zdroj není záznamem webové stránky (details { source } nebo { manifest_type }). SSRF_BLOCKED: webhook_url míří na blokovanou adresu. REDACTION_SOURCE_INTEGRITY_FAILED: soubor zdrojového balíčku neodpovídá SHA-256 uvedenému v jeho podepsaném manifestu, nebo uvedený soubor chybí (details { mismatched, missing }, jen názvy souborů); nic se nezačernilo ani nezaúčtovalo. IDEMPOTENCY_KEY_REUSED: Idempotency-Key už byl použit s jiným tělem požadavku (nebo z jiného prostředí klíčů).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED: příliš mnoho požadavků v aktuálním 60sekundovém okně. `error.details.retry_after_seconds` opakuje Retry-After. RateLimit hlásí r=0 a počet sekund do resetu okna. RATE_LIMITED také pro relaci dashboardu Website Archive: její denní strop 100 jednotek za den v UTC, sdílený jednotlivými i dávkovými záznamy (jedna jednotka za URL), porovnáním, začerněním a certify-hash (jedna jednotka za požadavek); požadavek, který se nevejde, se odmítne celý (details.daily_limit, details.remaining, details.action \"wa_session_captures\"; Retry-After a details.retry_after_seconds udávají počet sekund do dalšího dne v UTC a minutové hlavičky RateLimit a X-RateLimit-* se vynechají). Krátké odmítnutí jen s details.retry_after_seconds a Retry-After: 1 znamená souběžnou aktualizaci počítadla: opakujte požadavek. Odmítnutí, které nezavinil volající, jednotky vrací; práce přijatá s 202, která později selže, svou jednotku ponechává. Jde o měkkou bránu, ne o bezpečnostní hranici.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMITED",
                    "message": "Too many requests. See Retry-After header.",
                    "details": {
                      "retry_after_seconds": 42
                    }
                  },
                  "request_id": "..."
                }
              }
            }
          },
          "500": {
            "description": "INTERNAL_ERROR: neočekávaná chyba serveru; opakujte s exponenciálním odstupem. CAPTURE_TIME_BUDGET_EXCEEDED: synchronnímu začernění došel časový rozpočet a bylo zastaveno dříve, než byl vydán jakýkoli balíček; nic nebylo účtováno. S `details.reason` `source_read` zabralo čtení zdrojového balíčku většinu rozpočtu: balíček je teď příliš velký na začernění, zkuste to později.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/EidasOrAuthUnavailable"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/compare": {
      "post": {
        "tags": [
          "Porovnání a začernění"
        ],
        "operationId": "compareCaptures",
        "summary": "Porovnat dva záznamy",
        "description": "Porovná dva vaše dokončené záznamy (text stránky, obrázky zobrazené na stránce, metadata) a vytvoří podepsaný balíček porovnání. Vrátí 202; dotazujte se na GET /captures/{compare_id}, který pak obsahuje type, compared a diff_summary. Obrázky se porovnávají podle soupisu obrázků, který každý zdrojový záznam zapečetil (image_inventory.json: adresa každého zobrazeného obrázku a SHA-256 jeho bajtů), nikdy pixel po pixelu; výsledky jsou v image_changes.json a v diff_summary.image_changes. Zdroj pořízený dříve, než záznamy začaly ukládat soupis obrázků, se porovná také, jen bez porovnání obrázků (diff_summary.image_changes.status not_run). Započítá se jako jeden záznam. Srovnatelné se srovnatelným (2026-10-14): dva záznamy vykreslené s jiným profilem zařízení nebo s jiným nastavením záznamu se odmítnou s 422 COMPARE_PROFILE_MISMATCH (details.differing, details.before, details.after: pouze lišící se pole, vložené CSS a JavaScript jako jejich SHA-256), pokud allow_profile_mismatch není true, a dva záznamy různých stránek s 422 COMPARE_URL_MISMATCH (details.before a details.after: url a final_url jako původ (origin) a cesta), pokud allow_url_mismatch není true. Kontrola proběhne nejprve nad oběma řádky záznamů (dříve, než se cokoli načte nebo rezervuje), poté nad zapečetěnými metadata.json a forensic_log.json obou balíčků v rámci níže popsané kontroly zdrojů; neshoda zjištěná až během porovnání způsobí selhání porovnání s tímto kódem a měsíční jednotka se vrátí. Text se porovnává řádek po řádku deterministickým řádkovým diffem (bez časového limitu): diff_summary počítá řádky (text_unit line). Porovnat lze pouze webové záznamy (pořízené přes API nebo automatickým záznamem): certifikace hashe, porovnání nebo začerněný balíček se odmítne s 422 COMPARE_SOURCE_UNSUPPORTED (`details.capture_id`, `details.source`) dříve, než se načte jakýkoli balíček a cokoli rezervuje. Než se cokoli porovná nebo rezervuje, přepočítá se SHA-256 každého souboru, který manifest.json zdrojového balíčku uvádí se SHA-256; zdroj s pozměněným nebo chybějícím souborem nebo s manifestem, který neuvádí žádný soubor se SHA-256, se odmítne s 422 COMPARE_SOURCE_INTEGRITY_FAILED (žádné porovnání, žádný řádek, žádná měsíční jednotka). Porovnávají se pouze tyto uvedené soubory: soubor ve zdrojovém balíčku, který jeho manifest neuvádí se SHA-256 (například přidaný text_layout.json, image_inventory.json, page.html nebo domtextcontent.txt), se považuje za chybějící. Kontrola proběhne přímo při požadavku, když mají oba zdrojové balíčky nejvýše 50 MB a skončí přibližně do 10 sekund; jinak se požadavek přijme a kontrolu zopakuje až běh porovnání, a neúspěšný zdroj pak způsobí selhání porovnání (GET /captures/{compare_id} ukáže status failed s error.code COMPARE_SOURCE_INTEGRITY_FAILED) a měsíční jednotka se vrátí. Dokončené porovnání tuto kontrolu zaznamená v compare.json `sources[].source_files_reverified` a v comparison_method.json `source_verification`. /compare neposílá webhooky: webhook_url v těle se ignoruje. Dotazujte se na GET /captures/{compare_id}.\n\nPorovnání, jehož součástí je testovací záznam (pořízený testovacím klíčem, v sandboxu nebo účtem bez propojeného fakturačního účtu), je testovací balíček bez ohledu na to, jakým klíčem se o něj žádá: s vodoznakem, `test_mode: true` v manifest.json, `test_mode: true` u daného zdroje v compare.json `sources[]` a testovací řádek (key_env test), který se neúčtuje a nespotřebuje měsíční jednotku. include_eidas s testovacím zdrojem se odmítne s 403 EIDAS_REQUIRES_LIVE_KEY (details.reason).\n\nLimit počtu požadavků platí pro každý účet zvlášť v 60sekundových oknech (všechny klíče API účtu a jeho relace v dashboardu sdílejí jedno okno). Jakmile omezovač proběhne, obsahují odpovědi této cesty hlavičky `RateLimit-Policy` a `RateLimit` (podle IETF draft-ietf-httpapi-ratelimit-headers) a navíc starší `X-RateLimit-Limit`, `X-RateLimit-Remaining` a `X-RateLimit-Reset`. Odpověď 429 přidává `Retry-After`.\n\nPosílejte Idempotency-Key, aby opakovaný pokus (například po chybě 504) vrátil první odpověď místo druhého, vyúčtovaného běhu (24 hodin, stejná pravidla jako u POST /captures). Klíč se zabere před kontrolou zdrojů, takže opakování, zatímco první požadavek ještě běží, vrátí 409 IDEMPOTENCY_IN_PROGRESS; požadavek odmítnutý kontrolou zdrojů nebo kvótou svůj klíč uvolní, takže opakování se stejným klíčem se zkontroluje znovu.\n\nImportovaný balíček důkazů (zdroj import, ID s předponou `imp_`) nelze porovnat: 422 IMPORT_NOT_SUPPORTED (details.capture_id).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "capture_id_1": {
                    "type": "string",
                    "description": "Starší záznam."
                  },
                  "capture_id_2": {
                    "type": "string",
                    "description": "Novější záznam. Musí se lišit od capture_id_1."
                  },
                  "language": {
                    "type": "string",
                    "description": "Jazyk PDF s porovnáním. Pouze přesný kód; při jakékoli jiné hodnotě se bez upozornění použije angličtina.",
                    "enum": [
                      "en",
                      "de",
                      "it",
                      "fr",
                      "es",
                      "pt_BR",
                      "cs",
                      "el",
                      "hi",
                      "hu",
                      "id",
                      "ja",
                      "ko",
                      "nl",
                      "pl",
                      "ro",
                      "ru",
                      "sv",
                      "tr",
                      "vi",
                      "zh_CN",
                      "zh_TW",
                      "ar",
                      "he",
                      "da",
                      "fi",
                      "nb",
                      "sk",
                      "uk"
                    ]
                  },
                  "include_eidas": {
                    "type": "boolean",
                    "description": "Stejně jako v CaptureOptions.include_eidas.",
                    "default": false
                  },
                  "include_rule_902": {
                    "type": "boolean",
                    "description": "Přidá k porovnání nepodepsanou šablonu certifikace (rule_902_certification.pdf, viz CaptureOptions.include_rule_902). Není k dispozici pro záznamy vykreslené odlišně: při allow_profile_mismatch true a neshodě profilu nebo nastavení vrátí 422 RULE902_NOT_AVAILABLE_FOR_MISMATCH. Momentálně vypnuto: šablona certifikace je dočasně vypnutá, takže se toto pole přijme a ignoruje (rule_902_certification.pdf se nevygeneruje ani neuvede v balíčku) a odpověď nese varování RULE902_DISABLED.",
                    "default": false
                  },
                  "allow_profile_mismatch": {
                    "type": "boolean",
                    "default": false,
                    "description": "Porovná dva záznamy, i když byly pořízeny s jiným profilem zařízení (options.viewport mobile nebo desktop, viewport_width, viewport_height, device_scale_factor; v zapečetěných datech: velikost viewportu, faktor měřítka zařízení, emulace mobilu, user agent bez čísel verzí) nebo s jiným nastavením záznamu, které mění vykreslení stránky (dark_mode, block_ads, block_resources, inject_css, inject_js podle SHA-256, expand_collapsed, dismiss_consent, dismiss_popups, celá stránka). Bez něj se taková dvojice odmítne s 422 COMPARE_PROFILE_MISMATCH. S ním jsou diff_summary.text_verdict a images_verdict undetermined, changed je null, pokud se neliší některé obsahové pole metadat, a include_rule_902 se odmítne."
                  },
                  "allow_url_mismatch": {
                    "type": "boolean",
                    "default": false,
                    "description": "Porovná dva záznamy různých stránek. Dva záznamy se považují za stejnou stránku, když se některá adresa jednoho (požadovaná url, url a final_url zaznamenané v jeho metadata.json) po normalizaci shoduje s některou adresou druhého (host malými písmeny, http a https se berou jako totéž, výchozí port, fragment, koncové lomítko a proměnlivé parametry dotazu se vynechávají). Bez něj se různé stránky odmítnou s 422 COMPARE_URL_MISMATCH."
                  }
                },
                "required": [
                  "capture_id_1",
                  "capture_id_2"
                ]
              },
              "example": {
                "capture_id_1": "cap_a1B2c3D4e5F6g7H8",
                "capture_id_2": "cap_h8G7f6E5d4C3b2A1"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Přijato.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              },
              "X-Quota-Limit": {
                "$ref": "#/components/headers/QuotaLimit"
              },
              "X-Quota-Remaining": {
                "$ref": "#/components/headers/QuotaRemaining"
              },
              "X-Quota-Used": {
                "$ref": "#/components/headers/QuotaUsed"
              },
              "X-Quota-Cap": {
                "$ref": "#/components/headers/QuotaCap"
              },
              "X-Quota-Org-Limit": {
                "$ref": "#/components/headers/QuotaOrgLimit"
              },
              "X-Quota-Org-Used": {
                "$ref": "#/components/headers/QuotaOrgUsed"
              },
              "X-Sandbox-Limit": {
                "$ref": "#/components/headers/SandboxLimit"
              },
              "X-Sandbox-Remaining": {
                "$ref": "#/components/headers/SandboxRemaining"
              },
              "X-Sandbox-Used": {
                "$ref": "#/components/headers/SandboxUsed"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "compare_id": {
                      "type": "string",
                      "example": "cmp_a1B2c3D4e5F6g7H8"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing"
                      ]
                    },
                    "poll_path": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    },
                    "warnings": {
                      "$ref": "#/components/schemas/Rule902DisabledWarnings"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: neplatný JSON, chybějící ID, stejné ID dvakrát, nebo allow_profile_mismatch / allow_url_mismatch, které není boolean.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "QUOTA_EXCEEDED nebo PAYMENT_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "403": {
            "description": "FORBIDDEN: záznam vám nepatří. EIDAS_REQUIRES_LIVE_KEY: include_eidas s testovacím klíčem nebo s testovacím zdrojovým záznamem (pak s details.reason). EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená. PLAN_ARCHIVE_ONLY: tarif uchovává pouze archiv a nevytváří žádnou novou práci. PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard). PLAN_API_READ_ONLY s details.reason \"session_outside_dashboard\": relace dashboardu účtu Website Archive, jejíž požadavek nemá hlavičku Origin nebo má takovou, která není adresou dashboardu ProofSnap (nová práce se na tomto tarifu vytváří jen v dashboardu; jde o měkkou bariéru, ne o bezpečnostní hranici).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "404": {
            "description": "CAPTURE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "409": {
            "description": "COMPARE_NOT_READY: oba záznamy musí být dokončené. COMPANY_READ_ONLY: zdroj patří firmě vedené jako firemní archiv (nic nového se z něj nevytváří).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "422": {
            "description": "COMPARE_SOURCE_INTEGRITY_FAILED: soubor zdrojového záznamu neodpovídá SHA-256, který uvádí jeho podepsaný manifest, nebo chybí; nic se neporovnalo ani neúčtovalo. `details.capture_id`, `details.mismatched`, `details.missing` označují první neúspěšný zdroj; `details.reason` je přítomno, když nelze použít samotný zdrojový manifest (například \"the source manifest lists no file with a SHA-256\" nebo \"the source manifest lists no files\"); `details.sources[]` uvádí každý neúspěšný zdroj se stejnými poli. Ověřte zdrojový záznam (POST /captures/{capture_id}/verify). COMPARE_SOURCE_UNSUPPORTED: zdroj není webový záznam (certifikace hashe, porovnání nebo začerněný balíček); nic se nečetlo, neporovnalo ani neúčtovalo. `details.capture_id` označuje tento zdroj a `details.source` jeho druh, pokud ho řádek zaznamenává. Porovnejte místo toho původní webové záznamy. COMPARE_PROFILE_MISMATCH: oba záznamy byly pořízeny s jiným profilem zařízení nebo jiným nastavením záznamu; `details.differing` uvádí názvy polí (na úrovni řádku: viewport, viewport_width, viewport_height, device_scale_factor, dark_mode, block_ads, block_resources, inject_css, inject_js, expand_collapsed, dismiss_consent, dismiss_popups, full_page; na úrovni zapečetěných dat: viewport_width, viewport_height, device_scale_factor, is_mobile, user_agent a stejná nastavení), `details.before` a `details.after` jejich hodnoty. Chcete-li přesto porovnat, pošlete allow_profile_mismatch: true. COMPARE_URL_MISMATCH: oba záznamy jsou z různých stránek; `details.before` a `details.after` uvádějí url a final_url jako původ (origin) a cestu. Chcete-li přesto porovnat, pošlete allow_url_mismatch: true. RULE902_NOT_AVAILABLE_FOR_MISMATCH: include_rule_902 s allow_profile_mismatch u záznamů vykreslených odlišně; `details.differing`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED: příliš mnoho požadavků v aktuálním 60sekundovém okně. `error.details.retry_after_seconds` opakuje Retry-After. RateLimit hlásí r=0 a počet sekund do resetu okna. RATE_LIMITED také pro relaci dashboardu Website Archive: její denní strop 100 jednotek za den v UTC, sdílený jednotlivými i dávkovými záznamy (jedna jednotka za URL), porovnáním, začerněním a certify-hash (jedna jednotka za požadavek); požadavek, který se nevejde, se odmítne celý (details.daily_limit, details.remaining, details.action \"wa_session_captures\"; Retry-After a details.retry_after_seconds udávají počet sekund do dalšího dne v UTC a minutové hlavičky RateLimit a X-RateLimit-* se vynechají). Krátké odmítnutí jen s details.retry_after_seconds a Retry-After: 1 znamená souběžnou aktualizaci počítadla: opakujte požadavek. Odmítnutí, které nezavinil volající, jednotky vrací; práce přijatá s 202, která později selže, svou jednotku ponechává. Jde o měkkou bránu, ne o bezpečnostní hranici.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMITED",
                    "message": "Too many requests. See Retry-After header.",
                    "details": {
                      "retry_after_seconds": 42
                    }
                  },
                  "request_id": "..."
                }
              }
            }
          },
          "500": {
            "description": "INTERNAL_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/EidasOrAuthUnavailable"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/certify-hash": {
      "post": {
        "tags": [
          "Certifikace hashe"
        ],
        "operationId": "certifyHash",
        "summary": "Certifikovat hashe souborů",
        "description": "Pošlete jeden SHA-256 (hash) nebo až 100 (hashes). Balíček obsahuje manifest.json (s vašimi hashi), manifest.sig, publickey.pem, evidence.pdf, skripty verification/ a pokud je k dispozici, manifest.json.ots.\n\n- Jeden hash: synchronně, vrací 200 s hotovým certifikátem.\n- Více hashů s combined: true: jeden certifikát se všemi hashi, synchronně, vrací 200.\n- Více hashů bez combined: jeden nezávislý certifikát na každý hash, spuštěno na pozadí; vrací 202 s certify_ids. Dotazujte se přes GET /captures/{certify_id}; s webhook_url každý pošle certify.completed.\n\nKaždý certifikát se do měření, měsíčního limitu i limitu počtu požadavků započítá jako jeden záznam (N hashů bez combined se počítá jako N; N větší než limit okna vrací 400 RATE_LIMIT_COST_TOO_HIGH). `label` se vytiskne na certifikát: zkrátí se na 200 znaků a musí to být prostý text (bez řídicích, neviditelných znaků a znaků pro směr textu, jinak 400). V dávce chyba týkající se jedné položky uvádí tuto položku v `error.details.index`.\n\nLimit počtu požadavků platí na účet v 60sekundových oknech (všechny klíče API účtu a jeho relace dashboardu sdílejí jedno okno). Jakmile limiter proběhne, odpovědi tohoto endpointu obsahují hlavičky `RateLimit-Policy` a `RateLimit` (podle návrhu IETF draft-ietf-httpapi-ratelimit-headers) a starší `X-RateLimit-Limit`, `X-RateLimit-Remaining` a `X-RateLimit-Reset`. Odpověď 429 přidává `Retry-After`.\n\nPošlete Idempotency-Key, aby opakovaný požadavek (například po 504) vrátil první odpověď místo druhého, zpoplatněného běhu (24 hodin, stejná pravidla jako u POST /captures).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "hash": {
                    "type": "string",
                    "description": "SHA-256 jako 64 hexadecimálních znaků (na velikosti písmen nezáleží). Použijte hash nebo hashes."
                  },
                  "label": {
                    "type": "string",
                    "description": "Zobrazovaný název souboru. Delší hodnoty se zkrátí na 200 znaků."
                  },
                  "hashes": {
                    "type": "array",
                    "items": {
                      "oneOf": [
                        {
                          "type": "string",
                          "description": "SHA-256 v hexadecimálním tvaru."
                        },
                        {
                          "type": "object",
                          "properties": {
                            "hash": {
                              "type": "string"
                            },
                            "label": {
                              "type": "string"
                            }
                          },
                          "required": [
                            "hash"
                          ]
                        }
                      ]
                    },
                    "minItems": 1,
                    "maxItems": 100
                  },
                  "combined": {
                    "type": "boolean",
                    "description": "Certifikovat všechny hashe jedním certifikátem.",
                    "default": false
                  },
                  "algorithm": {
                    "type": "string",
                    "enum": [
                      "sha256"
                    ],
                    "default": "sha256"
                  },
                  "language": {
                    "type": "string",
                    "description": "Jazyk PDF čitelných pro člověka. Jedna z hodnot: en, de, it, fr, es, pt_BR, cs, el, hi, hu, id, ja, ko, nl, pl, ro, ru, sv, tr, vi, zh_CN, zh_TW, ar, he, da, fi, nb, sk, uk. Velikost písmen, spojovník a region se tolerují (\"DE\", \"fr-FR\" a \"PT-BR\" se přijmou); samotné \"pt\" a \"zh\" se odmítnou. Nepodporovaná hodnota vrátí 400 MALFORMED_REQUEST."
                  },
                  "case_reference": {
                    "type": "string",
                    "description": "Tiskne se na certifikát. Řídí se pravidlem pro prostý text (viz PlainText); nejvýše 200 znaků.",
                    "maxLength": 200
                  },
                  "include_eidas": {
                    "type": "boolean",
                    "description": "Stejně jako v CaptureOptions.include_eidas.",
                    "default": false
                  },
                  "include_rule_902": {
                    "type": "boolean",
                    "description": "Přidá nepodepsanou šablonu certifikace (rule_902_certification.pdf, viz CaptureOptions.include_rule_902). Momentálně vypnuto: šablona certifikace je dočasně vypnutá, takže se toto pole přijme a ignoruje (rule_902_certification.pdf se nevygeneruje ani neuvede v balíčku) a odpověď nese varování RULE902_DISABLED.",
                    "default": false
                  },
                  "webhook_url": {
                    "type": "string",
                    "description": "https URL, na kterou přichází certify.completed. URL musí být https a nesmí směřovat na privátní, loopback, link-local, carrier-grade NAT ani cloudovou metadatovou adresu (stejná pravidla jako u URL záznamu; jinak 422 SSRF_BLOCKED). Prázdná hodnota nebo hodnota jen z mezer znamená bez webhooku. Vyžaduje klíč API: při odeslání z relace dashboardu je odmítnuta s 400 WEBHOOK_REQUIRES_API_KEY, protože webhooky se podepisují tajným kódem webhooku daného klíče.",
                    "format": "uri"
                  }
                }
              },
              "example": {
                "hash": "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08",
                "label": "contract.pdf"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Certifikát připraven (jeden hash nebo kombinovaný).",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CertifyResult"
                }
              }
            }
          },
          "202": {
            "description": "Spuštěno několik nezávislých certifikátů. Certifikát, který po spuštění odmítne měsíční limit nebo příděl sandboxu, selže: jeho řádek (GET /captures/{certify_id}) má status failed a error.code QUOTA_EXCEEDED.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "batch_id": {
                      "type": "string"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "certify_ids": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      },
                      "description": "ID vytvořených certifikátů (včetně těch, jejichž spuštění selhalo)."
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing"
                      ]
                    },
                    "certificates": {
                      "type": "array",
                      "description": "Jedna položka pro každý odeslaný hash, v pořadí odeslání. status failed: tento certifikát se nepodařilo spustit (jeho řádek, pokud vznikl, je označen jako failed); ostatní běží dál.",
                      "items": {
                        "type": "object",
                        "properties": {
                          "certify_id": {
                            "type": "string",
                            "nullable": true
                          },
                          "hash_sha256": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string",
                            "enum": [
                              "processing",
                              "failed"
                            ]
                          }
                        }
                      }
                    },
                    "failed_count": {
                      "type": "integer",
                      "description": "Kolik položek certificates se nepodařilo spustit. Pokud selžou všechny, odpověď je místo toho 500 CONFIGURATION_ERROR."
                    },
                    "warnings": {
                      "$ref": "#/components/schemas/Rule902DisabledWarnings"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (details.reason uvádí pole, například \"label must be a string\"; details.index uvádí položku dávky), INVALID_HASH (details.index v dávce) nebo INVALID_URL (webhook_url není https nebo obsahuje přihlašovací údaje). WEBHOOK_REQUIRES_API_KEY: webhook_url odeslané z relace dashboardu (webhooky vyžadují klíč API). RATE_LIMIT_COST_TOO_HIGH: více hashů (bez combined), než povoluje jedno okno limitu počtu požadavků; details { max_per_window, window_seconds, requested }.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED, nebo QUOTA_EXCEEDED u synchronních cest.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "403": {
            "description": "EIDAS_REQUIRES_LIVE_KEY (details.reason \"no_billing_account\", když ostrý klíč nebo relace běží jako testovací, protože není propojen fakturační účet). EMAIL_NOT_VERIFIED: relace v dashboardu, jejíž e-mailová adresa není potvrzena, nebo klíč API takového účtu. PLAN_ARCHIVE_ONLY: tarif jen uchovává archiv a nevytváří žádnou novou práci. PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard). PLAN_API_READ_ONLY s details.reason \"session_outside_dashboard\": relace v dashboardu účtu Website Archive, jejíž požadavek nemá hlavičku Origin nebo ji má s adresou, která není adresou dashboardu ProofSnap (novou práci na tomto tarifu lze vytvářet jen v dashboardu; měkká brána, nikoli bezpečnostní hranice).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "422": {
            "description": "SSRF_BLOCKED: webhook_url míří na privátní, loopback, link-local nebo jinak blokovanou adresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED: příliš mnoho požadavků v aktuálním 60sekundovém okně. `error.details.retry_after_seconds` opakuje Retry-After. RateLimit hlásí r=0 a počet sekund do resetu okna. RATE_LIMITED také pro relaci dashboardu Website Archive: její denní strop 100 jednotek za den v UTC, sdílený jednotlivými i dávkovými záznamy (jedna jednotka za URL), porovnáním, začerněním a certify-hash (jedna jednotka za požadavek); požadavek, který se nevejde, se odmítne celý (details.daily_limit, details.remaining, details.action \"wa_session_captures\"; Retry-After a details.retry_after_seconds udávají počet sekund do dalšího dne v UTC a minutové hlavičky RateLimit a X-RateLimit-* se vynechají). Krátké odmítnutí jen s details.retry_after_seconds a Retry-After: 1 znamená souběžnou aktualizaci počítadla: opakujte požadavek. Odmítnutí, které nezavinil volající, jednotky vrací; práce přijatá s 202, která později selže, svou jednotku ponechává. Jde o měkkou bránu, ne o bezpečnostní hranici.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMITED",
                    "message": "Too many requests. See Retry-After header.",
                    "details": {
                      "retry_after_seconds": 42
                    }
                  },
                  "request_id": "..."
                }
              }
            }
          },
          "500": {
            "description": "CONFIGURATION_ERROR: certifikace selhala (details.reason).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          },
          "504": {
            "description": "UPSTREAM_TIMEOUT: synchronní certifikace (jeden hash nebo kombinovaná) nebyla dokončena zhruba do 25 s. Může se ještě dokončit: details.certify_id a details.poll_path určují řádek, na který se dotazujte přes GET /captures/{capture_id}.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "RateLimit": {
                "$ref": "#/components/headers/RateLimit"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/RateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/RateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/RateLimitReset"
              }
            }
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      }
    },
    "/webhook-events/{capture_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CaptureId"
        }
      ],
      "get": {
        "tags": [
          "Webhooky"
        ],
        "operationId": "listWebhookEvents",
        "summary": "Protokol doručení webhooků",
        "description": "Všechny pokusy o doručení pro jeden záznam, certifikát nebo začernění, od nejstaršího.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Protokol doručení.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "capture_id": {
                      "type": "string"
                    },
                    "webhook_url": {
                      "type": "string",
                      "description": "URL webhooku řádku (options.webhook_url záznamu, nebo URL zadaná u certifikátu či začernění; null, když žádná není). Vlastník firmy, pro kterou byl záznam pořízen, při čtení protokolu místa vidí jen schéma, hostitele, port a cestu (dotaz a fragment se odstraní, mohou obsahovat token); toto čtení se uchová v historii přístupů k záznamu (action webhook_events).",
                      "nullable": true
                    },
                    "attempts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "attempt_number": {
                            "type": "integer"
                          },
                          "attempted_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "status_code": {
                            "type": "integer",
                            "nullable": true
                          },
                          "latency_ms": {
                            "type": "integer",
                            "nullable": true
                          },
                          "success": {
                            "type": "boolean"
                          },
                          "error": {
                            "type": "string",
                            "nullable": true,
                            "description": "null, pokud bylo doručeno. Jinak obecná třída, nikdy surová síťová chyba: connection_failed, timeout, blocked_address (hostitel se v době doručení přeložil na privátní nebo jinak blokovanou adresu), redirect_not_followed (endpoint odpověděl kódem 3xx; přesměrování se nikdy nesledují), http_<status> (odpověď mimo 2xx) nebo věta s důvodem, proč událost nebyla odeslána (chybí klíč API, klíč byl zneplatněn nebo nenalezen, chybí tajný kód webhooku, načtení tajného kódu selhalo)."
                          },
                          "delivery_id": {
                            "type": "string",
                            "description": "Hlavička webhook-id tohoto doručení bez předpony `msg_`."
                          }
                        }
                      }
                    },
                    "attempt_count": {
                      "type": "integer"
                    },
                    "last_success": {
                      "type": "string",
                      "description": "attempted_at posledního úspěšného pokusu.",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "FORBIDDEN: záznam vám nepatří.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "CAPTURE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/scheduled-captures": {
      "post": {
        "tags": [
          "Automatické záznamy"
        ],
        "operationId": "createSchedule",
        "summary": "Vytvoření automatického záznamu",
        "description": "interval a cron: každý běh pořídí záznam a s webhook_url odešle capture.completed nebo capture.failed.\n\non_change: každý běh nejdřív stáhne stránku (prostým HTTP, nebo vykreslením v prohlížeči s js_render) a spočítá hash jejího normalizovaného textu. Tato kontrola není záznam a neúčtuje se. První běh pořídí výchozí záznam. Když se hash změní, pořídí se nový záznam, porovná se s předchozím a na webhook_url se odešle monitor.change_detected. Stránka, která vrátí chybu nebo téměř žádný text, se počítá jako beze změny.\n\nPo 5 neúspěšných bězích za sebou se automatický záznam sám pozastaví. Když je dosažen měsíční limit nebo je předplatné po splatnosti, běhy se přeskakují a automatický záznam zůstává aktivní.\n\nLimity podle plánu:\n\n| Plán | Aktivní automatické záznamy | Minimální interval | on_change |\n| --- | --- | --- | --- |\n| sandbox | 0 | není k dispozici | ne |\n| developer | 3 | 300 s | ano |\n| startup | 25 | 300 s | ano |\n| growth | 200 | 300 s | ano |\n| custom | neomezeně | 300 s | ano |\n| legal_solo | 3 | 300 s | ano |\n| legal_seats | 3 | 300 s | ano |\n| website_archive | 30 | 86400 s | ano |\n| archive_only | 0 | není k dispozici | ne |\n\nIdempotency-Key: opakovaný pokus se stejným klíčem a tělem do 24 hodin dostane zpět první odpověď 201 (hlavička Idempotent-Replay: true) místo druhého automatického záznamu; stejný klíč s jiným tělem vrátí 422 IDEMPOTENCY_KEY_REUSED.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ScheduleRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Vytvořeno.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Schedule"
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST, INVALID_URL, INVALID_CRON, INTERVAL_TOO_SHORT (details.min_interval_seconds) nebo chyba voleb záznamu. WEBHOOK_REQUIRES_API_KEY: webhook_url odeslané z relace dashboardu (webhooky vyžadují klíč API).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "SCHEDULE_LIMIT_REACHED (details.max_active, details.active) nebo ON_CHANGE_REQUIRES_PLAN. EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená. PLAN_ARCHIVE_ONLY: plán uchovává jen archiv a nevytváří žádnou novou práci. PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard). PLAN_API_READ_ONLY s details.reason \"session_outside_dashboard\": relace dashboardu účtu Website Archive, jejíž požadavek nemá hlavičku Origin nebo má takovou, která není adresou dashboardu ProofSnap (novou práci lze na tomto plánu vytvářet jen v dashboardu; jde o měkkou bránu, ne o bezpečnostní hranici).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "SSRF_BLOCKED: url nebo webhook_url míří na privátní, loopback, link-local nebo jinak blokovanou adresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ]
      },
      "get": {
        "tags": [
          "Automatické záznamy"
        ],
        "operationId": "listSchedules",
        "summary": "Výpis automatických záznamů",
        "description": "Až 100 vašich automatických záznamů.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Automatické záznamy.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "schedules": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Schedule"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/scheduled-captures/{schedule_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ScheduleId"
        }
      ],
      "get": {
        "tags": [
          "Automatické záznamy"
        ],
        "operationId": "getSchedule",
        "summary": "Získání automatického záznamu",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Automatický záznam.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Schedule"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "SCHEDULE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "patch": {
        "tags": [
          "Automatické záznamy"
        ],
        "operationId": "updateSchedule",
        "summary": "Pozastavení, obnovení nebo úprava automatického záznamu",
        "description": "Pošlete status pro pozastavení nebo obnovení a/nebo libovolné pole ScheduleRequest pro úpravu. Odeslané pole nejvyšší úrovně nahradí uložené, včetně explicitního null (tak se mažou webhook_url, timezone a js_render); vynechané pole si ponechá uloženou hodnotu; výsledek se znovu ověří jako celek. `options` je výjimkou z úprav pole po poli: nahrazuje se jako celá mapa, neslučuje se klíč po klíči, proto pošlete kompletní volby, které chcete (nejdřív je načtěte přes GET). Volba vynechaná z mapy se odstraní. Obnovení zkontroluje limit aktivních automatických záznamů, vynuluje počet selhání a vypočítá další běh od teď.\n\nZ relace dashboardu nelze webhook_url nastavit (400 WEBHOOK_REQUIRES_API_KEY); poslání null nebo prázdného řetězce ho smaže. Automatický záznam vytvořený z relace dashboardu nikdy neměl klíč API, kterým by se podepisovalo, proto jeho úprava zároveň zahodí i dříve uloženou webhook_url a ani klíč API ji k němu nemůže přidat (400 WEBHOOK_REQUIRES_API_KEY): plánovač podepisuje webhooky automatického záznamu tajným kódem webhooku toho klíče, kterým byl automatický záznam vytvořen. Chcete-li dostávat webhooky, vytvořte automatický záznam klíčem API.\n\nZměna url, mode nebo js_render u automatického záznamu on_change (nebo přepnutí automatického záznamu na on_change či z něj) smaže jeho výchozí stav (uložený hash kontroly a poslední záznam), takže další běh pořídí nový výchozí záznam a nebude porovnávat nový cíl se starým. Tělo požadavku musí být objekt JSON (jinak 400 MALFORMED_REQUEST).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "paused"
                    ]
                  },
                  "url": {
                    "type": "string",
                    "format": "uri"
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "interval",
                      "cron",
                      "on_change"
                    ]
                  },
                  "interval_seconds": {
                    "type": "integer"
                  },
                  "cron_expr": {
                    "type": "string"
                  },
                  "timezone": {
                    "type": "string",
                    "nullable": true,
                    "description": "Časové pásmo IANA pro cron. null nebo prázdný řetězec vrací nastavení zpět na UTC."
                  },
                  "webhook_url": {
                    "type": "string",
                    "description": "Pro odstranění pošlete null nebo prázdný řetězec. URL musí být https a nesmí mířit na privátní, loopback, link-local, carrier-grade NAT ani cloud-metadata adresu (stejná pravidla jako u URL záznamu; jinak 422 SSRF_BLOCKED). Vyžaduje klíč API na obou stranách: když se pošle z relace dashboardu, nebo s klíčem API pro automatický záznam vytvořený v dashboardu, odmítne se s 400 WEBHOOK_REQUIRES_API_KEY, protože webhooky se podepisují tajným kódem webhooku toho klíče, kterým byl automatický záznam vytvořen.",
                    "nullable": true
                  },
                  "js_render": {
                    "type": "boolean",
                    "nullable": true,
                    "description": "null znamená false."
                  },
                  "options": {
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/CaptureOptions"
                      }
                    ],
                    "description": "Nahradí uložené volby jako celek (neslučuje je klíč po klíči). Pošlete kompletní mapu; vynechaná volba se odstraní. null obnoví výchozí volby. options.webhook_url se nikdy neukládá (viz webhook_url)."
                  },
                  "max_capture_age_seconds": {
                    "type": "integer",
                    "nullable": true,
                    "minimum": 86400,
                    "maximum": 34560000,
                    "description": "Jen u on_change: úplný záznam nejméně každých N sekund i bez změny (1 až 400 dnů, déle než interval_seconds). null ho odstraní. Přepnutí režimu na interval nebo cron ho zruší."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Aktualizovaný automatický záznam.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Schedule"
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (včetně případu, kdy není co aktualizovat), INVALID_URL, INVALID_CRON nebo INTERVAL_TOO_SHORT. WEBHOOK_REQUIRES_API_KEY: webhook_url odeslané z relace dashboardu, nebo odeslané s klíčem API pro automatický záznam vytvořený v dashboardu (nemá klíč, jehož tajný kód webhooku by mohl webhooky podepsat).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "SCHEDULE_LIMIT_REACHED nebo ON_CHANGE_REQUIRES_PLAN. EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená (obnovení pozastaveného automatického záznamu; pozastavení a úpravy zůstávají povolené). PLAN_API_READ_ONLY: klíč API účtu Website Archive, u každého PATCH (včetně pozastavení a úprav). PLAN_API_READ_ONLY s details.reason \"session_outside_dashboard\": relace dashboardu účtu Website Archive, jejíž požadavek nemá hlavičku Origin nebo má takovou, která není adresou dashboardu ProofSnap (novou práci lze na tomto plánu vytvářet jen v dashboardu; jde o měkkou bránu, ne o bezpečnostní hranici). PLAN_ARCHIVE_ONLY: obnovení automatického záznamu na plánu Archive only.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "SCHEDULE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "SSRF_BLOCKED: url nebo webhook_url míří na privátní, loopback, link-local nebo jinak blokovanou adresu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Automatické záznamy"
        ],
        "operationId": "deleteSchedule",
        "summary": "Smazání automatického záznamu",
        "description": "Zastaví budoucí spuštění. Již pořízené záznamy zůstávají.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Smazáno.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "schedule_id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "PLAN_API_READ_ONLY: klíč API účtu Website Archive (jeho klíč je jen pro čtení; použijte dashboard).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "SCHEDULE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/scheduled-captures/{schedule_id}/runs": {
      "parameters": [
        {
          "$ref": "#/components/parameters/ScheduleId"
        }
      ],
      "get": {
        "tags": [
          "Automatické záznamy"
        ],
        "operationId": "listScheduleRuns",
        "summary": "Výpis běhů automatického záznamu",
        "description": "50 nejnovějších záznamů pořízených tímto automatickým záznamem (kontroly on_change, které nezjistily změnu, se neuvádějí).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Běhy.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "schedule_id": {
                      "type": "string"
                    },
                    "runs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "capture_id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "captured_at": {
                            "type": "string",
                            "nullable": true
                          },
                          "file_count": {
                            "type": "integer",
                            "nullable": true
                          }
                        }
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "SCHEDULE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/matters": {
      "get": {
        "tags": [
          "Spisy"
        ],
        "operationId": "listMatters",
        "summary": "Výpis spisů",
        "description": "Až 200 spisů, jejichž jste členem. Spisy firmy, kterou jste opustili, se neuvádějí.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Spisy.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matters": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Matter"
                      }
                    },
                    "total": {
                      "type": "integer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED: tarif není tarifem Legal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Spisy"
        ],
        "operationId": "createMatter",
        "summary": "Vytvoření spisu",
        "description": "Stanete se jeho vlastníkem. Protokol úschovy začíná položkou matter.created. Textová pole se oříznou o okrajové mezery a zkrátí na 200 znaků.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Prostý text: bílé znaky se sloučí a ořežou, nejvýše 200 znaků, žádné řídicí, směrové (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). Povinné. Zobrazuje se na veřejné stránce ověření spisu."
                  },
                  "client": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Prostý text: bílé znaky se sloučí a ořežou, nejvýše 200 znaků, žádné řídicí, směrové (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). Prázdná hodnota nebo null znamená nenastaveno (uloží se jako null). Hodnota, která není řetězec, se odmítne.",
                    "nullable": true
                  },
                  "case_number": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Prostý text: bílé znaky se sloučí a ořežou, nejvýše 200 znaků, žádné řídicí, směrové (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). Prázdná hodnota nebo null znamená nenastaveno (uloží se jako null). Hodnota, která není řetězec, se odmítne. Zobrazuje se na veřejné stránce ověření spisu.",
                    "nullable": true
                  },
                  "opposing_party": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Prostý text: bílé znaky se sloučí a ořežou, nejvýše 200 znaků, žádné řídicí, směrové (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). Prázdná hodnota nebo null znamená nenastaveno (uloží se jako null). Hodnota, která není řetězec, se odmítne.",
                    "nullable": true
                  },
                  "jurisdiction": {
                    "type": "string",
                    "description": "Volný text. Prostý text: mezery se sloučí a oříznou, nejvýše 200 znaků, žádné řídicí znaky, znaky směru textu (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). Prázdná hodnota nebo null znamená nenastaveno (uloží se null). Hodnota, která není řetězec, se odmítne. Zobrazuje se na veřejné stránce ověření spisu.",
                    "maxLength": 200,
                    "nullable": true
                  }
                },
                "required": [
                  "name"
                ]
              },
              "example": {
                "name": "Smith v. Jones",
                "case_number": "2026-CV-0142"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Vytvořeno.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Matter"
                }
              }
            }
          },
          "400": {
            "description": "MISSING_FIELD: name chybí nebo je prázdné. MALFORMED_REQUEST: neplatný JSON. MALFORMED_REQUEST: textové pole, které není řetězec, je delší než 200 znaků nebo obsahuje řídicí znaky či znaky pro směr textu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED: ostrý volající, jehož předplatné (nebo firma) je po splatnosti nebo nezaplacené."
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED: tarif není tarifem Legal. EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená, nebo klíč API takového účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/matters/{matter_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MatterId"
        }
      ],
      "get": {
        "tags": [
          "Spisy"
        ],
        "operationId": "getMatter",
        "summary": "Získání spisu",
        "description": "Spis s jeho záznamy (až 500), protokolem úschovy a až 100 událostmi přístupu. `members` uvádí e-mail každé položky `member_uids` a `actor_emails` přiřazuje uid uvedeným v protokolu úschovy a audit_stream tohoto spisu (aktéři a cíl `member.added` / `member.removed`, tedy i odebraní členové) jejich e-mail; e-mail je null, nebo uid v mapě chybí, když ho nelze přečíst. Tato pole dostávají jen volající, kteří mohou spis otevřít; `/matter-verify` e-maily nikdy neobsahuje. Volající, který smí zrušit veřejný odkaz pro sdílení (vlastník spisu, vlastník ukončené nebo archivované firmy), dostane také `share`: `{ share_url, created_at, expires_at }` aktivního odkazu (`expires_at` je vždy null: odkazy fungují, dokud nejsou zrušeny), nebo null, když žádný není; ostatní členové toto pole nikdy nedostanou. Položky audit_stream obsahují source_ip a user_agent jen pro vlastníka spisu; členové dostávají položky bez těchto dvou polí.\n\nSpis firmy, která skončila, nese `read_only: true`.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Spis.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "allOf": [
                    {
                      "$ref": "#/components/schemas/Matter"
                    },
                    {
                      "type": "object",
                      "properties": {
                        "members": {
                          "type": "array",
                          "description": "Jedna položka pro každou položku `member_uids`, ve stejném pořadí.",
                          "items": {
                            "type": "object",
                            "properties": {
                              "uid": {
                                "type": "string"
                              },
                              "email": {
                                "type": "string",
                                "format": "email",
                                "nullable": true,
                                "description": "Null, pokud účet nelze načíst."
                              }
                            }
                          }
                        },
                        "actor_emails": {
                          "type": "object",
                          "description": "`{ uid: email }` pro osoby uvedené v custody_log a audit_stream tohoto spisu (bez aktéra system). uid, jehož e-mail nelze přečíst, chybí.",
                          "additionalProperties": {
                            "type": "string",
                            "format": "email"
                          }
                        },
                        "captures": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/MatterCapture"
                          }
                        },
                        "custody_log": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/CustodyEntry"
                          }
                        },
                        "audit_stream": {
                          "type": "array",
                          "items": {
                            "$ref": "#/components/schemas/AuditEntry"
                          }
                        },
                        "share": {
                          "type": "object",
                          "nullable": true,
                          "description": "Jen pro volajícího, který smí odkaz zrušit. Null, pokud neexistuje aktivní odkaz.",
                          "properties": {
                            "share_url": {
                              "type": "string",
                              "format": "uri"
                            },
                            "created_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true
                            },
                            "expires_at": {
                              "type": "string",
                              "format": "date-time",
                              "nullable": true,
                              "description": "Vždy null: odkazy ke sdílení nevyprší."
                            }
                          }
                        }
                      }
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED: tarif není tarifem Legal.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "patch": {
        "tags": [
          "Spisy"
        ],
        "operationId": "updateMatter",
        "summary": "Aktualizace spisu",
        "description": "Jen pro vlastníka. Textová pole se ořežou a zkrátí na 200 znaků. name je povinné: pokud se pošle, musí to být neprázdný řetězec; prázdný název, název jen z bílých znaků, null nebo hodnota jiného typu než řetězec se odmítne s 400 a nic se nezmění. Členové: add_member_email přidá osobu, která už má účet ProofSnap a patří do firmy spisu; neexistující účet, nepotvrzená adresa i účet mimo firmu dostanou stejnou odpověď 404 NOT_FOUND; remove_member_uid odebere člena (ne vlastníka). Pokud se pošlou obě pole, použije se jen add_member_email. Spis má nejvýše 50 členů (plný spis požadavek odmítne ještě před vyhledáním adresy). Změny členů se zapisují do protokolu úschovy. Změna name, client, case_number, opposing_party, jurisdiction nebo status se do protokolu úschovy zapíše jako matter.updated; jeho target je řetězec JSON s fields (názvy změněných polí) a při změně stavu i s novým status. Volné textové hodnoty se do hashovaného veřejného protokolu úschovy nezapisují: staré a nové hodnoty jdou do protokolu přístupů (audit_stream, položka matter.updated). U archivovaného spisu se přejmenování nebo add_member_email odmítne s 409 MATTER_ARCHIVED, pokud ho tentýž požadavek znovu neotevře (status \"open\"); remove_member_uid a znovuotevření fungují dál. Každá pozvánka se započítává do denního limitu 50 na zvoucího vlastníka (pozvánky do firmy z dashboardu a add_member_email u spisů dohromady, včetně odmítnutých, protože každá vyhledává adresu); po dosažení limitu vrátí požadavek 429 RATE_LIMITED. Chyba na straně serveru se nepočítá.\n\nPrávní blokace: `{ \"legal_hold\": true|false }` samotné nastaví právní blokaci spisu (jen vlastník spisu) a ve stejném požadavku ji použije na jeho záznamy, se stejnými účinky jako blokace záznamu (právní blokace S3 Object Lock, položky řetězce úschovy capture.legal_hold_placed / capture.legal_hold_released, řetězec událostí záznamu). Odpovědí je spis plus `changed` (příznak se změnil), `captures_held` nebo `captures_released`, `skipped` ([{ capture_id, code }], např. záznam v koši) a `truncated` (víc než 1000 záznamů: pokračujte opětovným odesláním stejné hodnoty). Záznamy přiřazené do spisu později, dokud blokace trvá, se zablokují při přiřazení. Jedna jednotka limitu počtu požadavků za požadavek plus jedna za každých 10 změněných záznamů.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Musí obsahovat alespoň jeden znak, který není bílý. Pokud ho vynecháte, zůstane současný název. Platí stejné pravidlo pro prostý text: bílé znaky se sloučí, nejvýše 200 znaků, žádné řídicí, směrové ani neviditelné znaky (U+200C a U+200D jsou povoleny).",
                    "maxLength": 200
                  },
                  "client": {
                    "type": "string",
                    "nullable": true,
                    "description": "Prostý text: bílé znaky se sloučí a ořežou, nejvýše 200 znaků, žádné řídicí, směrové (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). null nebo řetězec jen z bílých znaků pole vymaže (uloží se jako null). Hodnota, která není řetězec, se odmítne s 400.",
                    "maxLength": 200
                  },
                  "case_number": {
                    "type": "string",
                    "nullable": true,
                    "description": "Prostý text: bílé znaky se sloučí a ořežou, nejvýše 200 znaků, žádné řídicí, směrové (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). null nebo řetězec jen z bílých znaků pole vymaže (uloží se jako null). Hodnota, která není řetězec, se odmítne s 400.",
                    "maxLength": 200
                  },
                  "opposing_party": {
                    "type": "string",
                    "nullable": true,
                    "description": "Prostý text: bílé znaky se sloučí a ořežou, nejvýše 200 znaků, žádné řídicí, směrové (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). null nebo řetězec jen z bílých znaků pole vymaže (uloží se jako null). Hodnota, která není řetězec, se odmítne s 400.",
                    "maxLength": 200
                  },
                  "jurisdiction": {
                    "type": "string",
                    "nullable": true,
                    "description": "Prostý text: bílé znaky se sloučí a ořežou, nejvýše 200 znaků, žádné řídicí, směrové (bidi) ani neviditelné znaky (spojovače U+200C a U+200D, které potřebuje pravopis hindštiny a perštiny, jsou povoleny) (jinak 400 MALFORMED_REQUEST). null nebo řetězec jen z bílých znaků pole vymaže (uloží se jako null). Hodnota, která není řetězec, se odmítne s 400.",
                    "maxLength": 200
                  },
                  "status": {
                    "type": "string",
                    "description": "K zapečetění použijte POST /matters/{matter_id}/seal.",
                    "enum": [
                      "open",
                      "archived"
                    ]
                  },
                  "add_member_email": {
                    "type": "string",
                    "format": "email"
                  },
                  "remove_member_uid": {
                    "type": "string"
                  },
                  "legal_hold": {
                    "type": "boolean",
                    "description": "Právní blokace spisu, posílá se samostatně (v kombinaci s jiným polem: 400). true zablokuje všechny současné záznamy spisu a každý záznam, který je do spisu přiřazen, dokud blokace trvá (legal_hold_source \"matter:<id>\"; záznam, který už blokaci má, si ponechá vlastní). false zruší jen blokace, které nastavil spis; ruční nebo hromadná blokace zůstává. Jen pro vlastníka spisu. Nevadí ani předplatné po splatnosti. Nastavení vyžaduje placený plán (403 LEGAL_HOLD_NOT_AVAILABLE, details.reason plan) a záznamy v testovacím režimu se přeskakují (kód LEGAL_HOLD_NOT_AVAILABLE ve `skipped`); samotné false se přijímá i po skončení plánu Legal."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Aktualizovaný spis.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Matter"
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: name je prázdné, obsahuje jen mezery nebo není řetězec; textové pole, které není řetězec, je delší než 200 znaků nebo obsahuje řídicí znaky či znaky směru textu; neplatný status; není co aktualizovat; uživatel už je členem; nebo odebrání vlastníka.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED: ostrý volající, jehož předplatné (nebo firma) je po splatnosti nebo nezaplacené."
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED, FORBIDDEN (nejste vlastník), LEGAL_HOLD_NOT_AVAILABLE (legal_hold true bez placeného tarifu) nebo EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená, nebo klíč API takového účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND nebo NOT_FOUND (pro e-mail neexistuje způsobilý účet: žádný, nepotvrzený nebo mimo firmu, ve všech případech stejná odpověď; nebo remove_member_uid není člen).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "MATTER_SEALED nebo MATTER_ARCHIVED (přejmenování nebo nový člen u archivovaného spisu). COMPANY_READ_ONLY: spis patří firmě, jejíž účet skončil nebo je uchováván jako archiv firmy (volající má plán Legal; otevření, export a zrušení sdílení dál fungují).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED: byl dosažen denní limit 50 pozvánek členů na jednoho zvoucího vlastníka (pozvánky do firmy z dashboardu a add_member_email u spisu se sčítají; details.daily_limit, details.action \"member_invite\"). Retry-After udává, kdy končí den v UTC.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/matters/{matter_id}/captures": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MatterId"
        }
      ],
      "post": {
        "tags": [
          "Spisy"
        ],
        "operationId": "assignMatterCaptures",
        "summary": "Přidat nebo odebrat záznamy",
        "description": "Volat může kterýkoli člen, přesunou se ale jen záznamy, které volající vytvořil; ostatní se vrátí v skipped, stejně jako záznamy, které už jsou v jiném spisu, a záznamy, které už v tomto spisu jsou (nebo s unassign v něm nejsou). Položky, které nejsou ID záznamů, se ignorují a zpracuje se nejvýše 100. Každá změna se zapíše do protokolu řetězce úschovy. Archivovaný spis nepřijímá nové záznamy (409 MATTER_ARCHIVED); unassign funguje dál.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "capture_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "minItems": 1,
                    "maxItems": 100
                  },
                  "unassign": {
                    "type": "boolean",
                    "description": "true odebere záznamy ze spisu.",
                    "default": false
                  }
                },
                "required": [
                  "capture_ids"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Výsledek.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matter_id": {
                      "type": "string"
                    },
                    "assigned": {
                      "type": "integer",
                      "description": "Počet změněných záznamů."
                    },
                    "skipped": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "unassign": {
                      "type": "boolean"
                    },
                    "legal_holds_placed": {
                      "type": "integer",
                      "description": "Uvádí se, když je zapnutá právní blokace spisu: u kolika přiřazených záznamů nastavila blokaci."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: žádné platné ID záznamu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED: ostrý volající, jehož předplatné (nebo firma) je po splatnosti nebo nezaplacené."
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED nebo EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená, nebo klíč API takového účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "MATTER_SEALED nebo MATTER_ARCHIVED (přidání do archivovaného spisu). COMPANY_READ_ONLY: spis patří firmě, která skončila nebo je uchovávána jako firemní archiv (volající na tarifu Legal; otevření, export a zrušení sdílení dál fungují).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/matters/{matter_id}/seal": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MatterId"
        }
      ],
      "post": {
        "tags": [
          "Spisy"
        ],
        "operationId": "sealMatter",
        "summary": "Zapečetit spis",
        "description": "Jen pro vlastníka. Ukotví aktuální hash hlavy řetězce úschovy přes OpenTimestamps, a pokud má nasazení nakonfigurovaný eIDAS a volající je ostrý (ostrý klíč API nebo relace dashboardu s propojenou fakturací), také eIDAS časovým razítkem (eIDAS časové razítko pečeti se neúčtuje; pokud selže, zapečetění proběhne bez něj). Testovací volající (testovací klíč API nebo relace sandboxu) se zapečetí jen přes OpenTimestamps a pečeť zaznamená eidas_status not_obtained s eidas_reason test_key; požadavek nemá žádnou volbu eIDAS, takže nejde o chybu. Spis se pak stane jen pro čtení: žádné úpravy, žádné změny záznamů a jeho záznamy nelze smazat. Spis, který má záznam v koši, se nezapečetí (409 MATTER_HAS_TRASHED_CAPTURES): záznam nejprve obnovte nebo ho ze spisu odeberte.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Zapečetěno.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matter_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "sealed"
                      ]
                    },
                    "seal": {
                      "$ref": "#/components/schemas/MatterSeal"
                    },
                    "custody_head_hash": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: spis nemá hlavu řetězce úschovy.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED: ostrý volající, jehož předplatné (nebo firma) je po splatnosti nebo nezaplacené."
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED: tarif není tarifem Legal. FORBIDDEN: nejste vlastník. EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená, nebo klíč API takového účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "MATTER_SEALED (už zapečetěný), MATTER_CHANGED (log řetězce úschovy se během pečetění změnil; opakujte) nebo MATTER_HAS_TRASHED_CAPTURES (některý záznam spisu je v koši; nejdřív ho obnovte nebo ho ze spisu odeberte). COMPANY_READ_ONLY: spis patří firmě, která skončila nebo je uchovávána jako firemní archiv (volající na tarifu Legal; otevření, export a zrušení sdílení dál fungují).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "TIMESTAMP_SERVICE_UNAVAILABLE (ukotvení selhalo, nic se nezměnilo; opakujte) nebo CONFIGURATION_ERROR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "EIDAS_SEAL_RETRY: časové razítko eIDAS pro zapečetění nedorazilo včas (nebo se ještě vydává). Nic nebylo zapečetěno. Zopakujte požadavek po uplynutí Retry-After sekund: opakovaný pokus dostane časové razítko již vydané pro tuto hlavu řetězce úschovy, žádné druhé razítko. SERVICE_UNAVAILABLE: brána nemohla ověřit přihlašovací údaje; opakujte s postupně prodlužovaným odstupem.",
            "headers": {
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": {
                    "code": "EIDAS_SEAL_RETRY",
                    "message": "The eIDAS timestamp of the seal did not arrive in time. Nothing was sealed. Retry after the Retry-After interval; the retry reuses the timestamp already issued for this custody head.",
                    "details": {
                      "reason": "The eIDAS timestamp did not arrive in time. Nothing was sealed. Retry the seal.",
                      "retry_after_seconds": 15
                    }
                  },
                  "request_id": "..."
                }
              }
            }
          }
        }
      }
    },
    "/matters/{matter_id}/export": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MatterId"
        }
      ],
      "post": {
        "tags": [
          "Spisy"
        ],
        "operationId": "exportMatter",
        "summary": "Export spisu",
        "description": "Jen pro vlastníka. Vytvoří jeden ZIP s custody_report.pdf, custody_log.json, matter.json, README.txt, access_log.json (pokud existují události přístupu) a balíčkem důkazů každého záznamu. Se zapnutým Batesovým číslováním (výchozí) přidá do exhibits/ kopie každého evidence.pdf s Batesovým razítkem (přílohy číslované od nejstaršího důkazu) a s formats.loadfile i load file pro Concordance/Opticon. S formats.pdfa se kopie pro podání navíc převedou do PDF/A, pokud je převodník k dispozici (u synchronního exportu jen v rámci časového rozpočtu); PDF/A jsou jen kopie započtené v pdfa_count, ostatní jsou PDF, která si PDF/A nenárokují, a README.txt zmiňuje PDF/A jen tehdy, když je pdfa_count větší než 0.\n\nSpis s nejvýše 20 záznamy se exportuje synchronně (200). Větší spis se exportuje na pozadí: odpověď je 202 s job_id; stav zjišťujte přes GET /matters/{matter_id}/export?job_id=. Záznamy, které se nevejdou do limitu velikosti (120 MB synchronně; 800 MB a 300 záznamů na pozadí), jsou uvedeny ve zprávách, ale do balíčku se nepřidají.\n\nFunguje u otevřených i zapečetěných spisů. Archivovaný spis se odmítne s 409 MATTER_ARCHIVED (nejprve ho znovu otevřete), s výjimkou volajícího, který ho znovu otevřít nemůže: vlastníka ukončené firmy po dobu uchovávání a účtu Archive only. Každý export se v protokolu přístupů zaznamená jako export.generated. Každý export se započítává do denního limitu 50 na uživatele; export na pozadí, který selže, svou jednotku vrátí.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "bates": {
                    "type": "object",
                    "properties": {
                      "enabled": {
                        "type": "boolean",
                        "default": true
                      },
                      "prefix": {
                        "type": "string",
                        "description": "Pouze písmena a číslice, velkými písmeny, nejvýše 12. Výchozí: odvozeno ze spisové značky nebo z názvu spisu."
                      },
                      "start": {
                        "type": "integer",
                        "minimum": 1,
                        "default": 1
                      },
                      "exhibit_start": {
                        "type": "integer",
                        "minimum": 1,
                        "default": 1
                      },
                      "pad": {
                        "type": "integer",
                        "minimum": 4,
                        "maximum": 8,
                        "default": 6
                      }
                    }
                  },
                  "formats": {
                    "type": "object",
                    "properties": {
                      "loadfile": {
                        "type": "boolean",
                        "description": "Zahrne load file pro e-discovery (vyžaduje číslování Bates).",
                        "default": true
                      },
                      "pdfa": {
                        "type": "boolean",
                        "description": "Převést kopie k podání opatřené Batesovým číslováním do PDF/A (vyžaduje Batesovo číslování). Podle možností: kopie, kterou se nepodaří převést, zůstane PDF bez deklarace PDF/A; pdfa_count v odpovědi uvádí, kolik kopií bylo převedeno.",
                        "default": true
                      }
                    }
                  },
                  "export_locale": {
                    "type": "string",
                    "description": "Jazyk custody_report.pdf, rejstříku příloh a README.txt: en, de, it, fr, es, pt_BR, cs, el, hi, hu, id, ja, ko, nl, pl, ro, ru, sv, tr, vi, zh_CN, zh_TW, ar, he, da, fi, nb, sk, uk (místo podtržítka se přijímá i spojovník). Při jiných hodnotách se použije angličtina."
                  },
                  "declaration": {
                    "type": "object",
                    "description": "Přijímá se kvůli kompatibilitě. Jeho textová pole (name, title, party, case_caption, executed_location) se řídí pravidlem pro prostý text (viz PlainText): hodnota se zakázaným znakem se odmítne s 400 MALFORMED_REQUEST. Příliš dlouhé hodnoty se zkrátí (name, title, executed_location na 120, party na 160, case_caption na 200 znaků)."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Export je připraven.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matter_id": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string",
                      "description": "Předem podepsaný odkaz ke stažení, platný 24 hodin.",
                      "format": "uri"
                    },
                    "expires_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "capture_count": {
                      "type": "integer"
                    },
                    "captures_included": {
                      "type": "integer"
                    },
                    "captures_skipped": {
                      "type": "integer",
                      "description": "Záznamy uvedené ve zprávách, ale nepřibalené, protože byl dosažen limit velikosti."
                    },
                    "custody_events": {
                      "type": "integer"
                    },
                    "exhibits_count": {
                      "type": "integer",
                      "description": "Kopie příloh s Batesovým číslováním."
                    },
                    "bates_prefix": {
                      "type": "string",
                      "nullable": true
                    },
                    "searchable": {
                      "type": "boolean",
                      "description": "Vždy false: do kopií pro podání se nepřidává žádná textová vrstva. Ponecháno kvůli stálému tvaru odpovědi."
                    },
                    "pdfa_count": {
                      "type": "integer",
                      "description": "Kopie pro podání ve složce exhibits/, které jsou ve formátu PDF/A. 0 znamená, že žádná kopie není PDF/A a žádná to o sobě netvrdí."
                    },
                    "loadfile": {
                      "type": "boolean"
                    },
                    "size_bytes": {
                      "type": "integer"
                    },
                    "generated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Export byl spuštěn na pozadí.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matter_id": {
                      "type": "string"
                    },
                    "async": {
                      "type": "boolean"
                    },
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing"
                      ]
                    },
                    "poll_path": {
                      "type": "string",
                      "description": "Zahrnuje stage /v1."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: některá volba exportu je neplatná (details.reason).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED: ostrý volající, jehož předplatné (nebo firma) je po splatnosti nebo nezaplacené."
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED: tarif není tarifem Legal. FORBIDDEN: nejste vlastník. EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená, nebo klíč API takového účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "MATTER_ARCHIVED: nejdřív spis znovu otevřete (PATCH status \"open\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "CONFIGURATION_ERROR: export se nepodařilo sestavit ani spustit.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          },
          "504": {
            "description": "UPSTREAM_TIMEOUT: synchronní export nebyl dokončen zhruba do 25 s (details.reason). Opakujte.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Spisy"
        ],
        "operationId": "getMatterExport",
        "summary": "Zjištění stavu exportu na pozadí",
        "description": "Jen pro vlastníka. Úloha, která se zpracovává ještě 30 minut po spuštění, se hlásí jako failed s chybou \"export timed out\". Úloha skončí jen jednou: úloha nahlášená jako failed se později nikdy nezmění na ready a úloha ve stavu ready se nikdy nenahlásí jako failed.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stav úlohy. Jakmile je připravena, vyplní se url a počty.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing",
                        "ready",
                        "failed"
                      ]
                    },
                    "url": {
                      "type": "string",
                      "nullable": true
                    },
                    "captures_included": {
                      "type": "integer",
                      "nullable": true
                    },
                    "captures_skipped": {
                      "type": "integer",
                      "nullable": true
                    },
                    "custody_events": {
                      "type": "integer",
                      "nullable": true
                    },
                    "size_bytes": {
                      "type": "integer",
                      "nullable": true
                    },
                    "error": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: chybí job_id.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED: tarif není tarifem Legal. FORBIDDEN: nejste vlastník.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND nebo NOT_FOUND pro neznámou úlohu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/matters/{matter_id}/share": {
      "parameters": [
        {
          "$ref": "#/components/parameters/MatterId"
        }
      ],
      "post": {
        "tags": [
          "Spisy"
        ],
        "operationId": "shareMatter",
        "summary": "Vytvoření veřejného odkazu k ověření",
        "description": "Jen pro vlastníka. Vrátí odkaz, přes který kdokoli zobrazí název spisu, spisovou značku, jurisdikci, stav, protokol úschovy a pečeť (viz GET /matter-verify). Obsah záznamů se nesdílí. Opakované volání vrátí stejný odkaz. Odkaz funguje, dokud ho nezrušíte.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Odkaz pro sdílení.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matter_id": {
                      "type": "string"
                    },
                    "share_url": {
                      "type": "string",
                      "format": "uri"
                    },
                    "token": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED: ostrý volající, jehož předplatné (nebo firma) je po splatnosti nebo nezaplacené."
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED: tarif není tarifem Legal. FORBIDDEN: nejste vlastník. EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená, nebo klíč API takového účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "MATTER_ARCHIVED: archivovaný spis se nesdílí. COMPANY_READ_ONLY: spis patří firmě, která skončila nebo je uchovávána jako firemní archiv (volající na tarifu Legal; otevření, export a zrušení sdílení dál fungují).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Spisy"
        ],
        "operationId": "revokeMatterShare",
        "summary": "Zneplatnit veřejný odkaz",
        "description": "Jen pro vlastníka. Odkaz přestane fungovat. Pozdější POST vytvoří nový. Vlastník ukončené firmy (nebo firmy uchovávané jako archiv firmy) a vlastník spisu v plánu Archive only mohou odkaz zrušit i bez plánu Legal (vytvoření odkazu zůstává funkcí plánu Legal).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Zneplatněno.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matter_id": {
                      "type": "string"
                    },
                    "revoked": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED: ostrý volající, jehož předplatné (nebo firma) je po splatnosti nebo nezaplacené."
          },
          "403": {
            "description": "MATTERS_NOT_ENABLED, FORBIDDEN (nejste vlastník) nebo EMAIL_NOT_VERIFIED: relace dashboardu, jejíž e-mailová adresa není potvrzená, nebo klíč API takového účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/health": {
      "get": {
        "tags": [
          "Veřejné"
        ],
        "operationId": "health",
        "summary": "Kontrola stavu",
        "description": "Vždy 200, dokud API odpovídá. S deep=1 (nebo true) přidá odpověď dependencies: zda je každá navazující služba nakonfigurovaná, a u eIDAS živý test služby časových razítek. Testuje se pouze eIDAS; ostatní hlásí jen konfiguraci. status přejde na degraded, když je eIDAS nakonfigurovaný a jeho test selže. Test, který neodpoví včas, se hlásí v dependencies (probe_timeout nebo eidas.error timeout), nikdy jako neúspěšné /health. deep=1 má limit počtu požadavků na IP adresu klienta (10 za minutu): po jeho překročení vrátí požadavek 429 RATE_LIMITED s Retry-After.",
        "security": [],
        "parameters": [
          {
            "name": "deep",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "1",
                "true"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stav.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "ok",
                        "degraded"
                      ]
                    },
                    "stage": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "uptime_ms": {
                      "type": "integer",
                      "description": "Milisekundy od spuštění obsluhující instance."
                    },
                    "version": {
                      "type": "string"
                    },
                    "dependencies": {
                      "type": "object",
                      "properties": {
                        "eidas": {
                          "type": "object",
                          "properties": {
                            "configured": {
                              "type": "boolean"
                            },
                            "healthy": {
                              "type": "boolean",
                              "description": "null, pokud není nakonfigurováno.",
                              "nullable": true
                            },
                            "error": {
                              "type": "string",
                              "description": "Pevný kód, pokud kontrola eIDAS nehlásila, že je služba v pořádku: timeout (žádná odpověď do 15 s), unavailable (služba časových razítek odpověděla, že není v pořádku), error (kontrolu nebylo možné spustit). Podrobnosti se zapisují do logu na serveru, nikdy se nevracejí.",
                              "enum": [
                                "timeout",
                                "unavailable",
                                "error"
                              ]
                            }
                          }
                        },
                        "ots": {
                          "type": "object",
                          "properties": {
                            "configured": {
                              "type": "boolean"
                            }
                          }
                        },
                        "c2pa_sign": {
                          "type": "object",
                          "properties": {
                            "configured": {
                              "type": "boolean"
                            }
                          }
                        },
                        "ntp": {
                          "type": "object",
                          "properties": {
                            "configured": {
                              "type": "boolean"
                            }
                          }
                        },
                        "whois": {
                          "type": "object",
                          "properties": {
                            "configured": {
                              "type": "boolean"
                            }
                          }
                        },
                        "error": {
                          "type": "string",
                          "description": "Jen pokud selhala samotná kontrola závislostí: probe_timeout, pokud neodpověděla do 20 s, jinak probe_failed. Odpověď je přesto 200."
                        }
                      },
                      "description": "Jen s deep=1."
                    }
                  }
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/ledger/{hash}": {
      "get": {
        "tags": [
          "Veřejné"
        ],
        "operationId": "ledgerLookup",
        "summary": "Vyhledání hashe manifestu",
        "description": "Ověří, zda ProofSnap zaznamenal vydání balíčku, jehož manifest.json má tento SHA-256. Záznamy, certifikáty, porovnání a začernění se evidují při vydání, s hashem manifestu, který je v dodaném balíčku (po kroku kvalifikovaného časového razítka); balíčky vydané dříve, než registr vznikl, v něm nejsou. issued: false znamená pouze, že o vydání neexistuje žádný údaj.",
        "security": [],
        "parameters": [
          {
            "name": "hash",
            "in": "path",
            "required": true,
            "description": "SHA-256 souboru manifest.json, 64 hexadecimálních znaků, libovolná velikost písmen, volitelně s předponou sha256:.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Výsledek vyhledání.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "manifest_sha256": {
                      "type": "string"
                    },
                    "issued": {
                      "type": "boolean"
                    },
                    "issued_at": {
                      "type": "string",
                      "nullable": true,
                      "format": "date-time",
                      "description": "Chybí, když je issued false."
                    },
                    "type": {
                      "type": "string",
                      "enum": [
                        "capture",
                        "certify",
                        "compare",
                        "redaction"
                      ],
                      "nullable": true,
                      "description": "Chybí, když je issued false."
                    },
                    "eidas": {
                      "type": "boolean",
                      "nullable": true,
                      "description": "Zda vydaný balíček nese kvalifikované časové razítko eIDAS (manifest.json.tsr). Chybí, když je issued false; null u položek zapsaných před 2026-10-01."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND: hash nemá 64 hexadecimálních znaků.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/matter-verify": {
      "get": {
        "tags": [
          "Veřejné"
        ],
        "operationId": "matterVerify",
        "summary": "Veřejné zobrazení sdíleného spisu",
        "description": "Data jen pro čtení za odkazem pro sdílení spisu: údaje o spisu, log řetězce úschovy (aby bylo možné řetězec hashů přepočítat) a pečeť s důkazem OpenTimestamps a tokenem eIDAS. Žádný obsah záznamů, odkazy ke stažení ani log přístupů. attested_by.organization je název firmy, které spis patří (firemní spis), jak ho nastavil vlastník, nebo null; osobní spis žádnou organizaci neuvádí. custody_log[].actor_org je firma, ke které aktér patřil v době zápisu dané položky (zaznamenáno s položkou, mimo hashovaný obsah), jen u firemního spisu; položky zapsané dříve, než se to začalo zaznamenávat, ukazují null. Limit počtu požadavků platí na IP adresu klienta (výchozí 30 požadavků za 60 sekund).",
        "security": [],
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[A-Za-z0-9_-]{16,64}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Zobrazení spisu.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "matter": {
                      "type": "object",
                      "properties": {
                        "name": {
                          "type": "string"
                        },
                        "case_number": {
                          "type": "string",
                          "nullable": true
                        },
                        "jurisdiction": {
                          "type": "string",
                          "nullable": true
                        },
                        "status": {
                          "type": "string"
                        },
                        "sealed": {
                          "type": "boolean"
                        },
                        "attested_by": {
                          "type": "object",
                          "properties": {
                            "organization": {
                              "type": "string",
                              "nullable": true
                            }
                          }
                        },
                        "capture_count": {
                          "type": "integer"
                        },
                        "custody_count": {
                          "type": "integer"
                        },
                        "custody_head_hash": {
                          "type": "string",
                          "nullable": true
                        },
                        "seal": {
                          "type": "object",
                          "properties": {
                            "root_hash": {
                              "type": "string"
                            },
                            "ots_present": {
                              "type": "boolean"
                            },
                            "eidas_present": {
                              "type": "boolean"
                            },
                            "ots_hex": {
                              "type": "string",
                              "nullable": true
                            },
                            "ots_pending": {
                              "type": "boolean"
                            },
                            "tsr_base64": {
                              "type": "string",
                              "nullable": true
                            },
                            "eidas_serial": {
                              "type": "string",
                              "nullable": true
                            },
                            "eidas_issued_at": {
                              "type": "string",
                              "nullable": true
                            },
                            "eidas_ltv": {
                              "type": "boolean"
                            },
                            "sealed_at": {
                              "type": "string"
                            },
                            "eidas_status": {
                              "type": "string",
                              "enum": [
                                "confirmed",
                                "not_obtained",
                                "not_configured"
                              ],
                              "nullable": true,
                              "description": "null u zapečetění provedených před 2026-10-01 bez tokenu eIDAS."
                            },
                            "eidas_reason": {
                              "type": "string",
                              "enum": [
                                "token_refused",
                                "unavailable",
                                "test_key",
                                "account_limit"
                              ],
                              "description": "Jen pokud je eidas_status not_obtained. test_key: pečeť vytvořil testovací volající, takže se eIDAS časové razítko nežádalo. account_limit: účet ještě nemá zaplacenou fakturu a dosáhl svého limitu eIDAS (20 za den UTC, 50 za měsíc UTC), takže se eIDAS časové razítko nežádalo."
                            },
                            "eidas_verification_status": {
                              "type": "string",
                              "nullable": true,
                              "description": "verified, pokud token při zapečetění prošel kontrolou ProofSnap."
                            },
                            "eidas_revocation_status": {
                              "type": "string",
                              "nullable": true,
                              "enum": [
                                "good",
                                "revoked_after_gen_time",
                                "unknown",
                                "not_checked",
                                null
                              ],
                              "description": "Stav certifikátu TSA zjištěný při zapečetění (nezjišťuje se online)."
                            },
                            "eidas_validation": {
                              "type": "object",
                              "nullable": true,
                              "additionalProperties": true,
                              "description": "Obsah eidas_validation.json zaznamenaný při zapečetění (řetězec TSA, připnutý kořen, odpověď OCSP, CRL, záznam o ověření), aby bylo možné token v tsr_base64 ověřit offline. null u starších zapečetění."
                            }
                          },
                          "nullable": true
                        },
                        "created_at": {
                          "type": "string"
                        }
                      }
                    },
                    "custody_log": {
                      "type": "array",
                      "items": {
                        "allOf": [
                          {
                            "$ref": "#/components/schemas/CustodyEntry"
                          },
                          {
                            "type": "object",
                            "properties": {
                              "actor_org": {
                                "type": "string",
                                "nullable": true
                              }
                            }
                          }
                        ]
                      }
                    },
                    "issuer": {
                      "type": "string",
                      "enum": [
                        "ProofSnap"
                      ]
                    },
                    "verified_at": {
                      "type": "string",
                      "nullable": true,
                      "description": "Vždy null."
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "NOT_FOUND: neplatný, neznámý nebo zneplatněný token.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/captures/export-jobs": {
      "post": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "startCaptureExportJob",
        "summary": "Export všech záznamů jako jednoho souboru ke stažení (asynchronní úloha)",
        "description": "Spustí úlohu, která zabalí všechny vaše záznamy do jednoho stažení, rozděleného na části o velikosti nejvýše zhruba 2 GB. Každá část je běžný ZIP: README.txt (anglicky) a README.<language>.txt (stejný text v překladu, když language není en; oba v UTF-8 se značkou pořadí bajtů a konci řádků CRLF; řádek 1 každého z nich odkazuje na druhý), captures.csv (UTF-8 se značkou pořadí bajtů, CRLF; každý záznam exportu se sloupci member (e-mail autora ve firemním exportu, ve vašem vlastním exportu prázdný), capture_id, created_at (kdy byl požadavek přijat), captured_at (okamžik pořízení; u neúspěšného záznamu prázdný), url, status (completed, failed nebo unavailable), export_part, file, ots_file (captures/<capture_id>.upgraded.ots, když tato část obsahuje důkaz, jinak prázdný), test_mode (true u záznamu pořízeného testovacím klíčem: s vodoznakem, nejde o důkaz) a note (proč balíček není zahrnut, také u každého řádku unavailable); stejný seznam je v každé části, a když se části liší, platí seznam z části s nejvyšším číslem) a captures/<capture_id>.zip, původní zapečetěný balíček důkazů bajt po bajtu, plus captures/<capture_id>.upgraded.ots, když je uložen povýšený důkaz OpenTimestamps. Každý vnitřní balíček se ověřuje samostatně svým verification/verify.sh nebo verify.ps1. Balíček větší než 2 GB se nezahrne (uvede se jako unavailable s poznámkou; stáhněte ho samostatně přes GET /captures/{capture_id}). Neúspěšné záznamy se uvádějí jen v captures.csv; záznamy v koši a vymazané záznamy se neexportují. Položky každé části nesou datum exportu (UTC, také jako pole rozšířeného časového údaje). Dotazujte se přes GET /captures/export-jobs/{job_id}, dokud status není ready. **Opětovné použití:** když je Váš poslední export připraven, má stejný rozsah (a org) i language, zbývá mu alespoň den z okna pro stažení, vaše oprávnění se nezměnila a od jeho naplánování nebyl žádný záznam přidán, dokončen, přesunut do koše, obnoven ani vymazán, požadavek vrátí 200 s touto úlohou (reused: true): nic se znovu nesestavuje a nespotřebuje se žádná denní jednotka. Novější připravený export stejného rozsahu nahradí předchozí (předchozí úloha přejde do stavu expired, expired_reason superseded). Kdo ho smí spustit: ostrý klíč API nebo relace dashboardu, na každém plánu včetně sandboxu, Archive only a klíčů jen pro čtení (Website Archive). Testovací klíč dostane 403 FORBIDDEN (export obsahuje ostré záznamy) a GET /captures/export-jobs/{job_id} vrací testovacímu klíči u každé úlohy 404 EXPORT_JOB_NOT_FOUND. Váš vlastní export (scope own) obsahuje vaše osobní záznamy a záznamy, které jste pořídili pro svou současnou firmu nebo firmu, kterou vlastníte, a to i přes klíč, dokud je tato firma běžícím firemním archivem (záznamy ostatních držitelů míst v archivu jsou dostupné jen přes relaci dashboardu). scope company (jen vlastník firmy, také u ukončené firmy v rámci jejího okna pro stažení; běžící firemní archiv jen přes relaci dashboardu) exportuje záznamy všech držitelů míst pořízené pro firmu a vaše vlastní, s e-mailem autora ve sloupci member. Jedna běžící úloha na účet (409 EXPORT_JOB_RUNNING ji uvádí), 5 spuštěných úloh na účet a den v UTC (neúspěšná úloha svou jednotku vrací, opětovně použitá žádnou nespotřebuje), minutový limit počtu požadavků vašeho plánu. Nejvýše 20 000 nejnovějších záznamů na úlohu (truncated).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "scope": {
                    "type": "string",
                    "enum": [
                      "own",
                      "company"
                    ],
                    "default": "own"
                  },
                  "org": {
                    "type": "string",
                    "description": "Se scope company: jedna z firem, které vlastníte (současná nebo poslední), pokud vlastníte obě."
                  },
                  "language": {
                    "type": "string",
                    "default": "en",
                    "description": "Jazyk překladu README: README.<language>.txt (úplný překlad) vedle anglického README.txt v každé části; en vytvoří jen README.txt. Jedna z hodnot: en, de, it, fr, es, pt_BR, cs, el, hi, hu, id, ja, ko, nl, pl, ro, ru, sv, tr, vi, zh_CN, zh_TW, ar, he, da, fi, nb, sk, uk. Velikost písmen, spojovník a region se tolerují (\"PT-BR\" je pt_BR); samotné \"pt\" a \"zh\" a cokoli jiného vrátí 400 MALFORMED_REQUEST. Hotový export se znovu použije jen pro stejný jazyk. Dashboard posílá jazyk svého rozhraní."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Váš připravený export je stále aktuální a použije se znovu: žádná nová úloha, žádná denní jednotka. Jeho odkazy načtete přes GET poll_path.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "job_id",
                    "status",
                    "scope",
                    "poll_path",
                    "reused"
                  ],
                  "properties": {
                    "job_id": {
                      "type": "string",
                      "example": "cexp_3Fh8sKq0aZr2LmN1"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "ready"
                      ]
                    },
                    "scope": {
                      "type": "string",
                      "enum": [
                        "own",
                        "company"
                      ]
                    },
                    "poll_path": {
                      "type": "string",
                      "example": "/v1/captures/export-jobs/cexp_3Fh8sKq0aZr2LmN1"
                    },
                    "reused": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  }
                }
              }
            }
          },
          "202": {
            "description": "Úloha byla spuštěna.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "job_id",
                    "status",
                    "scope",
                    "poll_path"
                  ],
                  "properties": {
                    "job_id": {
                      "type": "string",
                      "example": "cexp_3Fh8sKq0aZr2LmN1"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing"
                      ]
                    },
                    "scope": {
                      "type": "string",
                      "enum": [
                        "own",
                        "company"
                      ]
                    },
                    "poll_path": {
                      "type": "string",
                      "example": "/v1/captures/export-jobs/cexp_3Fh8sKq0aZr2LmN1"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: tělo není objekt JSON, nebo je scope / org neplatné.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "FORBIDDEN: požadavek byl odeslán s testovacím klíčem, nebo se scope company od někoho, kdo není vlastníkem firmy v rámci jejího okna pro stažení.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "EXPORT_JOB_RUNNING: úloha účtu se stále zpracovává; details.job_id a details.poll_path ji označují.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/captures/export-jobs/{job_id}": {
      "get": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "getCaptureExportJob",
        "summary": "Stav a odkazy ke stažení úlohy exportu záznamů",
        "description": "Stav a průběh úlohy; jakmile je připravena, jeden předem podepsaný odkaz pro každou část. Odkaz platí do url_expires_at: nejvýše 24 hodin, nikdy déle než do download_expires_at a nikdy déle než přístupové údaje, které ho podepsaly (může to být i méně než hodina); po url_expires_at se dotažte znovu pro nové odkazy. download_expires_at je 7 dní od půlnoci UTC před spuštěním první části úlohy (6 až 7 dní poté, co byla úloha připravena); potom se části smažou. Úloha přijde o stažení předčasně (status expired, části smazány, expired_reason), když ji nahradil novější export se stejným rozsahem, záznam v ní obsažený byl trvale smazán, data její firmy byla smazána nebo na ni už nemáte práva (kontroluje se při každém čtení připravené úlohy). Úlohu, která 30 minut nehlásí žádný průběh, toto volání ukončí jako failed a to, co zapsala, se smaže. První odpověď s odkazy za hodinu se zaznamená do auditního protokolu (capture.export_job.links_issued). Úlohu vidí jen účet, který ji spustil; u firemního exportu firmy ponechané jako firemní archiv jen přes relaci v dashboardu.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "job_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^cexp_[A-Za-z0-9]{16}$"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Úloha.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "job_id",
                    "status",
                    "scope",
                    "parts"
                  ],
                  "properties": {
                    "job_id": {
                      "type": "string",
                      "example": "cexp_3Fh8sKq0aZr2LmN1",
                      "pattern": "^cexp_[A-Za-z0-9]{16}$"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "processing",
                        "ready",
                        "failed",
                        "expired"
                      ],
                      "description": "processing, zatímco se zapisuje plán a části; ready s odkazy ke stažení; failed (spusťte novou úlohu, denní jednotka byla vrácena); expired, když skončilo okno pro stažení nebo bylo stažení odebráno (expired_reason; části jsou smazány)."
                    },
                    "scope": {
                      "type": "string",
                      "enum": [
                        "own",
                        "company"
                      ]
                    },
                    "language": {
                      "type": "string",
                      "enum": [
                        "en",
                        "de",
                        "it",
                        "fr",
                        "es",
                        "pt_BR",
                        "cs",
                        "el",
                        "hi",
                        "hu",
                        "id",
                        "ja",
                        "ko",
                        "nl",
                        "pl",
                        "ro",
                        "ru",
                        "sv",
                        "tr",
                        "vi",
                        "zh_CN",
                        "zh_TW",
                        "ar",
                        "he",
                        "da",
                        "fi",
                        "nb",
                        "sk",
                        "uk"
                      ],
                      "description": "Jazyk souboru README úlohy (README.<language>.txt vedle README.txt; en jen pro README.txt)."
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "ended_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true
                    },
                    "progress": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "captures_total": {
                          "type": "integer",
                          "nullable": true
                        },
                        "captures_done": {
                          "type": "integer"
                        },
                        "parts_total": {
                          "type": "integer",
                          "nullable": true
                        },
                        "parts_done": {
                          "type": "integer"
                        }
                      }
                    },
                    "truncated": {
                      "type": "boolean",
                      "description": "true, pokud má účet více než 20 000 exportovatelných záznamů: úloha obsahuje nejnovějších 20 000."
                    },
                    "counts": {
                      "type": "object",
                      "nullable": true,
                      "description": "Nastaveno, když je úloha připravena.",
                      "properties": {
                        "captures": {
                          "type": "integer",
                          "description": "Řádky souboru captures.csv."
                        },
                        "packaged": {
                          "type": "integer",
                          "description": "Balíčky v částech."
                        },
                        "failed": {
                          "type": "integer",
                          "description": "Neúspěšné záznamy (bez balíčku, uvedené jen v captures.csv)."
                        },
                        "unavailable": {
                          "type": "integer",
                          "description": "Nezahrnuté balíčky: během exportu je nebylo možné načíst, nebo jsou větší než 2 GB (které to jsou, uvádí captures.csv)."
                        }
                      }
                    },
                    "parts": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "part",
                          "bytes",
                          "count",
                          "download_url"
                        ],
                        "properties": {
                          "part": {
                            "type": "integer",
                            "minimum": 1,
                            "example": 1,
                            "description": "Číslo části, od 1 do počtu částí."
                          },
                          "bytes": {
                            "type": "integer",
                            "example": 1834201112,
                            "description": "Velikost části ZIP v bajtech."
                          },
                          "count": {
                            "type": "integer",
                            "example": 412,
                            "description": "Balíčky záznamů v této části."
                          },
                          "filename": {
                            "type": "string",
                            "example": "proofsnap-captures-2026-10-07T1430Z-part-1-of-3.zip",
                            "description": "Název souboru, pod kterým se stažený soubor uloží (Content-Disposition): proofsnap-captures-<datum a čas spuštění úlohy v UTC>, s -part-N-of-M, pokud je částí více."
                          },
                          "download_url": {
                            "type": "string",
                            "format": "uri",
                            "nullable": true,
                            "description": "Předem podepsaná GET URL ZIP souboru části, platná do url_expires_at. null, pokud úloha vypršela."
                          }
                        }
                      }
                    },
                    "download_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Konec okna pro stažení: 7 dní od půlnoci UTC předcházející zahájení první části (poté části smaže životní cyklus úložiště)."
                    },
                    "url_expires_at": {
                      "type": "string",
                      "format": "date-time",
                      "nullable": true,
                      "description": "Kdy hodnoty download_url v této odpovědi přestanou fungovat: nejvýše za 24 hodin, nikdy později než download_expires_at a nikdy později, než skončí platnost podepisujících přístupových údajů. Poté se dotažte znovu pro nové odkazy."
                    },
                    "error": {
                      "type": "string",
                      "nullable": true,
                      "example": "export timed out"
                    },
                    "expired_reason": {
                      "type": "string",
                      "nullable": true,
                      "enum": [
                        "window_ended",
                        "superseded",
                        "rights_changed",
                        "capture_erased",
                        "company_deleted",
                        null
                      ],
                      "description": "Nastaveno, když je status expired: window_ended (uplynul download_expires_at), superseded (novější export stejného rozsahu), rights_changed (Vaše oprávnění už úlohu nepokrývají), capture_erased (záznam, který obsahuje, byl vymazán), company_deleted (data jeho firmy byla smazána)."
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "EXPORT_JOB_NOT_FOUND: taková úloha neexistuje, jde o úlohu jiného účtu, její záznam vypršel (8 dní po jejím skončení), nebo byl požadavek odeslán s testovacím klíčem.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/webhook-subscriptions": {
      "get": {
        "tags": [
          "Webhooky"
        ],
        "operationId": "listWebhookSubscriptions",
        "summary": "Výpis odběrů webhooků",
        "description": "Odběry webhooků účtu, od nejnovějších, aktivní i vypnuté, bez tajných kódů. Klíč API nebo relace v dashboardu; použít ho smí i klíč jen pro čtení (Website Archive).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Odběry.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "subscriptions": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookSubscription"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "post": {
        "tags": [
          "Webhooky"
        ],
        "operationId": "createWebhookSubscription",
        "summary": "Odběr událostí účtu",
        "description": "Přihlásí https endpoint k odběru událostí účtu: každá odpovídající událost účtu se na něj odešle metodou POST, podepsaná vlastním tajným kódem odběru (vrátí se jen jednou, v této odpovědi). Vyžaduje potvrzenou e-mailovou adresu (403 EMAIL_NOT_VERIFIED). Povoleno i u předplatného po splatnosti (nic se neúčtuje). Limity AKTIVNÍCH odběrů na účet: 25 u developer, startup, growth, custom, legal_solo a legal_seats, 10 u website_archive, 0 u archive_only a sandbox (409 WEBHOOK_SUBSCRIPTION_LIMIT). URL se řídí pravidly pro webhook_url (https, bez přihlašovacích údajů, bez privátní nebo rezervované adresy; kontroluje se znovu při každém doručení). Idempotency-Key je podporován: opakování se stejným klíčem a tělem do 24 hodin dostane zpět první odpověď včetně tajného kódu, místo aby vznikl druhý odběr. Klíč API nebo relace v dashboardu; použít ho smí i klíč jen pro čtení (Website Archive).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "url",
                  "events"
                ],
                "additionalProperties": false,
                "properties": {
                  "url": {
                    "type": "string",
                    "example": "https://hooks.example.com/proofsnap"
                  },
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 9,
                    "uniqueItems": true,
                    "items": {
                      "$ref": "#/components/schemas/WebhookEventType"
                    }
                  },
                  "filters": {
                    "$ref": "#/components/schemas/WebhookSubscriptionFilters"
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Prostý text, nejvýše 200 znaků."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Vytvořeno. `secret` se zobrazí jen zde.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscriptionCreated"
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (events, filters, description, neznámé pole), MISSING_FIELD (url) nebo INVALID_URL.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "EMAIL_NOT_VERIFIED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "WEBHOOK_SUBSCRIPTION_LIMIT, IDEMPOTENCY_IN_PROGRESS.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "SSRF_BLOCKED (URL míří na blokovanou adresu) nebo IDEMPOTENCY_KEY_REUSED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/webhook-subscriptions/{subscription_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SubscriptionId"
        }
      ],
      "get": {
        "tags": [
          "Webhooky"
        ],
        "operationId": "getWebhookSubscription",
        "summary": "Získání odběru webhooku",
        "description": "Jeden odběr se stavem doručování, bez tajného kódu. Klíč API nebo relace dashboardu; může ho použít i klíč jen pro čtení (Website Archive).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Odběr.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "WEBHOOK_SUBSCRIPTION_NOT_FOUND: neznámý, smazaný nebo odběr jiného účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "patch": {
        "tags": [
          "Webhooky"
        ],
        "operationId": "updateWebhookSubscription",
        "summary": "Změnit nebo znovu aktivovat odběr webhooku",
        "description": "Změní události, filtry (null nebo {} je vymaže) nebo popis, případně znovu aktivuje vypnutý odběr se status \"active\" (vynuluje počítadla selhání; kontroluje se vůči limitu aktivních odběrů). URL změnit nelze: vytvořte nový odběr. Vyžaduje potvrzenou e-mailovou adresu. Klíč API nebo relace dashboardu; může ho použít i klíč jen pro čtení (Website Archive).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "events": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 9,
                    "uniqueItems": true,
                    "items": {
                      "$ref": "#/components/schemas/WebhookEventType"
                    }
                  },
                  "filters": {
                    "type": "object",
                    "allOf": [
                      {
                        "$ref": "#/components/schemas/WebhookSubscriptionFilters"
                      }
                    ],
                    "nullable": true
                  },
                  "description": {
                    "type": "string",
                    "maxLength": 200,
                    "nullable": true
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Změněný odběr.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookSubscription"
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "EMAIL_NOT_VERIFIED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "WEBHOOK_SUBSCRIPTION_NOT_FOUND: neznámý, smazaný nebo odběr jiného účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "WEBHOOK_SUBSCRIPTION_LIMIT (opětovná aktivace nad limit).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooky"
        ],
        "operationId": "deleteWebhookSubscription",
        "summary": "Smazání odběru webhooku",
        "description": "Smaže odběr, jeho tajný kód a jeho doručení ve frontě. 404 pro neznámý nebo již smazaný odběr (považujte jej za odstraněný). Klíč API nebo relace v dashboardu; smí jej použít i klíč jen pro čtení (Website Archive).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "204": {
            "description": "Smazáno.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "WEBHOOK_SUBSCRIPTION_NOT_FOUND: neznámý, smazaný nebo odběr jiného účtu.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/events": {
      "get": {
        "tags": [
          "Webhooky"
        ],
        "operationId": "listEvents",
        "summary": "Protokol událostí",
        "description": "Všechny události vydané pro účet za posledních 30 dní, bez ohledu na to, zda je přijal některý odběr, od nejnovější. Klíč API vidí události prostředí, ve kterém běží (ostrý klíč ostré události, testovací klíč testovací události); relace dashboardu vidí ostré události. Použijte ho k doplnění zameškaných událostí nebo k pravidelnému dotazování místo odběru. Klíč API nebo relace dashboardu; může ho použít i klíč jen pro čtení (Website Archive).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Jen tento typ události.",
            "schema": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1 až 100, výchozí 25.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "description": "ID události: stránka začíná za ní (předejte next_cursor). ID jiného účtu nebo prostředí, nebo starší než 30 dní, vrátí 400.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stránka událostí.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "events": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Event"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true,
                      "description": "Předejte jako starting_after pro další stránku; na poslední stránce null."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (type, limit nebo starting_after).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/whoami": {
      "get": {
        "tags": [
          "Webhooky"
        ],
        "operationId": "whoami",
        "summary": "Kdo jsem",
        "description": "Popis přístupového údaje: plán, prostředí, zda je klíč API jen pro čtení, a ID, název a prefix klíče (null u relace v dashboardu). Integrace ho používají k otestování připojení a k jeho označení. Bez e-mailové adresy a bez ID účtu. Klíč API nebo relace v dashboardu; použít ho smí i klíč jen pro čtení (Website Archive).",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Přístupový údaj.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "plan": {
                      "type": "string",
                      "nullable": true,
                      "example": "startup",
                      "enum": [
                        "developer",
                        "startup",
                        "growth",
                        "custom",
                        "legal_solo",
                        "legal_seats",
                        "website_archive",
                        "archive_only",
                        "sandbox",
                        null
                      ]
                    },
                    "api_read_only": {
                      "type": "boolean",
                      "description": "true u klíče API účtu Website Archive (smí číst a odebírat, ne pořizovat záznamy)."
                    },
                    "env": {
                      "type": "string",
                      "enum": [
                        "live",
                        "test"
                      ],
                      "description": "Prostředí, ve kterém přístupový údaj běží."
                    },
                    "key": {
                      "type": "object",
                      "nullable": true,
                      "properties": {
                        "key_id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string",
                          "nullable": true
                        },
                        "prefix": {
                          "type": "string",
                          "enum": [
                            "ps_live_",
                            "ps_test_"
                          ]
                        }
                      }
                    },
                    "email_verified": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/captures/events": {
      "get": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "listCaptureEvents",
        "summary": "Řetězec událostí záznamu (smazání a právní blokace)",
        "description": "Protokol účtu odhalující neoprávněné změny, který zachycuje, co se dělo s jeho záznamy: přesun do koše, obnovení, trvalé smazání (erase), vysypání koše, smazání po uplynutí doby uchování, smazání spolu s účtem nebo firmou, nastavení a zrušení právní blokace (zrušení systémem po skončení předplatného má actor `system` a detail `subscription_ended`), výsledek S3 Object Lock a import balíčku důkazů (type `import`, detail = druh balíčku). Seřazeno od nejstarší. Řetězec přetrvá záznamy i data účtu: obsahuje jen ID a hashe manifestů, žádný obsah záznamů ani volný text.\n\nOvěření: (1) pro každou událost spočítejte SHA-256 z kanonického JSON hashovaných polí (verification.hashed_fields; klíče seřazené, bez bílých znaků, chybějící hodnoty jako null) a porovnejte ho s `hash`; (2) zkontrolujte, že každý `prev_hash` se rovná `hash` předchozí události (64 nul pro seq 1) a že v seq nejsou mezery; (3) u kotvy zkontrolujte, že `head_hash` se rovná `hash` události `to_seq`, zapište `ots_proof_base64` do souboru (po dekódování z base64) a spusťte `ots verify -d <head_hash> anchor.ots` (klient OpenTimestamps): prokáže, že řetězec až po tuto událost existoval nejpozději v čase bloku Bitcoinu. Kotvy se vytvářejí jednou denně pro každý účet, který má události z dřívějšího dne.\n\nKlíč API nebo relace v dashboardu, vlastní účet; `scope=company` dá vlastníkovi firmy řetězec záznamů firmy (`org` vybere jednu, pokud jich volající vlastní více; firmu ponechanou jako firemní archiv jen přes relaci v dashboardu). Testovací klíč dostane 403 FORBIDDEN: řetězec pokrývá ostré záznamy a nelze ho filtrovat, aniž by se porušil.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "1 až 500, výchozí 100.",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 500,
              "default": 100
            }
          },
          {
            "name": "starting_after",
            "in": "query",
            "required": false,
            "description": "seq události: stránka začíná za ní (předejte next_starting_after).",
            "schema": {
              "type": "integer",
              "minimum": 0
            }
          },
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "own",
                "company"
              ],
              "default": "own"
            }
          },
          {
            "name": "org",
            "in": "query",
            "required": false,
            "description": "scope=company: id firmy.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Stránka řetězce.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "chain": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string",
                      "enum": [
                        "own",
                        "company"
                      ]
                    },
                    "head": {
                      "type": "object",
                      "properties": {
                        "chain": {
                          "type": "string"
                        },
                        "seq": {
                          "type": "integer"
                        },
                        "head_hash": {
                          "type": "string",
                          "nullable": true
                        },
                        "anchored_seq": {
                          "type": "integer"
                        }
                      }
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaptureEvent"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_starting_after": {
                      "type": "integer",
                      "nullable": true
                    },
                    "anchors": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CaptureEventAnchor"
                      }
                    },
                    "verification": {
                      "type": "object",
                      "properties": {
                        "hash": {
                          "type": "string"
                        },
                        "hashed_fields": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "genesis_prev_hash": {
                          "type": "string"
                        },
                        "anchor": {
                          "type": "string"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST: neplatné limit, starting_after nebo scope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "FORBIDDEN: požadavek byl odeslán s testovacím klíčem, nebo se scope=company od někoho, kdo firmu nevlastní.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/legal-holds": {
      "post": {
        "tags": [
          "Záznamy"
        ],
        "operationId": "bulkLegalHold",
        "summary": "Hromadné nastavení nebo zrušení právních blokací",
        "description": "Nastaví (enabled true) nebo zruší (false) právní blokaci mnoha záznamů najednou. selector obsahuje právě jedno z: `capture_ids` (1 až 500 ID), `matter_id` (záznamy spisu, který volající může otevřít), `host` (vlastní záznamy volajícího z tohoto hostitele) nebo `schedule_id` (vlastní záznamy volajícího pořízené jedním z jeho automatických záznamů). Každý záznam prochází pravidly PATCH /captures/{capture_id} s akcí legal_hold a dostane vlastní výsledek: applied, unchanged (už v daném stavu) nebo odmítnutí s kódem chyby (např. FORBIDDEN, CAPTURE_IN_TRASH, CAPTURE_PROCESSING, LEGAL_HOLD_OWNER_ONLY, LEGAL_HOLD_MATTER, LEGAL_HOLD_SOURCE u začernění, jehož zdrojový záznam je stále blokován, CAPTURE_NOT_FOUND, LEGAL_HOLD_NOT_AVAILABLE u záznamu v testovacím režimu). Začernění vytvořená z každého záznamu přebírají jeho blokaci, i u záznamu nahlášeného jako unchanged; pokud se to nestihne v rámci požadavku, dokončí se během několika minut. Nastavení blokací vyžaduje placený plán: bezplatný sandbox dostane pro celý požadavek 403 LEGAL_HOLD_NOT_AVAILABLE (details.reason \"plan\"); rušení funguje na každém plánu. Blokace nastavená zde má legal_hold_source \"bulk\"; zrušit ji lze hromadně i jednotlivě stejným způsobem. Nejvýše 500 záznamů na požadavek: spis, hostitel nebo automatický záznam s větším počtem se ořízne (`truncated: true`, pošlete požadavek znovu). Právní blokace S3 Object Lock prvních 25 změněných záznamů se použije v rámci požadavku, zbytek během několika minut (`s3_legal_hold.status` pending). Cena: jedna jednotka limitu počtu požadavků za každých 10 záznamů (nejméně jedna); požadavek, který potřebuje víc, než jedno okno dovoluje, vrátí 400 RATE_LIMIT_COST_TOO_HIGH. Klíč API nebo relace dashboardu; u Website Archive je klíč API jen pro čtení (403 PLAN_API_READ_ONLY). Relace dashboardu nebo klíč s nepotvrzenou e-mailovou adresou dostane 403 EMAIL_NOT_VERIFIED. Nevadí ani předplatné po splatnosti.",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "enabled",
                  "selector"
                ],
                "additionalProperties": false,
                "properties": {
                  "enabled": {
                    "type": "boolean"
                  },
                  "reason": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Prostý text uložený u každé nastavené blokace (ne u zrušení); nikdy není v hashovaných řetězcích."
                  },
                  "selector": {
                    "type": "object",
                    "minProperties": 1,
                    "maxProperties": 1,
                    "properties": {
                      "capture_ids": {
                        "type": "array",
                        "minItems": 1,
                        "maxItems": 500,
                        "items": {
                          "type": "string"
                        }
                      },
                      "matter_id": {
                        "type": "string"
                      },
                      "host": {
                        "type": "string"
                      },
                      "schedule_id": {
                        "type": "string"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Výsledky pro jednotlivé záznamy.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "enabled": {
                      "type": "boolean"
                    },
                    "selector": {
                      "type": "string",
                      "enum": [
                        "capture_ids",
                        "matter_id",
                        "host",
                        "schedule_id"
                      ]
                    },
                    "requested": {
                      "type": "integer"
                    },
                    "truncated": {
                      "type": "boolean"
                    },
                    "applied": {
                      "type": "integer"
                    },
                    "unchanged": {
                      "type": "integer"
                    },
                    "refused": {
                      "type": "integer"
                    },
                    "results": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "capture_id": {
                            "type": "string"
                          },
                          "result": {
                            "type": "string",
                            "enum": [
                              "applied",
                              "unchanged",
                              "refused"
                            ]
                          },
                          "code": {
                            "type": "string",
                            "description": "Kód chyby odmítnutí."
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (tělo, selektor, více než 500 capture_ids), RATE_LIMIT_COST_TOO_HIGH.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "description": "EMAIL_NOT_VERIFIED, PLAN_API_READ_ONLY, LEGAL_HOLD_NOT_AVAILABLE (nastavení bez placeného tarifu, details.reason plan).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND (matter_id, který volající nemůže otevřít), SCHEDULE_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/imports": {
      "post": {
        "tags": [
          "Import balíčku"
        ],
        "operationId": "createImport",
        "summary": "Spustit import balíčku",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Vytvoří import a zahájí jeho nahrávání. Pošlete přesnou velikost ZIP v bajtech; odpověď obsahuje jednu předem podepsanou URL pro PUT na každou část o 32 MiB (poslední je menší), platnou 1 hodinu (`upload.expires_at`; nikdy déle než podpisové přihlašovací údaje serveru). Bajty každé části odešlete metodou PUT na její URL, z každé odpovědi si uložte hlavičku `ETag` a do 24 hodin zavolejte POST /imports/{import_id}/complete. S `matter_id` se přijatý záznam přidá do tohoto spisu: musíte do něj v tu chvíli smět přidávat záznamy (otevřený spis, který smíte otevřít; import místa ve firmě jen do spisu této firmy). Každé vytvoření se započítává do denního limitu 50.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "filename",
                  "size_bytes"
                ],
                "additionalProperties": false,
                "properties": {
                  "filename": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Zobrazovaný název souboru (prostý text: bez řídicích a neviditelných znaků a bez znaků směru textu)."
                  },
                  "size_bytes": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 2147483648,
                    "description": "Přesná velikost ZIP v bajtech, nejvýše 2 GiB."
                  },
                  "matter_id": {
                    "type": "string",
                    "description": "Nepovinné: přidá přijatý záznam do tohoto spisu."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Import vytvořen; nahrajte části.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "import_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "uploading"
                      ]
                    },
                    "upload": {
                      "type": "object",
                      "properties": {
                        "upload_id": {
                          "type": "string"
                        },
                        "part_size": {
                          "type": "integer",
                          "example": 33554432
                        },
                        "parts": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "properties": {
                              "part_number": {
                                "type": "integer"
                              },
                              "url": {
                                "type": "string",
                                "format": "uri",
                                "description": "Předem podepsaná URL pro S3 UploadPart: nahrajte přes PUT přesně size_bytes bajtů (URL podepisuje Content-Length) a přečtěte hlavičku odpovědi ETag. Žádná další hlavička není potřeba."
                              },
                              "size_bytes": {
                                "type": "integer",
                                "description": "Přesná délka této části v bajtech: part_size u všech částí kromě poslední, u poslední zbytek (část n začíná na (n - 1) x part_size)."
                              }
                            }
                          }
                        },
                        "expires_at": {
                          "type": "string",
                          "format": "date-time"
                        }
                      }
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (body, filename, size_bytes, matter_id, neznámé pole).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED: předplatné je po splatnosti nebo nezaplacené.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "IMPORT_NOT_ALLOWED (details.reason plan: jen tarify Legal; live_credentials_required: testovací klíč, relace bez propojené fakturace nebo sandbox), EMAIL_NOT_VERIFIED, FORBIDDEN (import místa firmy do spisu jiné firmy).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "MATTER_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "IMPORT_LIMIT (probíhají 3 importy; details.limit, details.in_progress), MATTER_SEALED, MATTER_ARCHIVED, COMPANY_READ_ONLY.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "413": {
            "description": "IMPORT_TOO_LARGE: size_bytes nad 2 GiB (details.max_bytes).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED: minutový limit, nebo denní limit 50 importů (details.action import_create, details.daily_limit).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      },
      "get": {
        "tags": [
          "Import balíčku"
        ],
        "operationId": "listImports",
        "summary": "Výpis vašich importů",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Vaše importy, od nejnovějších. Dokončené importy se uchovávají 30 dní (záznam přijatého importu zůstává). Nahrávání po uplynutí 24 hodin se zobrazí jako expired.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "next_cursor předchozí stránky."
          }
        ],
        "responses": {
          "200": {
            "description": "Stránka importů.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "imports": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Import"
                      }
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (limit, cursor).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/imports/{import_id}": {
      "parameters": [
        {
          "name": "import_id",
          "in": "path",
          "required": true,
          "description": "ID importu (imp_ následované 16 až 24 písmeny a číslicemi). Chybně utvořené ID vrátí 404 IMPORT_NOT_FOUND.",
          "schema": {
            "type": "string",
            "pattern": "^imp_[A-Za-z0-9]{16,24}$"
          }
        }
      ],
      "get": {
        "tags": [
          "Import balíčku"
        ],
        "operationId": "getImport",
        "summary": "Získání importu",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Import a po dokončení jeho výsledek. Dotazujte se na něj po POST /imports/{import_id}/complete; ověření obvykle trvá sekundy, balíček o velikosti 2 GiB až několik minut. S ?upload=true u nahrávání, které ještě probíhá, odpověď přidá upload: nové předem podepsané URL (parts) pro části, které úložiště ještě nemá, a již přijaté části (received: part_number, etag, size_bytes; null, když je nebylo možné vypsat, pak se znovu podepíší všechny části), nebo completed: true, když už bylo nahrávání dokončeno (odešlete complete znovu). Slouží k navázání po výpadku sítě, po vypršení URL části (platí nejvýše 1 hodinu, okno pro nahrání 24 hodin) nebo po znovunačtení stránky. ?upload=true spotřebuje jednu jednotku minutového limitu počtu požadavků.",
        "responses": {
          "200": {
            "description": "Import.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Import"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "IMPORT_NOT_FOUND (i u importu jiného účtu).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED (jen s ?upload=true).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        },
        "parameters": [
          {
            "name": "upload",
            "in": "query",
            "required": false,
            "description": "true (nebo 1): přidá nové URL částí a přijaté části probíhajícího nahrávání.",
            "schema": {
              "type": "string",
              "enum": [
                "true",
                "1"
              ]
            }
          }
        ]
      },
      "delete": {
        "tags": [
          "Import balíčku"
        ],
        "operationId": "cancelImport",
        "summary": "Zrušit nahrávání",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Zruší import, který se ještě nahrává: nahrávání se přeruší, části se smažou a import se odstraní (GET pak vrací 404).",
        "responses": {
          "200": {
            "description": "Zrušeno.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "import_id": {
                      "type": "string"
                    },
                    "deleted": {
                      "type": "boolean",
                      "enum": [
                        true
                      ]
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "IMPORT_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "IMPORT_STATE: import už není ve stavu nahrávání (details.status).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    },
    "/imports/{import_id}/complete": {
      "parameters": [
        {
          "name": "import_id",
          "in": "path",
          "required": true,
          "description": "ID importu (imp_ následované 16 až 24 písmeny a číslicemi). Chybně utvořené ID vrátí 404 IMPORT_NOT_FOUND.",
          "schema": {
            "type": "string",
            "pattern": "^imp_[A-Za-z0-9]{16,24}$"
          }
        }
      ],
      "post": {
        "tags": [
          "Import balíčku"
        ],
        "operationId": "completeImport",
        "summary": "Dokončení nahrávání a ověření",
        "security": [
          {
            "ApiKeyAuth": []
          }
        ],
        "description": "Dokončí nahrávání a spustí ověření. Pole parts je nepovinné: pošlete čísla všech částí (1 až N, v pořadí) s ETag, který vrátil PUT dané části, nebo pole vynechte a server si nahrané části přečte z úložiště (hodí se v prohlížeči, který hlavičku ETag nepřečte). Kontroluje, že uložená velikost odpovídá size_bytes. Stav sledujte přes GET /imports/{import_id}. Seznam částí, který úložiště odmítne, nebo dosud nenahraná část (details.missing_parts) vrací 400 a nahrávání zůstává otevřené: nahrajte, co chybí (GET /imports/{import_id}?upload=true vydá nové URL), a požadavek pošlete znovu. Opakované odeslání complete po ztracené odpovědi je bezpečné: complete, které stále běží, vrací 409, to, které skončilo neúspěchem, se po 2 minutách převezme, a již dokončené nahrávání pokračuje k ověření. Velikost odlišná od size_bytes nahrávání zahodí (422 IMPORT_SIZE_MISMATCH; import je zamítnut, vytvořte nový).",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "parts": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "required": [
                        "part_number",
                        "etag"
                      ],
                      "properties": {
                        "part_number": {
                          "type": "integer",
                          "minimum": 1
                        },
                        "etag": {
                          "type": "string",
                          "description": "Hlavička odpovědi ETag z PUT dané části, s uvozovkami nebo bez nich."
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Ověření zahájeno.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/XRequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "import_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "verifying"
                      ]
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "MALFORMED_REQUEST (části mimo pořadí nebo neodpovídající nahraným částem; nebo, bez parts, část, která ještě nebyla nahrána: details.missing_parts).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "description": "PAYMENT_REQUIRED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "IMPORT_NOT_ALLOWED, EMAIL_NOT_VERIFIED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "IMPORT_NOT_FOUND.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "IMPORT_STATE: import se už nenahrává (details.status, například verifying nebo expired).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "422": {
            "description": "IMPORT_SIZE_MISMATCH (details.expected, details.actual).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "RATE_LIMITED.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/AuthUnavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Posílejte klíč API jako `Authorization: Bearer ps_live_...` (na velikosti písmen v názvu schématu nezáleží). Chybějící nebo chybně formátovaná hlavička vrací 401 MISSING_API_KEY. Neznámý, zneplatněný nebo prošlý klíč, případně účet bez přístupu k API, vrací 401 INVALID_API_KEY s `WWW-Authenticate: Bearer realm=\"ProofSnap API\", error=\"invalid_token\"`. 403 je vyhrazena pro platný přihlašovací údaj, který něco dělat nesmí (FORBIDDEN, omezení plánu). Klíč `ps_live_` účtu bez propojeného fakturačního účtu (zákazník Stripe) funguje jako testovací klíč: záznamy mají vodoznak, nikdy se neúčtují a include_eidas se odmítne s 403 EIDAS_REQUIRES_LIVE_KEY. Brána ukládá rozhodnutí pro klíč do mezipaměti až na 60 sekund, takže zneplatněný klíč může fungovat ještě až 60 sekund. Pokud přihlašovací údaj nelze ověřit kvůli dočasné chybě backendu, brána místo toho vrací 503 SERVICE_UNAVAILABLE; tato odpověď se do mezipaměti neukládá, proto opakujte s postupně prodlužovanou prodlevou. Výzva `WWW-Authenticate` se vrací beze změny u 401 z brány (ověření přihlašovacího údaje); u 401 z obslužného kódu endpointu ji brána doručí přejmenovanou na `x-amzn-Remapped-WWW-Authenticate`."
      }
    },
    "headers": {
      "XRequestId": {
        "description": "ID požadavku, užitečné i v žádostech o podporu. Posílá se v úspěšných odpovědích; těla chyb ho nesou jako request_id.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimitLimit": {
        "description": "Počet požadavků povolených v aktuálním 60sekundovém okně. Starší hlavička, zachovaná vedle RateLimit / RateLimit-Policy.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitRemaining": {
        "description": "Počet požadavků zbývajících v aktuálním okně. Starší hlavička, zachovaná vedle RateLimit / RateLimit-Policy.",
        "schema": {
          "type": "integer"
        }
      },
      "RateLimitReset": {
        "description": "Čas ve formátu ISO 8601, kdy končí aktuální okno. Starší hlavička, ponechaná vedle RateLimit / RateLimit-Policy.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "RetryAfter": {
        "description": "Počet sekund, po který se má před opakováním čekat.",
        "schema": {
          "type": "integer"
        }
      },
      "QuotaLimit": {
        "description": "Záznamy zahrnuté v tarifu za měsíc (ostré klíče u tarifů s měsíční kvótou).",
        "schema": {
          "type": "integer"
        }
      },
      "QuotaRemaining": {
        "description": "Zbývající zahrnuté záznamy v tomto měsíci.",
        "schema": {
          "type": "integer"
        }
      },
      "QuotaUsed": {
        "description": "Dokončené záznamy v tomto měsíci.",
        "schema": {
          "type": "integer"
        }
      },
      "QuotaCap": {
        "description": "Měsíční maximum, které platí pro volajícího (výchozí hodnota plánu, vlastní strop nebo limit firmy).",
        "schema": {
          "type": "integer"
        }
      },
      "QuotaOrgLimit": {
        "description": "Pouze členové firmy: měsíční limit celé firmy, pokud ho vlastník nastavil.",
        "schema": {
          "type": "integer"
        }
      },
      "QuotaOrgUsed": {
        "description": "Pouze členové firmy: záznamy přijaté za celou firmu v tomto měsíci.",
        "schema": {
          "type": "integer"
        }
      },
      "SandboxLimit": {
        "description": "Sandbox (relace dashboardu bez plánu): celoživotní příděl testovacích záznamů s vodoznakem (50).",
        "schema": {
          "type": "integer"
        }
      },
      "SandboxRemaining": {
        "description": "Sandbox: zbývající příděl.",
        "schema": {
          "type": "integer"
        }
      },
      "SandboxUsed": {
        "description": "Sandbox: využitý příděl.",
        "schema": {
          "type": "integer"
        }
      },
      "IdempotentReplay": {
        "description": "\"true\", pokud tato odpověď opakuje dřívější požadavek se stejným Idempotency-Key.",
        "schema": {
          "type": "string",
          "enum": [
            "true"
          ]
        }
      },
      "WWWAuthenticate": {
        "description": "Výzva podle RFC 6750 odesílaná s každou odpovědí 401. U 401, kterou vrátil obslužný kód endpointu, a ne brána, ji API Gateway doručí přejmenovanou na `x-amzn-Remapped-WWW-Authenticate`. Neplatný, zneplatněný nebo prošlý klíč API, případně chybný nebo zneplatněný token relace (INVALID_API_KEY): `Bearer realm=\"ProofSnap API\", error=\"invalid_token\"`. Chybějící nebo chybně formátovaná hlavička Authorization (MISSING_API_KEY): `Bearer realm=\"ProofSnap API\"`.",
        "schema": {
          "type": "string"
        },
        "example": "Bearer realm=\"ProofSnap API\", error=\"invalid_token\""
      },
      "RateLimitPolicy": {
        "description": "Zásada limitu počtu požadavků podle návrhu IETF draft-ietf-httpapi-ratelimit-headers (tvar structured field; vychází z návrhu a může se s ním měnit): `\"default\";q=<requests per window>;w=60`.",
        "schema": {
          "type": "string"
        },
        "example": "\"default\";q=120;w=60"
      },
      "RateLimit": {
        "description": "Aktuální stav limitu počtu požadavků podle návrhu IETF draft-ietf-httpapi-ratelimit-headers (vychází z návrhu): `\"default\";r=<requests left>;t=<seconds until the window resets>`, kde r je počet zbývajících požadavků a t počet sekund do obnovení okna. Posílá se v odpovědích tras s limitem počtu požadavků (jednotlivé a dávkové záznamy, compare, redact, certify-hash) poté, co proběhne omezovač, nejen u 429 (požadavek odmítnutý před omezovačem, například kvůli autentizaci, ji nemá).",
        "schema": {
          "type": "string"
        },
        "example": "\"default\";r=117;t=42"
      }
    },
    "parameters": {
      "CaptureId": {
        "name": "capture_id",
        "in": "path",
        "required": true,
        "description": "ID záznamu, certifikátu, porovnání, začernění nebo importovaného balíčku. ID začínají cap_, cert_, cmp_, red_ nebo imp_. Chybně formátované ID vrátí 404 CAPTURE_NOT_FOUND.",
        "schema": {
          "type": "string",
          "example": "cap_a1B2c3D4e5F6g7H8"
        }
      },
      "ScheduleId": {
        "name": "schedule_id",
        "in": "path",
        "required": true,
        "description": "ID automatického záznamu. Automatický záznam jiného účtu vrací 404 SCHEDULE_NOT_FOUND.",
        "schema": {
          "type": "string",
          "example": "sch_a1B2c3D4e5F6g7H8"
        }
      },
      "MatterId": {
        "name": "matter_id",
        "in": "path",
        "required": true,
        "description": "ID spisu. Pro spis, jehož nejste členem, se vrací 404 MATTER_NOT_FOUND.",
        "schema": {
          "type": "string",
          "example": "mat_a1B2c3D4e5F6g7H8"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Nepovinný klientský klíč, díky kterému je opakování požadavku bezpečné. Použije se jen prvních 255 znaků a klíče platí v rámci vašeho účtu 24 hodin. Opakování se stejným klíčem a stejným tělem vrátí původní tělo odpovědi s `Idempotent-Replay: true` (202 pro jeden záznam, dávku nebo porovnání, 201 pro začernění; `status` se aktualizuje na současný stav záznamu, porovnání nebo začernění a každého záznamu dávky); nový záznam se nevytvoří ani neúčtuje. Stejný klíč s jiným tělem vrátí 422 IDEMPOTENCY_KEY_REUSED. Opakování v době, kdy se první požadavek ještě přijímá, vrátí 409 IDEMPOTENCY_IN_PROGRESS s původním ID v `error.details.capture_id` (u dávky batch_id).",
        "schema": {
          "type": "string",
          "maxLength": 255
        }
      },
      "SubscriptionId": {
        "name": "subscription_id",
        "in": "path",
        "required": true,
        "description": "ID odběru webhooku. Odběr jiného účtu vrací 404 WEBHOOK_SUBSCRIPTION_NOT_FOUND.",
        "schema": {
          "type": "string",
          "example": "whs_a1B2c3D4e5F6g7H8"
        }
      }
    },
    "responses": {
      "RateLimited": {
        "description": "RATE_LIMITED: příliš mnoho požadavků v aktuálním 60sekundovém okně. `error.details.retry_after_seconds` opakuje Retry-After. RateLimit hlásí r=0 a počet sekund do resetu okna.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "RateLimit-Policy": {
            "$ref": "#/components/headers/RateLimitPolicy"
          },
          "RateLimit": {
            "$ref": "#/components/headers/RateLimit"
          },
          "X-RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimitLimit"
          },
          "X-RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimitRemaining"
          },
          "X-RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimitReset"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "RATE_LIMITED",
                "message": "Too many requests. See Retry-After header.",
                "details": {
                  "retry_after_seconds": 42
                }
              },
              "request_id": "..."
            }
          }
        }
      },
      "InternalError": {
        "description": "INTERNAL_ERROR: neočekávaná chyba serveru. Opakujte s exponenciálním odstupem.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "AuthUnavailable": {
        "description": "SERVICE_UNAVAILABLE: brána nemohla ověřit přihlašovací údaj (dočasná chyba backendu). Neukládá se do mezipaměti: opakujte s postupně prodlužovanou prodlevou.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "code": "SERVICE_UNAVAILABLE",
                "message": "Authentication is temporarily unavailable. Please retry."
              },
              "request_id": "..."
            }
          }
        }
      },
      "EidasOrAuthUnavailable": {
        "description": "EIDAS_UNAVAILABLE: bylo požadováno include_eidas, ale kvalifikovaná časová razítka nejsou v tomto nasazení nakonfigurována; zopakujte požadavek bez include_eidas. SERVICE_UNAVAILABLE: brána nemohla ověřit přihlašovací údaje (dočasná chyba backendu, neukládá se do mezipaměti); opakujte s postupně prodlužovaným odstupem.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "401, dva kódy. MISSING_API_KEY: hlavička Authorization chybí nebo má chybný formát (`WWW-Authenticate: Bearer realm=\"ProofSnap API\"`). INVALID_API_KEY: přihlašovací údaj byl odeslán, ale není platný: neznámý, zneplatněný nebo prošlý klíč API, účet bez přístupu k API, nebo neplatný či zneplatněný token relace (`WWW-Authenticate: Bearer realm=\"ProofSnap API\", error=\"invalid_token\"`). Neopakujte požadavek se stejným přihlašovacím údajem. 403 znamená, že přihlašovací údaj je platný, ale k této akci neopravňuje (FORBIDDEN, omezení tarifu).",
        "headers": {
          "WWW-Authenticate": {
            "$ref": "#/components/headers/WWWAuthenticate"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "examples": {
              "missing": {
                "value": {
                  "error": {
                    "code": "MISSING_API_KEY",
                    "message": "Missing or malformed Authorization header. Send Authorization: Bearer <your API key>."
                  },
                  "request_id": "..."
                }
              },
              "invalid": {
                "value": {
                  "error": {
                    "code": "INVALID_API_KEY",
                    "message": "The API key is invalid, revoked or expired, or the account has no API access."
                  },
                  "request_id": "..."
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Každá chyba má tento tvar. Chybové odpovědi nesou hlavičku `X-Request-ID` se stejnou hodnotou jako `request_id`.\n\nVelikost požadavku: tělo požadavku může mít nejvýše 6 MB (limit datové části Lambda; samotná API Gateway končí na 10 MB). Větší tělo je odmítnuto dřív, než se dostane ke kódu API, takže tato odpověď tento tvar nemá.\n\n| HTTP | code | Význam |\n| --- | --- | --- |\n| 400 | `MALFORMED_REQUEST` | Tělo není platný JSON (zpráva \"Request body is not valid JSON\"), nebo je požadavek neplatný: když `details.reason` uvádí, které pole a proč, `message` tento důvod opakuje, jinak zní \"The request is invalid.\" |\n| 400 | `MISSING_FIELD` | Chybí povinné pole. |\n| 400 | `INVALID_URL` | URL není platná URL http(s), je delší než 2048 znaků, nebo webhook_url není https. |\n| 400 | `INVALID_HASH` | certify-hash: hash nemá 64 šestnáctkových znaků. |\n| 400 | `INVALID_TIMESTAMP_TYPE` | options.timestamp_type není \"bitcoin\". |\n| 400 | `INVALID_VIEWPORT` | options.viewport není \"desktop\" ani \"mobile\". |\n| 400 | `METADATA_TOO_LARGE` | options.metadata má více než 10 klíčů, hodnotu, která není řetězec, nebo hodnotu delší než 500 znaků. |\n| 400 | `INVALID_EVIDENCE_PACK_OPTIONS` | options.evidence_pack je neplatné. |\n| 400 | `INVALID_BATCH` | urls dávky není pole 2 až 50 platných URL. |\n| 400 | `REDACTION_NO_OPS` | Začernění nemá žádné operace, nebo žádná z nich nic nenašla. |\n| 400 | `INVALID_CRON` | cron_expr nelze zpracovat. |\n| 400 | `INTERVAL_TOO_SHORT` | Interval automatického záznamu je pod minimem tarifu. |\n| 400 | `RATE_LIMIT_COST_TOO_HIGH` | Požadavek potřebuje více jednotek limitu počtu požadavků, než jedno okno dovoluje; `details.max_per_window`, `details.window_seconds`, `details.requested`. Rozdělte jej. |\n| 400 | `WEBHOOK_REQUIRES_API_KEY` | `webhook_url` byla odeslána z relace v dashboardu. Webhooky se podepisují tajným kódem webhooku klíče API, proto vyžadují klíč API. |\n| 401 | `MISSING_API_KEY` | Hlavička Authorization chybí nebo je chybně utvořená. `WWW-Authenticate: Bearer realm=\"ProofSnap API\"`. |\n| 401 | `INVALID_API_KEY` | Klíč je neznámý, zneplatněný nebo vypršel, nemá přístup k API, nebo je token relace neplatný či zneplatněný. `WWW-Authenticate: Bearer realm=\"ProofSnap API\", error=\"invalid_token\"`. |\n| 402 | `QUOTA_EXCEEDED` | Bylo dosaženo měsíčního maxima nebo příspěvku sandboxu (také v `error` certifikace na pozadí odmítnuté z tohoto důvodu). |\n| 402 | `PAYMENT_REQUIRED` | Ostré předplatné je po splatnosti nebo nezaplacené (také v `error` automatického záznamu přeskočeného z tohoto důvodu). |\n| 403 | `FORBIDDEN` | Prostředek patří někomu jinému, nebo akci smí provést jen vlastník. Zpráva: \"You do not have access to this resource.\" (details.reason uvádí podrobnosti tam, kde to pomůže). |\n| 403 | `EMAIL_NOT_VERIFIED` | Relace v dashboardu, jejíž e-mailová adresa není potvrzena, se pokusila vytvořit něco trvalého, placeného nebo něco, co zve další osoby (záznamy, dávky, porovnání, začernění, klíče API, tajné kódy webhooků, checkout, změny tarifu, změny míst, certify-hash, automatické záznamy, pozvánky do firmy, spisy a každou jejich změnu, členy spisů, záznamy přiřazené ke spisům, sdílení a jejich zrušení, zapečetění, exporty, právní blokace). Čtení zůstává povoleno. Zpráva: \"Confirm your email address first. Use the link we sent you, or send a new one from the dashboard.\" Stejně se odmítne klíč API, pokud e-mailová adresa jeho účtu není potvrzena. |\n| 403 | `EIDAS_REQUIRES_LIVE_KEY` | include_eidas odesláno s testovacím klíčem (za testovací se považuje i klíč ps_live_ účtu bez propojeného fakturačního účtu), nebo pro porovnání či začernění testovacího záznamu (`details.reason`). Ostrý klíč nebo relace, které běží jako testovací, protože není propojen fakturační účet, dostanou `details.reason` \"no_billing_account\". |\n| 403 | `MATTERS_NOT_ENABLED` | Spisy vyžadují tarif Legal. |\n| 403 | `SCHEDULE_LIMIT_REACHED` | Byl dosažen limit aktivních automatických záznamů tarifu (nebo tarif automatické záznamy nemá). |\n| 403 | `ON_CHANGE_REQUIRES_PLAN` | Tarif neumožňuje sledování on_change. |\n| 403 | `PLAN_ARCHIVE_ONLY` | Tarif Archive only udržuje vaše důkazy čitelné, ke stažení a ověřitelné; nevytváří žádné záznamy, automatické záznamy, certifikace, porovnání ani začernění. |\n| 403 | `PLAN_NOT_AVAILABLE` | Tento účet si tarif nemůže zvolit: Archive only se kupuje po skončení placeného předplatného API (dokud jsou důkazy ještě uchovány), nebo se k němu přejde změnou tarifu z developer, startup, growth, website_archive nebo legal_solo; firemní archive only jen vlastník firmy, jejíž předplatné skončilo, v rámci jejího okna pro stažení. `details.reason` uvádí důvod. |\n| 403 | `PLAN_API_READ_ONLY` | Tarif Website Archive: klíč API je jen pro čtení (výpis, stažení, ověření, webhooky). Záznamy, automatické záznamy a certifikace vytvářejte v dashboardu, nebo použijte tarif API. |\n| 403 | `LEGAL_HOLD_OWNER_ONLY` | Právní blokaci firemního záznamu ruší jen vlastník firmy (místo ji nastavit smí). |\n| 403 | `LEGAL_HOLD_NOT_AVAILABLE` | Nastavení právní blokace vyžaduje placený tarif (`details.reason` \"plan\": bezplatný sandbox nebo účet, jehož předplatné skončilo) a ostrý záznam (`details.reason` \"test_capture\": testovací záznam s vodoznakem). Zrušení blokace se z tohoto důvodu nikdy neodmítne. |\n| 403 | `IMPORT_NOT_ALLOWED` | Import balíčku vyžaduje tarif Legal (`details.reason` \"plan\") a ostrý klíč API nebo relaci v dashboardu s propojenou fakturací (`details.reason` \"live_credentials_required\"). |\n| 404 | `CAPTURE_NOT_FOUND` | Záznam neexistuje, byl smazán, nebo je ID chybně utvořené. |\n| 404 | `MATTER_NOT_FOUND` | Spis neexistuje, nebo nejste jeho členem. |\n| 404 | `IMPORT_NOT_FOUND` | Import neexistuje, patří jinému účtu, nebo je ID chybně utvořené. |\n| 404 | `WEBHOOK_SUBSCRIPTION_NOT_FOUND` | Odběr webhooku neexistuje, byl smazán, nebo patří jinému účtu. |\n| 404 | `SCHEDULE_NOT_FOUND` | Automatický záznam neexistuje, nebo patří jinému účtu. |\n| 404 | `NOT_FOUND` | Jiný prostředek nenalezen (formát hashe v ledgeru, token sdílení, úloha exportu, člen). |\n| 404 | `EXPORT_JOB_NOT_FOUND` | Úloha exportu záznamů neexistuje, patří jinému účtu, vypršela, nebo byla vyžádána testovacím klíčem. |\n| 405 | `METHOD_NOT_ALLOWED` | Metoda HTTP není pro tuto trasu povolena. |\n| 409 | `CAPTURE_PROCESSING` | Záznam se stále zpracovává a zatím jej nelze smazat (ani změnit jeho právní blokaci). |\n| 409 | `CAPTURE_LEGAL_HOLD` | Záznam je pod právní blokací a nelze jej smazat. |\n| 409 | `CAPTURE_IN_TRASH` | Právní blokace: záznam je v koši; nejprve jej obnovte. |\n| 409 | `CAPTURE_HOLD_GRACE` | Trvalé smazání během ochranné lhůty po zrušení právní blokace záznamu; `details.until`. Přesun do koše je povolen. |\n| 409 | `LEGAL_HOLD_MATTER` | Blokaci záznamu nastavila právní blokace jeho spisu, která stále trvá: zrušte ji na spisu (`details.matter_id` pro čtenáře spisu). |\n| 409 | `LEGAL_HOLD_SOURCE` | Blokace začernění nebo porovnání se řídí záznamem, ze kterého vzniklo (u porovnání kterýmkoli z porovnaných záznamů), a ten je stále pod právní blokací (nastavenou na tomto záznamu nebo prostřednictvím jeho spisu): balíček zůstává blokován, dokud se tato blokace nezruší (`details.source_capture_id`). |\n| 409 | `COMPANY_READ_ONLY` | Předplatné firmy skončilo (nebo je vedena jako firemní archiv): její spisy lze otevírat, exportovat a rušit jejich odkazy ke sdílení, nic jiného, a z jejích záznamů se nic nového neodvozuje. |\n| 409 | `WEBHOOK_SUBSCRIPTION_LIMIT` | Byl dosažen limit aktivních odběrů webhooků tarifu (25 u tarifů API a Legal, 10 u Website Archive, 0 u Archive only a sandboxu); `details.limit`, `details.active`. |\n| 409 | `WEBHOOK_SECRET_ROTATION_PENDING` | Předchozí tajný kód webhooku je stále ve svém 24hodinovém období překryvu; `details.previous_secret_expires_at`. |\n| 409 | `IDEMPOTENCY_IN_PROGRESS` | První požadavek s tímto Idempotency-Key se stále přijímá. |\n| 409 | `COMPARE_NOT_READY` | Před porovnáním musí být oba záznamy dokončeny. |\n| 409 | `REDACTION_NOT_READY` | Před začerněním musí být zdrojový záznam dokončen. |\n| 409 | `MATTER_SEALED` | Spis (nebo spis záznamu) je zapečetěný a nelze jej měnit. |\n| 409 | `MATTER_SEALING` | Probíhá zapečetění spisu (nejvýše 60 s): mezitím nelze přiřazovat záznamy, přejmenovávat, měnit členy, přesouvat propojený záznam do koše ani spustit druhé zapečetění. `Retry-After`. |\n| 409 | `MATTER_ARCHIVED` | Spis je archivovaný: žádné nové záznamy, přejmenování, noví členové, sdílení ani export; nejprve jej znovu otevřete (PATCH status \"open\"). Odebrání záznamu nebo člena stále funguje. |\n| 409 | `MATTER_CHANGED` | Protokol řetězce úschovy se během zapečetění změnil; nic nebylo zapečetěno, zkuste to znovu. |\n| 409 | `MATTER_LINKED` | Smazání záznamu: záznam je přílohou spisu, do kterého volající již nepatří. Vlastník spisu jej musí nejprve ze spisu odebrat. |\n| 409 | `MATTER_HAS_TRASHED_CAPTURES` | Zapečetění spisu: některý záznam spisu je v koši. Obnovte jej nebo jej ze spisu odeberte a pak spis zapečeťte znovu. |\n| 409 | `MEMBER_HAS_INDIVIDUAL_SUBSCRIPTION` | Pozvánka do firmy: vlastní předplatné API pozvané osoby se stále obnovuje. Pozvaný jej zruší a vlastník jej pak pozve znovu. |\n| 409 | `IMPORT_LIMIT` | Již probíhají 3 importy (nahrávání nebo ověřování); `details.limit`, `details.in_progress`. |\n| 409 | `IMPORT_STATE` | Import není ve stavu, který by to umožňoval (complete nebo cancel importu, který se již nenahrává); `details.status`. |\n| 409 | `EXPORT_JOB_RUNNING` | Export vašich záznamů se stále připravuje; `details.job_id` a `details.poll_path` jej označují. Nový spusťte, až skončí. |\n| 413 | `IMPORT_TOO_LARGE` | Balíček je větší než 2 GiB; `details.max_bytes`. |\n| 413 | `VERIFY_PACKAGE_TOO_LARGE` | POST /captures/{capture_id}/verify: uložený balíček přesahuje 256 MiB; ověřte jej offline přiloženými skripty. `details.size_bytes`, `details.limit_bytes`. |\n| 422 | `IDEMPOTENCY_KEY_REUSED` | Idempotency-Key byl znovu použit s jiným tělem nebo v jiném prostředí klíče (live nebo test). |\n| 422 | `SSRF_BLOCKED` | URL míří na privátní, loopback, link-local nebo jinak blokovanou adresu. |\n| 422 | `TARGET_UNREACHABLE` | Název hostitele z URL nemá žádné záznamy DNS, nebo jej nelze přeložit. |\n| 422 | `REDACTION_SCREENSHOT_UNREADABLE` | Snímek obrazovky nelze pro začernění rámečkem dekódovat. |\n| 422 | `REDACTION_LEAK_DETECTED` | Začerňovaný výraz přetrval začernění mimo URL záznamu; nic nebylo vydáno. `details.files`, `details.rule_indexes`, `details.metadata_fields`, `details.in_capture_url`. |\n| 422 | `REDACTION_SOURCE_UNSUPPORTED` | Začernit lze jen záznamy webových stránek. `details.source` nebo `details.manifest_type`. |\n| 422 | `REDACTION_SOURCE_INTEGRITY_FAILED` | Soubor zdrojového záznamu neodpovídá SHA-256 uvedenému v jeho podepsaném manifestu, nebo chybí; nic nebylo vydáno. `details.mismatched`, `details.missing`. |\n| 422 | `COMPARE_PROFILE_MISMATCH` | POST /compare: oba záznamy byly pořízeny s jiným profilem zařízení nebo jiným nastavením záznamu; `details.differing`, `details.before`, `details.after`. Pro porovnání i přesto pošlete allow_profile_mismatch: true (výsledek pro text a obrázky je pak neurčený). |\n| 422 | `COMPARE_URL_MISMATCH` | POST /compare: oba záznamy zachycují různé stránky; `details.before`, `details.after` (url a final_url jako origin a cesta). Pro porovnání i přesto pošlete allow_url_mismatch: true. |\n| 422 | `RULE902_NOT_AVAILABLE_FOR_MISMATCH` | POST /compare: include_rule_902 u záznamů vykreslených odlišně (allow_profile_mismatch); `details.differing`. |\n| 422 | `COMPARE_SOURCE_INTEGRITY_FAILED` | Soubor zdrojového záznamu z POST /compare neodpovídá SHA-256 uvedenému v jeho podepsaném manifestu, nebo chybí; nic nebylo porovnáno ani účtováno. `details.capture_id`, `details.mismatched`, `details.missing`, `details.sources[]`. |\n| 422 | `REDACTION_PATTERN_TOO_SLOW` | Regulární výraz v text_redactions běžel na této stránce příliš dlouho (katastrofický backtracking); nic nebylo vydáno ani účtováno. `details.rule_index`. Výraz zjednodušte. |\n| 422 | `IMPORT_SIZE_MISMATCH` | Nahraný balíček nemá ohlášenou velikost size_bytes; nahrávání bylo zahozeno. `details.expected`, `details.actual`. |\n| 422 | `IMPORT_NOT_SUPPORTED` | Porovnání nebo začernění importovaného balíčku důkazů. |\n| 429 | `RATE_LIMITED` | Příliš mnoho požadavků v aktuálním okně, nebo byl dosažen denní strop pro vytvoření spisu (200), zapečetění (20), export (50), pozvánky členů (50) nebo importy balíčků (50, `import_create`) (`details.daily_limit`, `details.action`). `Retry-After` uvádí, kdy to zkusit znovu. |\n| 429 | `CONCURRENT_CAPTURE_LIMIT` | Současně běží příliš mnoho záznamů účtu (developer 10, startup 25, growth 100, legal_solo a legal_seats 25, custom 200, website_archive 25, sandbox 5). Dávka spustí tolik URL, kolik se vejde, a zbytek uvede v `not_admitted`; když není volné žádné místo, odmítne se celý požadavek. `details.limit`, `details.in_flight`, `details.requested`, `Retry-After`. |\n| 429 | `TEST_MODE_DAILY_LIMIT` | Práce v testovacím režimu (testovací klíč nebo relace bez propojené fakturace; s vodoznakem, neúčtuje se) je omezena na 200 jednotek na účet a den UTC (dávka počítá své URL). `details.used`, `details.limit`, `details.reset_at`, `Retry-After`. |\n| 429 | `IMPORT_DAILY_BYTES_LIMIT` | Import balíčku: byl dosažen objem importu účtu za den UTC (5 GiB ohlášených velikostí). `details.period`, `details.limit_bytes`, `details.used_bytes`, `details.requested_bytes`, `details.reset_at`. |\n| 429 | `IMPORT_MONTHLY_BYTES_LIMIT` | Import balíčku: byl dosažen objem importu účtu za měsíc UTC (20 GiB). Stejné podrobnosti. |\n| 500 | `INTERNAL_ERROR` | Neočekávaná chyba. Opakujte s postupně prodlužovaným odstupem. |\n| 500 | `CAPTURE_FAILED` | Záznam se nepodařilo spustit, nebo (v `error` neúspěšného záznamu) dokončit. |\n| 500 | `CAPTURE_TIME_BUDGET_EXCEEDED` | V `error` neúspěšného záznamu nebo u synchronního začernění: běhu došel časový rozpočet a žádný balíček nebyl vydán ani účtován. |\n| 500 | `CAPTURE_SCREENSHOT_TIMEOUT` | V `error` neúspěšného záznamu: prohlížeč nedokončil vykreslení snímku obrazovky: všechny způsoby jeho pořízení (jedním snímkem, menšími pruhy, vlastním snímkem prohlížeče) vypršely, stejně jako jeden opakovaný pokus v nově spuštěném prohlížeči, pokud na něj zbýval časový rozpočet. Nic nebylo účtováno; zkuste to znovu. |\n| 500 | `CERTIFY_FAILED` | V `error` neúspěšné certifikace: certifikaci se nepodařilo dokončit. |\n| 500 | `REDACTION_FAILED` | V `error` neúspěšného začernění: začernění se nepodařilo dokončit. Začernění odmítnuté ze známého důvodu nese místo toho kód tohoto důvodu (například REDACTION_LEAK_DETECTED). |\n| 500 | `TIMESTAMP_SERVICE_UNAVAILABLE` | Zapečetění spisu: ukotvení OpenTimestamps selhalo; nic se nezměnilo, zkuste to znovu. |\n| 500 | `CONFIGURATION_ERROR` | Krok na straně serveru selhal nebo není nakonfigurován (`details.reason`). |\n| 503 | `SERVICE_UNAVAILABLE` | Autentizace je dočasně nedostupná (přihlašovací údaje nebylo možné ověřit). Neukládá se do mezipaměti; zkuste to znovu. |\n| 503 | `EIDAS_UNAVAILABLE` | Bylo požadováno include_eidas, ale časová razítka eIDAS nejsou nakonfigurována. |\n| 503 | `EIDAS_SEAL_RETRY` | Zapečetění spisu: časové razítko eIDAS nedorazilo včas; nic nebylo zapečetěno. Zkuste to znovu po `Retry-After`; opakovaný pokus použije již vydané časové razítko. |\n| 503 | `LIMIT_CHECK_UNAVAILABLE` | Zapečetění spisu: jeho denní limit nebylo možné ověřit; nic se neprovedlo. Zkuste to znovu. |\n| 504 | `UPSTREAM_TIMEOUT` | Synchronní krok zpracování (certify-hash, export spisu) neodpověděl včas. Může se ještě dokončit: sledujte to, co uvádí `details` (`certify_id`, `poll_path`), nebo to zkuste znovu. |\n| 404 | `ORG_INVITE_NOT_FOUND` | Pozvánka do firmy, která je neznámá, je určena někomu jinému, již nečeká na vyřízení, nebo jejíž firma již nefunguje (details.reason `company_inactive`). |\n| 409 | `ORG_INVITE_NO_SEATS` | Přijetí pozvánky do firmy: všechna místa firmy jsou obsazena; pozvánka zůstává otevřená. |\n| 409 | `ORG_INVITE_IN_OTHER_ORG` | Přijetí pozvánky do firmy: volající má místo v jiné firmě; pozvánka zůstává otevřená. |\n| 409 | `ORG_INVITE_HAS_SUBSCRIPTION` | Přijetí pozvánky do firmy: vlastní předplatné API volajícího se stále obnovuje; pozvánka zůstává otevřená. |\n| 409 | `ORG_OWNER_CANNOT_LEAVE` | Vlastník firmy se pokusil opustit vlastní firmu. |\n| 410 | `ORG_INVITE_EXPIRED` | Přijetí pozvánky do firmy starší než 7 dní. |",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "Strojově čitelný kód chyby (UPPER_SNAKE_CASE)."
              },
              "message": {
                "type": "string",
                "description": "Zpráva čitelná pro člověka."
              },
              "details": {
                "type": "object",
                "additionalProperties": true,
                "description": "Nepovinný doplňující kontext, například `reason`, `field` nebo `retry_after_seconds`."
              }
            },
            "required": [
              "code",
              "message"
            ]
          },
          "request_id": {
            "type": "string",
            "description": "ID požadavku."
          }
        },
        "example": {
          "error": {
            "code": "INVALID_URL",
            "message": "URL is not a valid http(s) URL",
            "details": {
              "reason": "Only http and https schemes are allowed"
            }
          },
          "request_id": "..."
        }
      },
      "CaptureOptions": {
        "type": "object",
        "description": "Volby záznamu. Všechna pole jsou nepovinná.",
        "properties": {
          "scroll_full_page": {
            "type": "boolean",
            "description": "Zachytí celou posouvatelnou stránku. false zachytí pouze viditelnou oblast (viewport).",
            "default": true
          },
          "expand_collapsed": {
            "type": "boolean",
            "description": "Před pořízením snímku obrazovky rozbalí sbalené sekce: zavřené prvky <details>, tlačítka akordeonů a rozbalovacích sekcí (aria-expanded s aria-controls) a textové ovládací prvky \"see more\" / \"show replies\". S pojistkami: nic uvnitř navigace, hlaviček, nabídek ani dialogů, žádné odkazy na jinou URL, žádné odeslání formuláře, žádné popisky měnící stav (like, follow, buy, delete, ...), každý prvek nejvýše jednou, a prvek, který se pokusí opustit stránku, rozbalování zastaví a znovu se načte původní URL. Výsledek se zaznamenává pro každý prvek do forensic_log.json (page_modifications.expand_collapsed: nalezené, otevřené, ponechané zavřené, důvody přeskočení, spuštěné požadavky, výška stránky před a po) se souhrnem v metadata.json (expand_collapsed: requested, opened_total, left_closed_total); evidence.pdf a certifikáty uvádějí jen to, co bylo skutečně otevřeno.",
            "default": true
          },
          "viewport": {
            "type": "string",
            "description": "desktop je 1920x1080 s poměrem pixelů 1; mobile je 390x844 s poměrem pixelů 3 a user agentem mobilního Safari. Jiné hodnoty vrátí 400 INVALID_VIEWPORT.",
            "enum": [
              "desktop",
              "mobile"
            ],
            "default": "desktop"
          },
          "viewport_width": {
            "type": "number",
            "minimum": 320,
            "maximum": 3840,
            "description": "Vlastní šířka zobrazované oblasti v pixelech CSS. Musí se poslat společně s viewport_height, jinak 400 MALFORMED_REQUEST."
          },
          "viewport_height": {
            "type": "number",
            "minimum": 240,
            "maximum": 4320,
            "description": "Vlastní výška zobrazované oblasti v pixelech CSS. Musí se poslat společně s viewport_width."
          },
          "device_scale_factor": {
            "type": "number",
            "minimum": 1,
            "maximum": 3,
            "description": "Poměr pixelů zařízení u snímku obrazovky."
          },
          "wait_for_selector": {
            "type": "string",
            "description": "Před pořízením záznamu počká až 10 sekund na tento selektor CSS. Pokud se neobjeví, záznam pokračuje bez chyby. Zaznamenává se do page_modifications ve forensic_log.json.",
            "maxLength": 200
          },
          "wait_ms": {
            "type": "number",
            "minimum": 0,
            "maximum": 15000,
            "description": "Dodatečné čekání v milisekundách po načtení stránky."
          },
          "screenshot_format": {
            "type": "string",
            "description": "jpeg dodá screenshot.jpeg; png dodá bezeztrátový screenshot.png. C2PA Content Credentials se přidávají jen ke snímkům obrazovky ve formátu JPEG.",
            "enum": [
              "jpeg",
              "png"
            ],
            "default": "jpeg"
          },
          "url_stamp": {
            "type": "boolean",
            "description": "Přidá nad obraz stránky záhlaví s URL zachycené stránky, časem pořízení záznamu v UTC (okamžik, kdy prohlížeč vytvořil snímek obrazovky; u dlouhé stránky snímané po pásech okamžik, kdy vznikl poslední pás) a ID důkazu, označené jako softwarová anotace. Záhlaví se přidává nad obraz, takže nezakrývá žádný pixel stránky. chain_of_custody.json zaznamenává screenshot_url_header.raw_screenshot_sha256 spolu s raw_screenshot_source: u stránky nasnímané vcelku (browser_image, browser_png, browser_jpeg_joined, browser_jpeg_reencoded) je to SHA-256 obrazu stránky, jak ho vytvořil prohlížeč, před přidáním záhlaví; u dlouhé stránky nasnímané po pásech a spojené (joined_bands, joined_bands_lossless, joined_bands_reencoded) SHA-256 spojeného obrazu, jak ho ProofSnap zapsal i se záhlavím, před přidáním C2PA Content Credentials. Pokud záhlaví nelze přidat (obraz by s ním přesáhl 65 535 px, které JPEG pojme, jeho vykreslení selhalo, nebo, pouze u záložní cesty pořízení snímku obrazovky, má obraz stránky přes 32 000 000 pixelů), dodá se snímek obrazovky bez něj: metadata.json to zaznamená v screenshot.url_stamp_skipped a chain_of_custody.json v screenshot_url_header (applied false, s důvodem).",
            "default": false
          },
          "network_log": {
            "type": "boolean",
            "description": "Zahrne network.har (HAR s hlavičkami požadavků a odpovědí a časováním, bez těl) a network.original.har.",
            "default": true
          },
          "warc": {
            "type": "boolean",
            "description": "Zahrne capture.warc (ISO 28500) s transakcemi HTTP při načítání stránky. Těla odpovědí se čtou v časovém limitu (nejvýše 30 s, a jen dokud to dovolí nepovinná část časového rozpočtu záznamu, po odečtení času vyhrazeného pro eIDAS, C2PA a závěrečné odečtení času); tělo useknuté tímto limitem se uloží prázdné s WARC-Truncated: time, odpověď, na kterou nedošlo, se vynechá, a warc_captured v chain_of_custody.json (a warc ve forensic_log.json) zaznamená truncated, truncation_reason, response_pairs, records_total a počty.",
            "default": false
          },
          "external_archive": {
            "type": "boolean",
            "description": "Požádá službu Save Page Now z Internet Archive o archivaci URL (Internet Archive tuto kopii uchovává veřejně). Výsledek se třídí podle toho, čí požadavek snímek vytvořil, a podle jeho času vůči požadavku: created (vytvořen pro tento požadavek), recent_existing (Internet Archive odpověděl dřívějším snímkem), created_after_request (existuje novější snímek, ale požadavek nebyl potvrzen), existing (existuje pouze starší snímek), pending, rate_limited, failed (Internet Archive požadavek odmítl), unconfirmed (žádná odpověď ho nepotvrdila ani neodmítla a žádný snímek není znám), unavailable, skipped, skipped_sensitive nebo skipped_query. URL, které vypadají, že obsahují přihlašovací údaje, nebo nesou parametry, názvy parametrů či segmenty cesty podobné tokenům, se nikdy neodesílají. URL s řetězcem dotazu se odešle pouze tehdy, když je tato volba výslovně nastavena na true; s výchozí hodnotou se přeskočí (skipped_query). Výsledek se zaznamená ve forensic_log.json (external_archive, se snapshot_offset_seconds vůči záznamu) a v chain_of_custody.json a GET /captures/{capture_id} ho vrací jako external_archive. Pro soukromé URL nastavte false. Požadavek se odešle, jakmile se stránka načte, souběžně se zbytkem záznamu. Selhání nezpůsobí selhání záznamu.",
            "default": true
          },
          "dismiss_consent": {
            "type": "boolean",
            "description": "Před načtením stránky nastaví souhlasové cookies „přijmout vše“ a pokusí se zavřít lišty se souhlasem s cookies. Tím se stránka mění, proto je volba ve výchozím stavu vypnutá; co bylo provedeno, se zaznamená do forensic_log.json consent_dismissal.",
            "default": false
          },
          "dismiss_popups": {
            "type": "boolean",
            "description": "Zavře překryvná okna s newslettery, akcemi a podobná okna pomocí jejich vlastního ovládacího prvku pro zavření. Počet zavřených oken a použité ovládací prvky se zaznamenají ve forensic_log.json page_modifications. Každé zavřené okno se zaznamená ve forensic_log.json page_modifications (popups_dismissed, popups_dismissed_controls); evidence.pdf uvádí, kolik jich bylo zavřeno.",
            "default": false
          },
          "dark_mode": {
            "type": "boolean",
            "description": "Vykreslí stránku v tmavém barevném schématu. Mění vzhled stránky; zaznamená se v page_modifications v forensic_log.json. Uvádí se v evidence.pdf a v page_modifications v forensic_log.json.",
            "default": false
          },
          "block_ads": {
            "type": "boolean",
            "description": "Blokuje požadavky na známé reklamní a sledovací hostitele. Část obsahu tím chybí; zaznamenává se ve forensic_log.json page_modifications.",
            "default": false
          },
          "block_resources": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "image",
                "font",
                "media",
                "stylesheet"
              ]
            },
            "description": "Typy zdrojů, které se mají blokovat. Část obsahu tím chybí; zaznamená se v page_modifications v forensic_log.json."
          },
          "inject_css": {
            "type": "string",
            "description": "CSS přidané na stránku před pořízením záznamu. Mění stránku; ukládá se doslovně ve forensic_log.json page_modifications. Vždy se ukládá doslovně ve forensic_log.json page_modifications (injected_css) s injected_css_status `applied` nebo `failed` a injected_css_error. evidence.pdf uvádí, že bylo vloženo vlastní CSS; samotný kód netiskne.",
            "maxLength": 10000
          },
          "inject_js": {
            "type": "string",
            "description": "JavaScript spuštěný na stránce před pořízením záznamu. Mění stránku. Vždy se ukládá doslovně do forensic_log.json page_modifications (injected_js) spolu s injected_js_status a injected_js_error: `applied` (doběhl do konce), `invalid` (nepodařilo se ho zkompilovat, například kvůli syntaktické chybě, takže se nikdy nespustil a stránku nezměnil), `failed` (během běhu vyhodil výjimku, takže mohl stránku změnit, než se zastavil) nebo `timed_out` (záznam na něj po 5 sekundách přestal čekat; skript mohl dál běžet a stránku měnit). evidence.pdf uvádí výsledek a odkazuje na forensic_log.json a certifikát původu uvádí vložený kód mezi úpravami stránky, pokud nebyl `invalid`; ani jeden z nich kód nevypisuje.",
            "maxLength": 10000
          },
          "locale": {
            "type": "string",
            "description": "Národní prostředí prohlížeče k emulaci, například de nebo de-DE (nastaví jazyk prohlížeče a Accept-Language). Pouze emulace: nepoužívá se proxy, takže obsah závislý na IP adrese návštěvníka dál odpovídá regionu serveru, který záznam pořizuje. Zaznamenává se v metadata.json geo.",
            "pattern": "^[a-z]{2}(-[A-Z]{2})?$"
          },
          "timezone": {
            "type": "string",
            "description": "Časové pásmo prohlížeče k emulaci (název IANA, například Europe/Berlin). Pouze emulace."
          },
          "language": {
            "type": "string",
            "description": "Jazyk PDF čitelných pro člověka. Jedna z hodnot: en, de, it, fr, es, pt_BR, cs, el, hi, hu, id, ja, ko, nl, pl, ro, ru, sv, tr, vi, zh_CN, zh_TW, ar, he, da, fi, nb, sk, uk. Velikost písmen, spojovník a region se tolerují (\"DE\", \"fr-FR\" a \"PT-BR\" se přijmou); samotné \"pt\" a \"zh\" se odmítnou. Nepodporovaná hodnota vrátí 400 MALFORMED_REQUEST.",
            "default": "en",
            "example": "de"
          },
          "timestamp_type": {
            "type": "string",
            "description": "Přijímá se jen \"bitcoin\" (ukotvení přes OpenTimestamps se zkouší vždy). Jakákoli jiná hodnota vrátí 400 INVALID_TIMESTAMP_TYPE. Pro kvalifikované časové razítko použijte include_eidas.",
            "enum": [
              "bitcoin"
            ],
            "default": "bitcoin"
          },
          "include_eidas": {
            "type": "boolean",
            "description": "Navíc si vyžádá kvalifikované elektronické časové razítko eIDAS (RFC 3161) nad SHA-256 souboru manifest.json, dodané jako manifest.json.tsr (plus eidas_validation.json, pokud jsou vrácena validační data). Pouze ostré klíče: testovací klíč vrátí 403 EIDAS_REQUIRES_LIVE_KEY. Pokud nasazení nemá nakonfigurovanou službu eIDAS, odmítne se požadavek s 503 EIDAS_UNAVAILABLE dříve, než se cokoli vyúčtuje. Před použitím tokenu ho ProofSnap zkontroluje (podpis, hash, který nese, řetězec certifikátů ke kořenové CA Disig QCA4, stav certifikátu TSA) a tuto kontrolu zaznamená v eidas_validation.json (verification). Pokud požadavek na časové razítko během záznamu selže nebo token kontrolou neprojde, dodá se balíček bez něj, pouze s ukotvením OpenTimestamps, razítko se neúčtuje a timestamps.eidas (řádek záznamu, GET /captures/{capture_id}, webhook completed) uvádí stav not_obtained s důvodem (token_refused, unavailable nebo time_budget). Od snímku obrazovky dál nechávají nepovinné kroky záznamu (těla WARC, odpovědi archivu a WHOIS, podpis C2PA, druhé odečtení času) prostor pro razítko a vynechávají se jako první. Účtuje se za každé razítko.",
            "default": false
          },
          "include_rule_902": {
            "type": "boolean",
            "description": "Přidá rule_902_certification.pdf: nepodepsanou šablonu certifikace podle [FRE 902(13)/(14)](https://www.govinfo.gov/content/pkg/USCODE-2023-title28/html/USCODE-2023-title28-app-federalru-dup2-rule902.htm) a [28 U.S.C. 1746](https://www.govinfo.gov/content/pkg/USCODE-2023-title28/html/USCODE-2023-title28-partV-chap115-sec1746.htm), kterou osoba vyplní a podepíše. Její SHA-256 je uveden v manifest.json. Přidá se také, když má evidence_pack.custodian neprázdnou hodnotu. Pokud se ji nepodaří vygenerovat, záznam se dokončí bez ní. Momentálně vypnuto: šablona certifikace je dočasně vypnutá, takže se toto pole přijme a ignoruje (rule_902_certification.pdf se nevygeneruje ani neuvede v balíčku) a odpověď nese varování RULE902_DISABLED.",
            "default": false
          },
          "case_reference": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PlainText"
              }
            ],
            "description": "Označení vašeho spisu nebo případu. Bílé znaky se slučují. Řídí se pravidlem prostého textu (viz PlainText). Zaznamenává se do metadata.json, forensic_log.json a chain_of_custody.json a tiskne se na evidence.pdf.",
            "maxLength": 200
          },
          "case_id": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PlainText"
              }
            ],
            "description": "Identifikátor případu ve vašem systému. Zaznamenává se stejně jako case_reference; řídí se pravidlem prostého textu (viz PlainText).",
            "maxLength": 200
          },
          "case_note": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PlainText"
              }
            ],
            "description": "Poznámka ve volném textu. Řídí se pravidlem prostého textu (viz PlainText). Zaznamená se do metadata.json, forensic_log.json a chain_of_custody.json (legal_context.note).",
            "maxLength": 500
          },
          "webhook_url": {
            "type": "string",
            "description": "https URL, na kterou přichází capture.completed nebo capture.failed. Viz Webhooky. URL musí být https a nesmí směřovat na privátní, loopback, link-local, carrier-grade NAT ani cloudovou metadatovou adresu (stejná pravidla jako u URL záznamu; jinak 422 SSRF_BLOCKED). Prázdná hodnota nebo hodnota jen z mezer znamená bez webhooku. Vyžaduje klíč API: při odeslání z relace dashboardu je odmítnuta s 400 WEBHOOK_REQUIRES_API_KEY, protože webhooky se podepisují tajným kódem webhooku daného klíče.",
            "format": "uri"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "maxProperties": 10,
            "description": "Až 10 textových štítků (hodnoty až 500 znaků), vracených se záznamem. Porušení vrací 400 METADATA_TOO_LARGE."
          },
          "evidence_pack": {
            "type": "object",
            "properties": {
              "enabled": {
                "type": "boolean",
                "description": "false vynechá certifikační stránku z evidence.pdf.",
                "default": true
              },
              "jurisdiction": {
                "type": "string",
                "description": "Zaznamená se ve forensic_log.json (options). Jiný účinek nemá.",
                "enum": [
                  "US-Federal",
                  "EU-eIDAS"
                ],
                "default": "US-Federal"
              },
              "custodian": {
                "type": "object",
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Přijímá se; v šabloně se netiskne, pole deklaranta v ní zůstávají prázdná pro osobu, která ji podepíše.",
                    "maxLength": 200
                  },
                  "law_firm": {
                    "type": "string",
                    "description": "Přijímá se; v šabloně se netiskne, pole deklaranta v ní zůstávají prázdná pro osobu, která ji podepíše.",
                    "maxLength": 200
                  },
                  "role": {
                    "type": "string",
                    "description": "Přijímá se; šablona ho nepoužívá.",
                    "maxLength": 200
                  },
                  "case_caption": {
                    "type": "string",
                    "description": "Přijímá se; šablona ho nepoužívá.",
                    "maxLength": 200
                  }
                },
                "additionalProperties": false,
                "description": "Každá hodnota se řídí pravidlem prostého textu (viz PlainText); jinak 400 INVALID_EVIDENCE_PACK_OPTIONS."
              }
            },
            "description": "Neplatné hodnoty vrátí 400 INVALID_EVIDENCE_PACK_OPTIONS."
          }
        }
      },
      "CaptureRequest": {
        "type": "object",
        "required": [
          "url"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "Stránka k zachycení. Jen http nebo https, nejvýše 2048 znaků. Privátní, loopback, link-local a metadatové adresy se odmítnou s 422 SSRF_BLOCKED a hostitel bez záznamů DNS vrátí 422 TARGET_UNREACHABLE.",
            "format": "uri",
            "maxLength": 2048
          },
          "options": {
            "$ref": "#/components/schemas/CaptureOptions"
          },
          "private_note": {
            "$ref": "#/components/schemas/PrivateNote"
          }
        },
        "example": {
          "url": "https://example.com",
          "options": {
            "case_reference": "Smith v. Jones",
            "webhook_url": "https://your-app.example/webhooks/proofsnap"
          }
        }
      },
      "CaptureAccepted": {
        "type": "object",
        "properties": {
          "capture_id": {
            "type": "string",
            "example": "cap_a1B2c3D4e5F6g7H8"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing"
            ]
          },
          "url": {
            "type": "string"
          },
          "poll_path": {
            "type": "string",
            "description": "Cesta ke stavu včetně stage /v1, například /v1/captures/cap_..."
          },
          "message": {
            "type": "string"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "private_note": {
            "type": "string",
            "description": "Soukromá poznámka v uložené (normalizované) podobě, uvedená jen tehdy, když byla odeslána."
          },
          "warnings": {
            "$ref": "#/components/schemas/Rule902DisabledWarnings"
          }
        }
      },
      "CaptureResult": {
        "type": "object",
        "description": "Záznam, certifikát, porovnání nebo začernění. Pole závisí na hodnotě status.",
        "properties": {
          "capture_id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "processing",
              "completed",
              "failed"
            ]
          },
          "url": {
            "type": "string",
            "description": "URL zachycené stránky (null u certifikátů a porovnání).",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "batch_id": {
            "type": "string",
            "nullable": true
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "type": {
            "type": "string",
            "description": "comparison u porovnání, import u importovaného balíčku důkazů.",
            "enum": [
              "comparison",
              "import"
            ]
          },
          "compared": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Jen u porovnání: ID obou zdrojových záznamů."
          },
          "diff_summary": {
            "$ref": "#/components/schemas/DiffSummary"
          },
          "estimated_completion_seconds": {
            "type": "integer",
            "description": "Jen u processing: hrubý odhad, nejméně 5."
          },
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "CAPTURE_FAILED",
                  "CAPTURE_TIME_BUDGET_EXCEEDED",
                  "CAPTURE_SCREENSHOT_TIMEOUT",
                  "SSRF_BLOCKED",
                  "TARGET_UNREACHABLE",
                  "PAYMENT_REQUIRED",
                  "COMPARE_PROFILE_MISMATCH",
                  "COMPARE_URL_MISMATCH",
                  "RULE902_NOT_AVAILABLE_FOR_MISMATCH",
                  "COMPARE_SOURCE_INTEGRITY_FAILED",
                  "QUOTA_EXCEEDED",
                  "CERTIFY_FAILED",
                  "REDACTION_FAILED"
                ],
                "description": "Veřejný důvod selhání (viz tabulka chyb). CAPTURE_SCREENSHOT_TIMEOUT: prohlížeč nedokončil snímek obrazovky; CAPTURE_TIME_BUDGET_EXCEEDED: běh vyčerpal celý svůj časový rozpočet; ani jedno se neúčtuje. Řádek porovnání (cmp_) může selhat také s COMPARE_SOURCE_INTEGRITY_FAILED (zdrojový balíček byl změněn po přijetí požadavku), COMPARE_PROFILE_MISMATCH nebo COMPARE_URL_MISMATCH (zjištěno až v zapečetěných údajích, které běh porovnává) nebo RULE902_NOT_AVAILABLE_FOR_MISMATCH; jednotka se vrací. Certifikace hashe spuštěná na pozadí selže s QUOTA_EXCEEDED, když je v okamžiku spuštění dosaženo měsíčního maxima. CERTIFY_FAILED a REDACTION_FAILED: certifikaci hashe nebo začernění nebylo možné dokončit; opakujte požadavek."
              },
              "message": {
                "type": "string"
              }
            },
            "description": "Jen u failed."
          },
          "failed_at": {
            "type": "string",
            "description": "Jen u failed.",
            "format": "date-time"
          },
          "captured_at": {
            "type": "string",
            "description": "Kdy byla stránka zachycena (jen dokončené řádky). U začernění čas pořízení jeho zdrojového záznamu (redacted_at udává, kdy bylo začernění provedeno).",
            "format": "date-time"
          },
          "redacted_at": {
            "type": "string",
            "format": "date-time",
            "description": "Jen začernění: kdy začernění vzniklo. captured_at začernění je čas pořízení jeho zdrojového záznamu."
          },
          "compared_at": {
            "type": "string",
            "nullable": true,
            "format": "date-time",
            "description": "Jen u porovnání: kdy bylo porovnání provedeno. Pole captured_at nese stejnou hodnotu (ponecháno kvůli starším klientům); používejte compared_at."
          },
          "package_url": {
            "type": "string",
            "description": "Jen completed: předem podepsaný odkaz ke stažení ZIP balíčku, platný až 24 hodin (viz package_url_expires_at); nový odkaz získáte opětovným načtením záznamu.",
            "format": "uri"
          },
          "package_url_expires_at": {
            "type": "string",
            "description": "Jen completed: kdy package_url přestane fungovat, nejvýše 24 hodin po této odpovědi (odkaz podepsaný dočasnými přístupovými údaji serveru může přestat fungovat dříve); nový odkaz získáte opětovným načtením záznamu.",
            "format": "date-time"
          },
          "verification_url": {
            "type": "string",
            "description": "Jen completed: odkaz na veřejný ověřovač ProofSnap.",
            "format": "uri"
          },
          "manifest_hash": {
            "type": "string",
            "description": "Jen completed: sha256:<hex> souboru manifest.json.",
            "example": "sha256:3f2a..."
          },
          "timestamps": {
            "$ref": "#/components/schemas/Timestamps"
          },
          "c2pa": {
            "type": "object",
            "properties": {
              "included": {
                "type": "boolean"
              },
              "signed_screenshot_sha256": {
                "type": "string",
                "description": "sha256:<hex> podepsaného snímku obrazovky.",
                "nullable": true
              }
            },
            "description": "Jen completed."
          },
          "file_count": {
            "type": "integer",
            "description": "Jen completed."
          },
          "size_bytes": {
            "type": "integer",
            "description": "Jen completed."
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "consent_gated"
                  ]
                },
                "reason": {
                  "type": "string",
                  "nullable": true
                },
                "final_host": {
                  "type": "string",
                  "nullable": true
                },
                "final_url": {
                  "type": "string",
                  "nullable": true
                },
                "message": {
                  "type": "string"
                },
                "remedy": {
                  "type": "object",
                  "properties": {
                    "option": {
                      "type": "string"
                    },
                    "value": {
                      "type": "boolean"
                    }
                  }
                }
              }
            },
            "description": "Jen completed, když záznam skončil na stěně souhlasu s cookies nebo na mezistránce místo samotné stránky. Spusťte znovu s dismiss_consent: true."
          },
          "external_archive": {
            "allOf": [
              {
                "$ref": "#/components/schemas/ExternalArchive"
              }
            ],
            "description": "Jen completed. Požadavek na Internet Archive podaný volbou external_archive: aktuální výsledek (status), stav zapečetěný v balíčku (status_at_sealing) a odkaz na snímek. { requested: false }, když požadavek nebyl podán."
          },
          "storage": {
            "$ref": "#/components/schemas/CaptureStorage"
          },
          "private_note": {
            "type": "string",
            "nullable": true,
            "description": "Vaše soukromá poznámka (viz PrivateNote). Vrací se jen tomu, kdo záznam pořídil; nikdy není součástí balíčku důkazů."
          },
          "legal_hold": {
            "type": "boolean",
            "description": "Záznam je pod právní blokací: dokud je true, nesmaže se (PATCH /captures/{capture_id} s action legal_hold). Zruší se automaticky a záznam se smaže, když předplatné skončilo a jeho 30 dní uplynulo bez plánu, který data uchovává."
          },
          "legal_hold_set_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Kdy byla aktuální právní blokace nastavena; null bez blokace."
          },
          "legal_hold_reason": {
            "type": "string",
            "nullable": true,
            "description": "Důvod uložený u aktuální právní blokace; null bez blokace nebo bez důvodu."
          },
          "legal_hold_set_by_email": {
            "type": "string",
            "nullable": true,
            "description": "Pouze vlastník firmy, u blokovaného firemního záznamu: e-mailová adresa toho, kdo právní blokaci nastavil."
          },
          "legal_hold_source": {
            "type": "string",
            "nullable": true,
            "description": "Odkud aktuální blokace pochází: \"manual\" (PATCH /captures/{capture_id}), \"bulk\" (POST /legal-holds), \"matter:<matter_id>\" (právní blokace spisu) nebo \"derived:<capture_id>\" (začernění nebo porovnání blokované proto, že je blokován záznam, ze kterého vzniklo). null bez blokace."
          },
          "legal_hold_released_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Kdy byla poslední blokace zrušena (začátek ochranné lhůty po zrušení); null, dokud blokace trvá nebo nebyla nikdy zrušena, a po automatickém zrušení na konci předplatného (bez ochranné lhůty)."
          },
          "deletion_blocked_until": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Konec ochranné lhůty po zrušení blokace: do té doby se záznam trvale nesmaže (trvalé DELETE vrací 409 CAPTURE_HOLD_GRACE, žádné čištění koše, žádné smazání v rámci retence); přesun do koše je možný. Mazání účtu a firmy po skončení předplatného na ni nečeká. null, když žádná lhůta neběží (také dokud trvá blokace: ta blokuje bez konce)."
          },
          "s3_legal_hold": {
            "type": "object",
            "nullable": true,
            "description": "Právní blokace S3 Object Lock uložených objektů balíčku (ZIP, aktualizovaný důkaz OpenTimestamps a samostatně uložená kopie, všechny verze). status: on, off, pending (nastavuje se), failed (server to zkouší znovu), unsupported (úložiště nemá konfiguraci Object Lock; blokace na záznamu přesto platí), none (není uložen žádný balíček, např. u neúspěšného záznamu).",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "on",
                  "off",
                  "pending",
                  "failed",
                  "unsupported",
                  "none"
                ]
              },
              "at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "source_held": {
            "type": "boolean",
            "nullable": true,
            "description": "Začernění a porovnání: true, když je záznam, ze kterého vznikly, pod právní blokací. Odvozený balíček se řídí blokací svého zdroje: dokud je zdroj blokován, je blokováno i začernění nebo porovnání (legal_hold_source derived:<capture_id>) a jeho blokaci nelze zrušit samostatně (409 LEGAL_HOLD_SOURCE). U ostatních záznamů null."
          },
          "import": {
            "$ref": "#/components/schemas/CaptureImport"
          },
          "source": {
            "type": "string",
            "description": "Jak byl záznam pořízen: api, schedule, certify-hash, compare, redact, import. GET /captures/{capture_id} ho vrací jen u importovaného balíčku (\"import\"); řádky GET /captures ho nesou vždy."
          }
        }
      },
      "Timestamps": {
        "type": "object",
        "properties": {
          "bitcoin_ots": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "description": "Stav důkazu Bitcoin OpenTimestamps v manifest.json.ots. pending_confirmation: důkaz čeká na blok Bitcoinu (obvykle několik hodin; kontroly začínají asi 2 hodiny po dokončení záznamu a opakují se v prodlužujících se intervalech). verified: blok Bitcoinu potvrzuje hash manifestu (block_height, block_time). not_present: balíček nemá manifest.json.ots (při zapečetění balíčku nebyly kalendáře dostupné). unconfirmed: během 7 dnů kontrol nebylo nalezeno žádné potvrzení; důkaz v balíčku lze stále aktualizovat a ověřit klientem OpenTimestamps (ots upgrade, ots verify). package_missing: balíček důkazů už v úložišti není, důkaz proto už nelze ověřovat. manifest_mismatch: manifest.json v uloženém balíčku neodpovídá hashi manifestu zaznamenanému při zapečetění; časové razítko pro něj není potvrzeno. Oba stavy jsou konečné. Samotný balíček se nikdy nemění. not_checked: záznam byl dokončen dříve, než existovaly automatické kontroly potvrzení, a nikdy nebyl zkontrolován; jeho balíček může přesto obsahovat manifest.json.ots, který klient OpenTimestamps dokáže aktualizovat a ověřit. Odpovědi webhooku a vytvoření se odesílají při dokončení, uvádějí proto pending_confirmation (nebo not_present, když kalendáře selhaly); aktuální stav zjistíte přes GET /captures/{capture_id}. Balíček se zapečetí s čekajícím důkazem: v tu chvíli už byl hash manifestu odeslán do kalendářů OpenTimestamps. Po potvrzení v bloku Bitcoinu {block_height} ({block_time} UTC) důkaz prokazuje, že manifest.json existoval nejpozději v tomto čase; stáhněte aktualizovaný důkaz (upgraded_proof_url) a uložte ho vedle manifest.json jako manifest.json.upgraded.ots, verify.sh a verify.ps1 ho pak zkontrolují automaticky.",
                "enum": [
                  "pending_confirmation",
                  "verified",
                  "not_present",
                  "unconfirmed",
                  "package_missing",
                  "manifest_mismatch",
                  "not_checked"
                ]
              },
              "block_height": {
                "type": "integer",
                "nullable": true,
                "description": "Výška bloku Bitcoinu, která důkaz potvrzuje. Nastaveno, když je status verified."
              },
              "block_time": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Čas tohoto bloku Bitcoinu. Jen GET /captures/{capture_id}, nastaveno, když je status verified."
              },
              "verified_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Kdy ProofSnap ukotvení potvrdil. Jen GET /captures/{capture_id}, nastaveno, když je status verified."
              },
              "upgraded_proof_url": {
                "type": "string",
                "format": "uri",
                "nullable": true,
                "description": "Pouze GET /captures/{capture_id}. Jakmile je ukotvení ověřeno, ProofSnap uloží důkaz OpenTimestamps aktualizovaný z kalendářů (obsahuje atestaci bloku Bitcoin, takže se ověří offline bez kontaktování jakéhokoli kalendáře). Toto je jeho předem podepsaný odkaz ke stažení, platný až 24 hodin stejně jako package_url; pro nový odkaz záznam načtěte znovu. null, pokud žádný není (ještě neověřeno, nebo uloženo později zpětným doplněním na pozadí). Zapečetěný balíček se nikdy nemění: soubor uložte vedle manifest.json balíčku jako manifest.json.upgraded.ots. Balíčky zapečetěné od 2026-09-29 ho ověřují přiloženými skripty (verification/verify.sh a verify.ps1 ho používají místo manifest.json.ots); u staršího balíčku spusťte `ots verify manifest.json.upgraded.ots -f manifest.json`. Exporty spisů ho obsahují jako captures/<capture_id>.upgraded.ots vedle captures/<capture_id>.zip. Maže se spolu s balíčkem."
              }
            }
          },
          "eidas": {
            "$ref": "#/components/schemas/EidasTimestamp"
          }
        }
      },
      "DiffSummary": {
        "type": "object",
        "properties": {
          "text_insertions": {
            "type": "integer",
            "description": "Přidané řádky (stejná hodnota jako text_lines_added; od 2026-10-14 se text počítá v řádcích, viz text_unit). Porovnání provedená dříve počítají znaky. Zastaralé (2026-10-14): ponecháno pro stávající čtenáře, neodstraněno; použijte text_lines_added.",
            "deprecated": true
          },
          "text_deletions": {
            "type": "integer",
            "description": "Odebrané řádky (stejná hodnota jako text_lines_removed; od 2026-10-14 řádky, dříve znaky). Zastaralé (2026-10-14): ponecháno pro stávající čtenáře, neodstraněno; použijte text_lines_removed.",
            "deprecated": true
          },
          "text_unit": {
            "type": "string",
            "enum": [
              "line"
            ],
            "description": "Jednotka počtů textu: line (každý řádek domtextcontent.txt i se znakem konce řádku). Chybí u porovnání provedených před 2026-10-14, která počítala znaky."
          },
          "text_lines_added": {
            "type": "integer",
            "description": "Přidané řádky (řádky textu Po v přidaných úsecích řádkového rozdílu)."
          },
          "text_lines_removed": {
            "type": "integer",
            "description": "Odebrané řádky (řádky textu Před v odebraných úsecích řádkového rozdílu)."
          },
          "text_lines_before": {
            "type": "integer",
            "description": "Řádky textu Před."
          },
          "text_lines_after": {
            "type": "integer",
            "description": "Řádky textu Po."
          },
          "text_changed_percent": {
            "type": "number",
            "description": "100 x (odebrané řádky + přidané řádky) / (řádky před + řádky po), na jedno desetinné místo."
          },
          "text_diff_capped": {
            "type": "boolean",
            "description": "true, pokud porovnání po řádcích vyčerpalo svůj pracovní rozpočet a část textů byla započítána jako nahrazená celá (hlásí víc, nikdy změnu neskryje)."
          },
          "metadata_changes": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "{ key, before, after, class } pro každé pole metadata.json, které se liší, a to přesně tato: url, final_url, page_title, http_status, http_headers.content-type, http_headers.server, dns.connected_ip, resolved_ips (porovnáváno jako seřazený seznam), tls.issuer, tls.valid_to a pole profilu zařízení viewport_width, viewport_height, device_scale_factor, is_mobile a user_agent. class je content (url, final_url, page_title, http_status, http_headers.content-type: počítá se jako změna), infrastructure (http_headers.server, dns.connected_ip, resolved_ips, tls.issuer, tls.valid_to: který server stránku doručil, jen se hlásí) nebo device_profile (jak záznam stránku vykreslil, jen se hlásí). Porovnání provedené před 2026-10-10 class nemá."
          },
          "meta_content": {
            "type": "integer",
            "description": "Odlišná pole metadat třídy content; započítávají se do changed."
          },
          "meta_infra": {
            "type": "integer",
            "description": "Odlišná pole metadat třídy infrastructure (serverový software, připojená IP, přeložené IP, vydavatel a platnost TLS). Síť pro doručování obsahu (CDN) odpovídá ze střídajících se adres, takže dvě načtení nezměněné stránky se zde mohou lišit; uvádějí se pro informaci, nikdy se nezapočítávají do changed."
          },
          "meta_device_profile": {
            "type": "integer",
            "description": "Odlišná pole profilu zařízení (zobrazovaná oblast, měřítko, emulace mobilu, user agent); uvádějí se pro informaci, nikdy se nezapočítávají do changed."
          },
          "image_changes": {
            "type": "object",
            "description": "Porovnání obrázků ze soupisu obrázků, který zapečetil každý zdrojový záznam (image_inventory.json). status ran, nebo not_run s reason source_without_inventory (zdroj pořízený dříve, než záznamy soupis zaznamenávaly), source_inventory_failed nebo source_inventory_unreadable; nic jiného se místo něj nepoužívá. Úplné výsledky pro jednotlivé obrázky jsou v image_changes.json balíčku.",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "ran",
                  "not_run"
                ]
              },
              "reason": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "source_without_inventory",
                  "source_inventory_failed",
                  "source_inventory_unreadable",
                  null
                ],
                "description": "Proč nebyly obrázky porovnány: source_without_inventory (zdroj pořízený dříve, než záznamy zaznamenávaly soupis obrázků; nové záznamy ho zaznamenávají), source_inventory_failed (soupis se při pořízení daného záznamu nepodařilo zaznamenat) nebo source_inventory_unreadable; null, když porovnání proběhlo."
              },
              "images_changed": {
                "type": "integer",
                "nullable": true,
                "description": "Vlastní obrázky webu (načítané z registrovatelné domény samotné stránky, nebo od 2026-10-14 z domény, kterou stránka uvádí jako svůj og:image nebo ikonu, nebo která v obou záznamech poskytuje většinu obrázků stránky: image_changes.json site_image_hosts), které byly nahrazeny, přidány nebo odebrány, tedy obrazová část hodnoty changed; přesunuté obrázky se nezapočítávají. null, pokud porovnání neproběhlo. Zastaralé (2026-10-14): ponecháno pro stávající čtenáře, neodstraněno; použijte site_images_changed.",
                "deprecated": true
              },
              "first_party": {
                "$ref": "#/components/schemas/ImageChangeCounts"
              },
              "third_party": {
                "$ref": "#/components/schemas/ImageChangeCounts"
              },
              "tracking_pixel": {
                "$ref": "#/components/schemas/ImageChangeCounts"
              },
              "inventories_truncated": {
                "type": "boolean",
                "description": "true, pokud soupis zdroje dosáhl svého limitu položek; viz inventory_cutoff."
              },
              "site_images_changed": {
                "type": "integer",
                "description": "Totéž co images_changed (počet)."
              },
              "other_images_changed": {
                "type": "integer",
                "description": "Obrázky z jiných domén a sledovací pixely, které byly nahrazeny, odebrány nebo přidány (nikdy se nezapočítávají)."
              },
              "site_image_hosts": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Registrovatelné domény, které se kromě domény stránky počítají jako vlastní domény webu (site_image_hosts v image_changes.json)."
              },
              "inventory_cutoff": {
                "type": "object",
                "nullable": true,
                "properties": {
                  "before_only_index_limit": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Obrázek nalezený pouze v Before je rozhodnutelný (removed), když je jeho index v soupisu obrázků Before nižší než tato hodnota; null: bez omezení (soupis After je úplný)."
                  },
                  "after_only_index_limit": {
                    "type": "integer",
                    "nullable": true,
                    "description": "Obrázek nalezený pouze v After je rozhodnutelný (added), když je jeho index v soupisu obrázků After nižší než tato hodnota; null: bez omezení (soupis Before je úplný)."
                  }
                },
                "description": "Od druhého auditu z 2026-10-14 (algoritmus 3 v image_changes.json) objekt, rozhodovaný podle indexu v dokumentu: když DRUHÝ soupis dosáhl svého limitu položek, obrázek nalezený jen na jedné straně lze rozhodnout jen tehdy, když je jeho index nižší než počet položek druhého soupisu minus rezerva (větší z hodnot 10 položek a 5 procent tohoto počtu); jinak je neurčený (undetermined_reason beyond_inventory_limit). null, když žádný soupis není zkrácen. Porovnání vytvořená dříve nesou číslo (relativní pozice v dokumentu podle dřívějšího pravidla)."
              }
            }
          },
          "changed": {
            "type": "boolean",
            "nullable": true,
            "description": "true, pokud se liší viditelný text, liší se pole metadat obsahu (meta_content), nebo byl obrázek z vlastní domény stránky nahrazen, odstraněn či přidán (image_changes.images_changed). Pole infrastruktury a profilu zařízení, přesunuté obrázky (stejné bajty na jiné adrese), obrázky třetích stran a sledovací pixely se hlásí, ale tuto hodnotu nenastavují. null (od 2026-10-14), pokud se nic započítávaného spolehlivě nezměnilo, ale výsledek pro text nebo obrázky nelze určit (záznamy vykreslené odlišně, allow_profile_mismatch). Balíček uvádí pravidlo v comparison_method.json counted_as_change. Zastaralé (2026-10-14): ponecháno pro stávající čtenáře, neodstraňuje se; použijte verdict (changed | unchanged | undetermined) a dílčí text_verdict, images_verdict, metadata_verdict.",
            "deprecated": true
          },
          "text_verdict": {
            "type": "string",
            "enum": [
              "changed",
              "unchanged",
              "undetermined"
            ],
            "description": "undetermined, pokud byly oba záznamy vykresleny s odlišným profilem zařízení nebo nastavením záznamu (allow_profile_mismatch)."
          },
          "images_verdict": {
            "type": "string",
            "enum": [
              "changed",
              "unchanged",
              "undetermined",
              "not_run"
            ]
          },
          "metadata_verdict": {
            "type": "string",
            "enum": [
              "changed",
              "unchanged"
            ],
            "description": "Z polí metadat třídy obsahu (adresa, konečná adresa, titulek, HTTP stav, typ obsahu)."
          },
          "verdict": {
            "type": "string",
            "enum": [
              "changed",
              "unchanged",
              "undetermined"
            ],
            "description": "Celkový výsledek slovy: changed, když je changed true, undetermined, když je changed null."
          },
          "undetermined_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "render_profile_mismatch",
              "capture_settings_mismatch",
              null
            ]
          },
          "text_changes": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Pouze GET: až 60 změněných úseků textu."
          },
          "change_regions": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Pouze GET: až 60 změn textu umístěných na snímcích obrazovky (podle text_layout.json zdrojů), v pixelech snímku. Každá změna nese counterpart_y_px (svou svislou polohu na druhém snímku, převzatou z nejbližšího nezměněného bloku textu) a report_region (číslo místa změny, ve kterém ji ukazuje evidence.pdf, nejvýše 10 míst, nebo null) jako v change_regions.json."
          },
          "change_regions_info": {
            "type": "object",
            "nullable": true
          },
          "order_reversed": {
            "type": "boolean",
            "description": "Pouze GET: true, pokud byl záznam zadaný jako capture_id_1 (Před) pořízen později než záznam zadaný jako capture_id_2 (Po), viz order_reversed v compare.json. Porovnání zachová zadané pořadí; zpráva i dashboard na to upozorní."
          },
          "render_profile_mismatch": {
            "type": "boolean",
            "description": "Pouze GET: oba záznamy byly vykresleny s odlišným profilem zařízení (compare.json)."
          },
          "capture_settings_mismatch": {
            "type": "boolean",
            "description": "Pouze GET: oba záznamy byly pořízeny s odlišným nastavením záznamu (compare.json)."
          },
          "capture_settings_differing": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "setting": {
                  "type": "string"
                },
                "before": {},
                "after": {}
              }
            },
            "description": "Pouze GET: nastavení, která se liší, { setting, before, after }."
          },
          "profile_mismatch_allowed": {
            "type": "boolean",
            "description": "Pouze GET: porovnání bylo provedeno s allow_profile_mismatch pro záznamy vykreslené odlišně. Zastaralé (2026-10-14): ponecháno pro stávající čtenáře, neodstraněno; použijte render_profile_mismatch a capture_settings_mismatch.",
            "deprecated": true
          },
          "url_mismatch": {
            "type": "boolean",
            "description": "Pouze GET: oba záznamy nemají žádnou společnou adresu (provedeno s allow_url_mismatch)."
          }
        },
        "description": "Shrnutí porovnání."
      },
      "ImageChangeCounts": {
        "type": "object",
        "properties": {
          "unchanged": {
            "type": "integer"
          },
          "replaced": {
            "type": "integer"
          },
          "moved": {
            "type": "integer"
          },
          "removed": {
            "type": "integer"
          },
          "added": {
            "type": "integer"
          },
          "undetermined": {
            "type": "integer"
          },
          "alt_changed": {
            "type": "integer"
          },
          "position_changed": {
            "type": "integer"
          },
          "undetermined_same_error": {
            "type": "integer",
            "description": "Nerozhodnuté dvojice, jejichž obě strany vrátily stejný chybový stav HTTP (například 404 v obou záznamech); jsou zahrnuty do undetermined, započítány ve zprávě a nevypisují se."
          },
          "occurrences": {
            "type": "integer",
            "description": "Všechny výsledky této strany: výskyty na stránce."
          },
          "distinct": {
            "type": "object",
            "description": "Počet různých obrázků mezi výsledky, celkem a podle kategorií (obrázek zobrazený vícekrát se počítá jednou): každý výsledek představuje SHA-256 své strany Po, nebo strany Před, když stranu Po nemá, případně adresu této strany, když nemá SHA-256.",
            "properties": {
              "total": {
                "type": "integer"
              },
              "unchanged": {
                "type": "integer"
              },
              "replaced": {
                "type": "integer"
              },
              "moved": {
                "type": "integer"
              },
              "removed": {
                "type": "integer"
              },
              "added": {
                "type": "integer"
              },
              "undetermined": {
                "type": "integer"
              }
            }
          }
        },
        "description": "Počty v jednotlivých kategoriích jako výskyty na stránce (obrázek zobrazený třikrát se počítá třikrát): unchanged, replaced (stejná adresa, jiné bajty), moved (jiná adresa, stejné bajty; uvádí se, ale nepočítá se jako změna), removed, added, undetermined (obrázek bez SHA-256 na některé ze stran, nikdy se nepočítá jako odebraný ani přidaný); dále spárované obrázky, u nichž se změnil alternativní text nebo pořadí mezi obrázky stránky, neurčené páry se stejnou chybou HTTP na obou stranách a počet různých obrázků."
      },
      "BatchRequest": {
        "type": "object",
        "required": [
          "urls"
        ],
        "properties": {
          "urls": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "uri",
              "maxLength": 2048
            },
            "minItems": 2,
            "maxItems": 50,
            "description": "2 až 50 URL, každá se ověřuje stejně jako CaptureRequest.url. Při přijetí dávky se u názvů hostitelů neprovádí kontrola DNS; URL, která neprojde kontrolou DNS nebo adresy, selže později se stavem failed (a událostí capture.failed)."
          },
          "options": {
            "$ref": "#/components/schemas/CaptureOptions"
          },
          "private_note": {
            "allOf": [
              {
                "$ref": "#/components/schemas/PrivateNote"
              }
            ],
            "description": "Jedna soukromá poznámka uložená u každého záznamu dávky. Vaše soukromá poznámka k záznamu (například \"mobile capture\"), nejvýše 200 znaků, prostý text (pravidlo PlainText). Ukládá se jen k záznamu v databázi: NENÍ součástí zapečetěného balíčku důkazů (není v ZIP, PDF, manifestu ani v žádném hashi) a nemá důkazní váhu, takže ji lze později změnit nebo smazat přes PATCH /v1/captures/{capture_id}, aniž by to ovlivnilo důkazy. Číst ji může jen autor záznamu. Pokud poznámku nechcete, pole vynechte nebo pošlete null či prázdný řetězec."
          }
        }
      },
      "BatchResult": {
        "type": "object",
        "properties": {
          "batch_id": {
            "type": "string",
            "example": "batch_a1B2c3D4e5F6g7H8"
          },
          "count": {
            "type": "integer"
          },
          "captures": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "capture_id": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "status": {
                  "type": "string",
                  "description": "failed, pokud se záznam nepodařilo spustit.",
                  "enum": [
                    "processing",
                    "failed"
                  ]
                }
              }
            }
          },
          "not_admitted": {
            "type": "array",
            "description": "Jen pokud účet dosáhl limitu souběžně zpracovávaných záznamů: URL, které nebyly spuštěny, v pořadí odeslání. Nic nestojí (nečerpají limit počtu požadavků ani měsíční jednotku); pošlete je znovu později. Chybí, pokud byly spuštěny všechny URL.",
            "items": {
              "type": "object",
              "properties": {
                "url": {
                  "type": "string"
                },
                "code": {
                  "type": "string",
                  "description": "Proč nebyl záznam pro URL spuštěn.",
                  "enum": [
                    "CONCURRENT_CAPTURE_LIMIT"
                  ]
                }
              }
            }
          },
          "in_flight_limit": {
            "type": "integer",
            "description": "Jen spolu s not_admitted: počet záznamů, které může účet zpracovávat současně (developer 10, startup 25, growth 100, legal_solo a legal_seats 25, custom 200, website_archive 25, sandbox 5)."
          },
          "warnings": {
            "$ref": "#/components/schemas/Rule902DisabledWarnings"
          }
        }
      },
      "VerifyResult": {
        "type": "object",
        "properties": {
          "verdict": {
            "type": "string",
            "nullable": true,
            "description": "match: podpis je platný a každý uvedený soubor je přítomen se zaznamenaným SHA-256. modified: podpis je neplatný nebo soubor chybí či byl změněn. invalid: balíček se nepodařilo zkontrolovat. null jen u importovaného balíčku, který tentokrát nebyl znovu zkontrolován (`rechecked: false`, s `reason` a ověřením zaznamenaným při importu v `stored_verification`).",
            "enum": [
              "match",
              "modified",
              "invalid",
              null
            ]
          },
          "reason": {
            "type": "string",
            "description": "Jen u invalid; u importovaného balíčku s `rechecked: false` důvod, proč nebyl znovu zkontrolován (too_large_for_synchronous_check, time_budget, storage_error)."
          },
          "capture_id": {
            "type": "string"
          },
          "source": {
            "type": "string",
            "enum": [
              "s3"
            ]
          },
          "checks": {
            "type": "object",
            "properties": {
              "manifest_signature": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "valid",
                      "invalid"
                    ]
                  },
                  "algorithm": {
                    "type": "string",
                    "enum": [
                      "RSA-4096"
                    ]
                  }
                }
              },
              "declared_files": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "all_match",
                      "mismatch"
                    ]
                  },
                  "mismatched": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  },
                  "missing": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              },
              "bitcoin_ots": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "Jen přítomnost manifest.json.ots; samotný důkaz se zde nekontroluje.",
                    "enum": [
                      "present",
                      "not_present"
                    ]
                  }
                }
              },
              "eidas_disig": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "Přítomnost manifest.json.tsr. Samotný token se kontroluje v checks.eidas. missing: manifest.json uvádí eidas_requested (balíček byl vydán s tokenem), ale manifest.json.tsr v balíčku není.",
                    "enum": [
                      "present",
                      "missing"
                    ]
                  }
                },
                "nullable": true,
                "description": "null, pokud v balíčku není manifest.json.tsr a manifest.json nezaznamenává eidas_requested."
              },
              "proofsnap_issuance": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "issued_by_proofsnap: hash manifestu je v registru vydání ProofSnap. unverified: není v něm (balíčky vydané předtím, než registr existoval, v něm nejsou). unknown: vyhledání selhalo.",
                    "enum": [
                      "issued_by_proofsnap",
                      "unverified",
                      "unknown"
                    ]
                  },
                  "manifest_sha256": {
                    "type": "string"
                  },
                  "issued_at": {
                    "type": "string",
                    "nullable": true,
                    "format": "date-time"
                  },
                  "type": {
                    "type": "string"
                  }
                }
              },
              "eidas": {
                "type": "object",
                "nullable": true,
                "description": "null, pokud v balíčku není manifest.json.tsr a manifest.json nezaznamenává eidas_requested. Token časového razítka eIDAS, jak ho na požádání zkontroloval ProofSnap z uloženého balíčku. Jde o kontrolu provedenou společností ProofSnap; pole note popisuje, jak token ověřit nezávisle.",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "verified",
                      "verified_revocation_unknown",
                      "failed",
                      "unavailable",
                      "missing"
                    ],
                    "description": "missing: manifest.json zaznamenává eidas_requested: true, balíček tedy byl vydán s kvalifikovaným časovým razítkem, ale manifest.json.tsr v něm není (odpověď pak obsahuje varování EIDAS_TOKEN_MISSING). verified: všechny kontroly prošly a stav certifikátu TSA zaznamenaný při vydání je známý (good, nebo revoked po čase tokenu z jiného důvodu než kompromitace klíče). verified_revocation_unknown: všechny provedené kontroly prošly, ale stav certifikátu TSA se ze zaznamenaných dat nepodařilo zjistit (revocation.status unknown nebo not_checked). failed: alespoň jedna kontrola selhala, viz failures (odpověď pak obsahuje varování EIDAS_TOKEN_FAILED). unavailable: o tokenu není žádný verdikt (reason: not configured, timeout, input_rejected, když ověřovač odmítl vstup, například příliš velká validační data, inconclusive); o tokenu z toho nic nevyplývá."
                  },
                  "reason": {
                    "type": "string",
                    "description": "Jen u unavailable: timeout, input_rejected, inconclusive nebo krátké vysvětlení."
                  },
                  "checked_by": {
                    "type": "string",
                    "example": "ProofSnap API on request"
                  },
                  "checked_at": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "gen_time": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true,
                    "description": "Čas v tokenu (TSTInfo genTime)."
                  },
                  "tsa_name": {
                    "type": "string",
                    "nullable": true,
                    "description": "Z certifikátu podepisujícího (obecné jméno a organizace), nikdy výchozí hodnota."
                  },
                  "serial_number": {
                    "type": "string",
                    "nullable": true
                  },
                  "policy_oid": {
                    "type": "string",
                    "nullable": true
                  },
                  "hash_algorithm": {
                    "type": "string",
                    "nullable": true
                  },
                  "signature_algorithm": {
                    "type": "string"
                  },
                  "signing_certificate_form": {
                    "type": "string",
                    "enum": [
                      "ESSCertIDv2",
                      "ESSCertID"
                    ]
                  },
                  "signer_certificate": {
                    "type": "object",
                    "nullable": true,
                    "properties": {
                      "subject": {
                        "type": "string"
                      },
                      "issuer": {
                        "type": "string"
                      },
                      "serial_number": {
                        "type": "string"
                      },
                      "sha256": {
                        "type": "string"
                      },
                      "not_before": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "not_after": {
                        "type": "string",
                        "format": "date-time"
                      }
                    }
                  },
                  "root": {
                    "type": "object",
                    "properties": {
                      "label": {
                        "type": "string",
                        "example": "CA Disig QCA4"
                      },
                      "sha256": {
                        "type": "string"
                      }
                    }
                  },
                  "chain_checked_at": {
                    "type": "string",
                    "format": "date-time",
                    "nullable": true,
                    "description": "Čas, ke kterému byl řetězec ověřen: genTime tokenu, takže certifikát, jehož platnost skončila až po vydání tokenu, nezpůsobí neúspěch ověření."
                  },
                  "chain": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "subject": {
                          "type": "string"
                        },
                        "sha256": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "revocation": {
                    "type": "object",
                    "description": "Stav certifikátu TSA podle údajů zaznamenaných při vydání (basis recorded_at_issuance), ověřený podpisem a s požadavkem, aby byl v čase genTime platný. Nezjišťuje se online.",
                    "properties": {
                      "status": {
                        "type": "string",
                        "enum": [
                          "good",
                          "revoked",
                          "revoked_after_gen_time",
                          "unknown",
                          "not_checked"
                        ],
                        "description": "revoked_after_gen_time: zneplatněn po čase tokenu z jiného důvodu než kompromitace klíče (token zůstává ověřený). not_checked: nebyla zaznamenána ani zkontrolována žádná data o zneplatnění."
                      },
                      "source": {
                        "type": "string",
                        "enum": [
                          "ocsp",
                          "crl"
                        ],
                        "nullable": true
                      },
                      "basis": {
                        "type": "string",
                        "enum": [
                          "recorded_at_issuance"
                        ]
                      },
                      "produced_at": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "this_update": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "next_update": {
                        "type": "string",
                        "format": "date-time",
                        "nullable": true
                      },
                      "reason": {
                        "type": "string",
                        "description": "Proč je stav neznámý."
                      }
                    }
                  },
                  "checks": {
                    "type": "object",
                    "description": "Každá kontrola: passed, failed, not_applicable (nonce: u uloženého tokenu žádný zaznamenán není), unknown (odvolání bez použitelných dat) nebo not_checked (kontrolu zastavilo dřívější selhání).",
                    "properties": {
                      "response_status": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "message_imprint": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "nonce": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "content_type": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "message_digest": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "signature": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "signing_certificate": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "timestamping_eku": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "chain": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      },
                      "revocation": {
                        "type": "string",
                        "enum": [
                          "passed",
                          "failed",
                          "not_applicable",
                          "unknown",
                          "not_checked"
                        ]
                      }
                    }
                  },
                  "failures": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "check": {
                          "type": "string"
                        },
                        "reason": {
                          "type": "string"
                        }
                      }
                    }
                  },
                  "note": {
                    "type": "string"
                  },
                  "detail": {
                    "type": "string",
                    "nullable": true,
                    "description": "Jen u input_rejected: co ověřovač odmítl."
                  }
                }
              }
            },
            "description": "Chybí, když je verdict invalid. Verdikt závisí pouze na manifest_signature a declared_files; eidas se uvádí vedle něj, a pokud ověření selhalo, také ve warnings."
          },
          "warnings": {
            "type": "array",
            "description": "Uvádí se jen tehdy, když pozornost vyžaduje něco mimo verdikt. EIDAS_TOKEN_FAILED: manifest.json.tsr neprošel kontrolou v checks.eidas. EIDAS_TOKEN_MISSING: manifest.json uvádí eidas_requested, ale manifest.json.tsr v balíčku není.",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "EIDAS_TOKEN_FAILED",
                    "EIDAS_TOKEN_MISSING"
                  ]
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "ScheduleRequest": {
        "type": "object",
        "required": [
          "url",
          "mode"
        ],
        "properties": {
          "url": {
            "type": "string",
            "description": "Stránka k zachycení, ověřuje se stejně jako CaptureRequest.url.",
            "format": "uri",
            "maxLength": 2048
          },
          "mode": {
            "type": "string",
            "description": "interval: každých interval_seconds. cron: podle cron_expr. on_change: kontrolovat stránku každých interval_seconds a záznam pořídit, jen když se změnil její text.",
            "enum": [
              "interval",
              "cron",
              "on_change"
            ]
          },
          "interval_seconds": {
            "type": "integer",
            "description": "Povinné pro interval a on_change. Nejméně minimum plánu (300 u developer, startup, growth, custom, legal_solo a legal_seats; 86400 u website_archive), jinak 400 INTERVAL_TOO_SHORT.",
            "minimum": 300
          },
          "cron_expr": {
            "type": "string",
            "description": "Povinné pro cron (nejvýše 200 znaků). Výraz, který nelze zpracovat, vrací 400 INVALID_CRON; dva po sobě jdoucí běhy s menším odstupem, než je minimum plánu, vrací 400 INTERVAL_TOO_SHORT.",
            "maxLength": 200,
            "example": "0 9 * * 1-5"
          },
          "timezone": {
            "type": "string",
            "description": "Časové pásmo IANA, podle kterého se vyhodnocuje cron_expr. Výchozí UTC.",
            "example": "Europe/Berlin"
          },
          "webhook_url": {
            "type": "string",
            "description": "https URL. Běhy interval a cron odesílají capture.completed nebo capture.failed; on_change odesílá monitor.change_detected. URL musí být https a nesmí směřovat na privátní, loopback, link-local, carrier-grade NAT ani cloudovou metadatovou adresu (stejná pravidla jako u URL záznamu; jinak 422 SSRF_BLOCKED). Prázdná hodnota nebo hodnota jen z mezer znamená bez webhooku. Automatický záznam má jedinou webhook_url, na nejvyšší úrovni: options.webhook_url se neukládá (pokud není odeslána webhook_url na nejvyšší úrovni, použije se jako ona), takže automatický záznam on_change nikdy neodesílá zároveň capture.completed. Vyžaduje klíč API: při odeslání z relace dashboardu je odmítnuta s 400 WEBHOOK_REQUIRES_API_KEY, protože webhooky se podepisují tajným kódem webhooku daného klíče.",
            "format": "uri"
          },
          "js_render": {
            "type": "boolean",
            "description": "Jen u on_change: kontrolovat stránku úplným vykreslením v prohlížeči místo prostého stažení přes HTTP (pro stránky, které potřebují JavaScript).",
            "default": false
          },
          "options": {
            "$ref": "#/components/schemas/CaptureOptions"
          },
          "max_capture_age_seconds": {
            "type": "integer",
            "nullable": true,
            "minimum": 86400,
            "maximum": 34560000,
            "description": "Jen u on_change: pořídit úplný záznam (odešle capture.completed) i tehdy, když je nejnovější záznam automatického záznamu starší než tato hodnota, i když se stránka nezměnila. Pro pravidla, která vyžadují kopii nejméně každých N dnů, např. 7776000 pro 90 dnů. Od 1 dne do 400 dnů a déle než interval_seconds; null (výchozí) pořizuje záznam jen při změně. PATCH s null ho odstraní."
          },
          "alert_on": {
            "type": "string",
            "enum": [
              "any",
              "text"
            ],
            "nullable": true,
            "description": "Jen u on_change (2026-10-14): která zjištěná změna odešle monitor.change_detected. any (výchozí, dosavadní chování): každý záznam při změně. text: jen když porovnání s předchozím záznamem zjistí, že se změnil viditelný text (diff_summary.text_verdict changed); záznam při změně, jehož porovnání říká, že se text nezměnil nebo to nelze určit, neodešle nic (záznam se přesto pořídí, účtuje a odběrům odešle capture.completed). Bez výsledku porovnání (chybí výchozí záznam, porovnání selhalo) upozorní. Při jiném režimu nebo hodnotě 400 MALFORMED_REQUEST. null u automatických záznamů interval a cron."
          }
        },
        "example": {
          "url": "https://example.com/terms",
          "mode": "on_change",
          "interval_seconds": 3600,
          "webhook_url": "https://your-app.example/webhooks/proofsnap"
        }
      },
      "Schedule": {
        "type": "object",
        "properties": {
          "schedule_id": {
            "type": "string"
          },
          "url": {
            "type": "string"
          },
          "mode": {
            "type": "string",
            "enum": [
              "interval",
              "cron",
              "on_change"
            ]
          },
          "interval_seconds": {
            "type": "integer",
            "nullable": true
          },
          "cron_expr": {
            "type": "string",
            "nullable": true
          },
          "timezone": {
            "type": "string",
            "nullable": true
          },
          "webhook_url": {
            "type": "string",
            "nullable": true,
            "description": "Webhook automatického záznamu (u staršího automatického záznamu, který ho měl v options.webhook_url, se zde zobrazí tato hodnota a options ji nikdy neobsahuje). Vyžaduje klíč API: při odeslání z relace v dashboardu je odmítnut s 400 WEBHOOK_REQUIRES_API_KEY, protože webhooky se podepisují tajným kódem webhooku daného klíče."
          },
          "options": {
            "type": "object",
            "description": "Volby záznamu s použitými výchozími hodnotami."
          },
          "js_render": {
            "type": "boolean"
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          },
          "next_run_at": {
            "type": "string",
            "format": "date-time"
          },
          "last_run_at": {
            "type": "string",
            "nullable": true,
            "format": "date-time"
          },
          "last_capture_id": {
            "type": "string",
            "nullable": true
          },
          "run_count": {
            "type": "integer"
          },
          "consecutive_failures": {
            "type": "integer"
          },
          "pause_reason": {
            "type": "string",
            "description": "Proč byl automatický záznam automaticky pozastaven: max_failures (5 neúspěšných běhů po sobě), no_billing, plan_downgrade (limity plánu nebo plán Archive only), invalid_cron nebo key_revoked. null, když je aktivní nebo když jste ho pozastavili sami.",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "max_capture_age_seconds": {
            "type": "integer",
            "nullable": true
          },
          "current_capture_id": {
            "type": "string",
            "nullable": true,
            "description": "Nejnovější DOKONČENÝ záznam automatického záznamu (jeho aktuální verze; last_capture_id je nejnovější spuštěný)."
          },
          "current_captured_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "alert_on": {
            "type": "string",
            "enum": [
              "any",
              "text"
            ],
            "nullable": true,
            "description": "on_change: any nebo text (any u automatického záznamu vytvořeného dříve, než tato volba existovala); null u interval a cron."
          },
          "warnings": {
            "$ref": "#/components/schemas/Rule902DisabledWarnings"
          }
        }
      },
      "Matter": {
        "type": "object",
        "properties": {
          "matter_id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "client": {
            "type": "string",
            "nullable": true
          },
          "case_number": {
            "type": "string",
            "nullable": true
          },
          "opposing_party": {
            "type": "string",
            "nullable": true
          },
          "jurisdiction": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "open",
              "archived",
              "sealed"
            ]
          },
          "sealed": {
            "type": "boolean"
          },
          "capture_count": {
            "type": "integer"
          },
          "custody_count": {
            "type": "integer",
            "description": "Položky v protokolu řetězce úschovy."
          },
          "custody_head_hash": {
            "type": "string",
            "description": "sha256:<hex> nejnovější položky logu řetězce úschovy.",
            "nullable": true
          },
          "seal": {
            "type": "object",
            "nullable": true,
            "description": "null do zapečetění.",
            "allOf": [
              {
                "$ref": "#/components/schemas/MatterSeal"
              }
            ]
          },
          "member_uids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_by": {
            "type": "string",
            "description": "Vlastník.",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "read_only": {
            "type": "boolean",
            "description": "Uvádí se (true) u spisu firmy, jejíž účet skončil nebo je uchováván jako archiv firmy: jen otevření, export a zrušení sdílení."
          },
          "legal_hold": {
            "type": "boolean",
            "description": "Právní blokace spisu je zapnutá (PATCH { legal_hold })."
          },
          "legal_hold_set_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      },
      "MatterSeal": {
        "type": "object",
        "properties": {
          "root_hash": {
            "type": "string",
            "description": "sha256:<hex>: hash hlavy řetězce úschovy, který byl zapečetěn a odeslán do OpenTimestamps."
          },
          "ots": {
            "type": "string",
            "description": "Důkaz OpenTimestamps, hex."
          },
          "ots_pending": {
            "type": "boolean"
          },
          "eidas": {
            "type": "object",
            "properties": {
              "tsr_base64": {
                "type": "string",
                "nullable": true
              },
              "serial": {
                "type": "string",
                "nullable": true
              },
              "issued_at": {
                "type": "string",
                "nullable": true
              },
              "ltv": {
                "type": "boolean"
              },
              "verification_status": {
                "type": "string",
                "enum": [
                  "verified"
                ],
                "description": "Token při zapečetění prošel kontrolou ProofSnap (sdílený ověřovač, stejné kontroly jako u tokenu záznamu)."
              },
              "revocation_status": {
                "type": "string",
                "enum": [
                  "good",
                  "revoked_after_gen_time",
                  "unknown",
                  "not_checked"
                ],
                "description": "Stav certifikátu TSA zjištěný při zapečetění z tehdy získané odpovědi OCSP nebo CRL."
              },
              "validation": {
                "type": "object",
                "nullable": true,
                "description": "Obsah eidas_validation.json zaznamenaný při zapečetění pro offline ověření tokenu: tsaCertChain, rootCaPem, ocspResponse, crlResponse (vynechá se a uvede v omitted, když je příliš velký), ocspUrl, ocspFetchedAt, ocspStatus, crlUrl, verification. Zapečetění provedená před 2026-10-01 ho nemají.",
                "additionalProperties": true
              }
            },
            "nullable": true,
            "description": "Časové razítko eIDAS nad stejným hashem, pokud má nasazení nakonfigurovaný eIDAS, volající je ostrý a token byl získán a prošel kontrolou, jinak null (viz eidas_status)."
          },
          "sealed_by": {
            "type": "string",
            "nullable": true
          },
          "sealed_at": {
            "type": "string",
            "format": "date-time"
          },
          "eidas_status": {
            "type": "string",
            "enum": [
              "confirmed",
              "not_obtained",
              "not_configured"
            ],
            "description": "Chybí u pečetí vytvořených před 2026-10-01. not_obtained: pečeť nese pouze ukotvení OpenTimestamps (eidas_reason token_refused, unavailable nebo test_key). Vypršení časového limitu u razítka eIDAS nikdy pečeť nevytvoří: požadavek místo toho vrátí 503 EIDAS_SEAL_RETRY."
          },
          "eidas_reason": {
            "type": "string",
            "enum": [
              "token_refused",
              "unavailable",
              "test_key",
              "account_limit"
            ],
            "description": "Jen u not_obtained. test_key: zapečetil testovací volající (testovací klíč API nebo relace sandboxu), takže časové razítko eIDAS nebylo vyžádáno. account_limit: účet ještě nemá žádnou zaplacenou fakturu a dosáhl svého limitu eIDAS (20 za den UTC, 50 za měsíc UTC)."
          }
        },
        "nullable": true
      },
      "CustodyEntry": {
        "type": "object",
        "properties": {
          "seq": {
            "type": "integer"
          },
          "ts": {
            "type": "string",
            "format": "date-time"
          },
          "actor_uid": {
            "type": "string",
            "nullable": true
          },
          "actor_name": {
            "type": "string",
            "nullable": true
          },
          "actor_role": {
            "type": "string",
            "enum": [
              "api",
              "user"
            ],
            "nullable": true
          },
          "action": {
            "type": "string",
            "description": "Například matter.created, matter.updated, capture.added, capture.removed, capture.legal_hold_placed, capture.legal_hold_released, member.added, member.removed, package.imported (balíček důkazů importovaný s matter_id; target je id záznamu)."
          },
          "target": {
            "type": "string",
            "nullable": true
          },
          "prev_hash": {
            "type": "string"
          },
          "entry_hash": {
            "type": "string"
          },
          "details": {
            "type": "object",
            "description": "Jen u package.imported: manifest_sha256, zip_sha256, package_kind, verdict, levels. Ukládá se s položkou, ale entry_hash ho NEPOKRÝVÁ.",
            "additionalProperties": true
          }
        },
        "description": "Jeden článek hashového řetězce. entry_hash pokrývá seq, ts, actor, action, target a prev_hash."
      },
      "MatterCapture": {
        "type": "object",
        "properties": {
          "capture_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "nullable": true
          },
          "source": {
            "type": "string"
          },
          "label": {
            "type": "string",
            "nullable": true
          },
          "created_at": {
            "type": "string"
          },
          "captured_at": {
            "type": "string",
            "nullable": true
          },
          "file_count": {
            "type": "integer",
            "nullable": true
          },
          "manifest_hash": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "AuditEntry": {
        "type": "object",
        "properties": {
          "ts": {
            "type": "string"
          },
          "actor_uid": {
            "type": "string",
            "nullable": true
          },
          "actor_name": {
            "type": "string",
            "nullable": true
          },
          "actor_role": {
            "type": "string",
            "nullable": true
          },
          "action": {
            "type": "string",
            "description": "Například capture.downloaded, export.generated, share.created, share.revoked."
          },
          "target": {
            "type": "string",
            "nullable": true
          },
          "source_ip": {
            "type": "string",
            "nullable": true,
            "description": "Jen pro vlastníka spisu (u členů chybí)."
          },
          "user_agent": {
            "type": "string",
            "nullable": true,
            "description": "Jen pro vlastníka spisu (u členů chybí)."
          }
        },
        "description": "Událost přístupu. Není součástí hashového řetězce."
      },
      "CertifyResult": {
        "type": "object",
        "properties": {
          "certify_id": {
            "type": "string",
            "example": "cert_a1B2c3D4e5F6g7H8"
          },
          "status": {
            "type": "string",
            "enum": [
              "completed"
            ]
          },
          "hash_sha256": {
            "type": "string",
            "description": "Jen jeden certifikát."
          },
          "combined": {
            "type": "boolean",
            "description": "Pouze kombinovaný certifikát."
          },
          "file_count": {
            "type": "integer",
            "description": "Pouze kombinovaný certifikát."
          },
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string",
                  "description": "Štítek, který jste odeslali.",
                  "nullable": true
                },
                "sha256": {
                  "type": "string"
                }
              }
            },
            "description": "Pouze kombinovaný certifikát."
          },
          "label": {
            "type": "string",
            "description": "Váš štítek, nebo \"N files\" u kombinovaného certifikátu.",
            "nullable": true
          },
          "certified_at": {
            "type": "string",
            "format": "date-time"
          },
          "timestamps": {
            "type": "object",
            "properties": {
              "bitcoin_ots": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": [
                      "pending_confirmation",
                      "not_present"
                    ],
                    "description": "pending_confirmation: manifest.json.ots je v balíčku a čeká na bitcoinový blok. not_present: kalendáře OpenTimestamps nebyly dostupné, balíček neobsahuje manifest.json.ots a manifest.json ho neuvádí."
                  },
                  "block_height": {
                    "type": "integer",
                    "nullable": true
                  }
                }
              },
              "eidas": {
                "$ref": "#/components/schemas/EidasTimestamp"
              }
            }
          },
          "package_url": {
            "type": "string",
            "format": "uri"
          },
          "package_url_expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "verify_url": {
            "type": "string",
            "description": "Odkaz na veřejný ověřovač ProofSnap.",
            "format": "uri"
          },
          "warnings": {
            "$ref": "#/components/schemas/Rule902DisabledWarnings"
          }
        }
      },
      "PlainText": {
        "type": "string",
        "description": "Pravidlo pro prostý text u krátkých volných textových polí, která se tisknou na dokumenty pro soud nebo na veřejné stránky (case_reference, case_id, case_note, hodnoty evidence_pack.custodian, case_reference u certify-hash, custodian u začernění, prohlášení u exportu, názvy firem a spisů). Hodnota se normalizuje na NFC, bílé znaky se sloučí a ořežou a délka se počítá ve znacích (kódových bodech Unicode). Odmítají se: řídicí znaky (C0, C1), bidi vnoření, přepisy a izolace (U+202A až U+202E, U+2066 až U+2069), směrové značky (U+200E, U+200F, U+061C), znaky nulové šířky a neviditelné znaky (U+200B, U+2060 až U+2064, U+FEFF, U+00AD, U+034F, U+180E, U+206A až U+206F, U+FFF9 až U+FFFB), výplňové znaky hangulu (U+115F, U+1160, U+3164, U+FFA0), znaky tagů (U+E0000 až U+E007F), osamocené náhradní kódové body (surrogates) a znaky pro soukromé použití. Písmena všech písem projdou, včetně slabik hangulu, arabštiny, hebrejštiny, dévanágarí a CJK, a U+200C / U+200D (ZWNJ, ZWJ) jsou povoleny, protože je správný pravopis v několika písmech potřebuje."
      },
      "EidasTimestamp": {
        "type": "object",
        "description": "Výsledek eIDAS, pokud bylo u ostrého klíče požadováno include_eidas; pokud požadováno nebylo, pole chybí. confirmed: balíček obsahuje manifest.json.tsr (účtuje se, pokud není neznámý stav zneplatnění). not_obtained: žádný token nebyl dodán a nic se neúčtovalo; balíček obsahuje jen ukotvení OpenTimestamps (reason token_refused: token se vrátil, ale při vydání neprošel kontrolou; unavailable: token se nepodařilo získat; time_budget: požadavek se nevešel do zbývajícího času, a proto nebyl odeslán, služba časových razítek ho odmítla ještě před požadavkem na autoritu, nebo byl zastaven, k čemuž dochází u synchronní cesty začernění nebo na konci dlouhého záznamu; account_limit: účet ještě nemá žádnou zaplacenou fakturu a dosáhl svého limitu eIDAS 20 razítek za den UTC nebo 50 za měsíc UTC, počítaných dohromady přes záznamy, dávky, automatické záznamy, certifikace, porovnání, začernění a zapečetění spisů, takže žádný požadavek nebyl odeslán; účty se zaplacenou fakturou omezené nejsou). Řádky dokončené před 2026-10-01 uvádějí jen confirmed.",
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "confirmed",
              "not_obtained"
            ]
          },
          "reason": {
            "type": "string",
            "enum": [
              "token_refused",
              "unavailable",
              "time_budget",
              "account_limit"
            ],
            "description": "Jen u not_obtained."
          },
          "serial": {
            "type": "string",
            "nullable": true,
            "description": "Jen u confirmed."
          },
          "issued_at": {
            "type": "string",
            "nullable": true,
            "description": "Jen u confirmed."
          },
          "revocation": {
            "type": "string",
            "enum": [
              "unknown"
            ],
            "description": "Jen u confirmed, a to jen tehdy, když se stav certifikátu TSA nepodařilo zjistit při vydání (token prošel všemi ostatními kontrolami). Token je v balíčku a neúčtuje se."
          },
          "billed": {
            "type": "boolean",
            "enum": [
              false
            ],
            "description": "Uvádí se (false) spolu s revocation unknown: tento token nebyl účtován."
          }
        }
      },
      "ExternalArchive": {
        "type": "object",
        "description": "Výsledek Internet Archive (Wayback Machine) pro záznam. Internet Archive je veřejný archiv třetí strany.",
        "required": [
          "requested"
        ],
        "properties": {
          "requested": {
            "type": "boolean",
            "description": "false, pokud nebyl odeslán žádný požadavek do Internet Archive (external_archive: false, certifikace nebo porovnání, záznam pořízený dříve, než archivace existovala, nebo se požadavek nevešel do časového rozpočtu). Všechna ostatní pole pak chybí."
          },
          "status": {
            "type": "string",
            "enum": [
              "created",
              "recent_existing",
              "created_after_request",
              "existing",
              "pending",
              "rate_limited",
              "failed",
              "unconfirmed",
              "unavailable",
              "skipped",
              "skipped_sensitive",
              "skipped_query"
            ],
            "description": "Aktuální výsledek. U úlohy Save Page Now, která při zapečetění stále čeká, přečte plánovač stav úlohy přibližně 5 a 30 minut po požadavku a tento výsledek se stane konečným (created, recent_existing, failed, rate_limited, nebo unconfirmed, pokud během kontrolního okna nepřišla odpověď). created, recent_existing, created_after_request a existing nesou snapshot_url."
          },
          "status_at_sealing": {
            "type": "string",
            "enum": [
              "created",
              "recent_existing",
              "created_after_request",
              "existing",
              "pending",
              "rate_limited",
              "failed",
              "unconfirmed",
              "unavailable",
              "skipped",
              "skipped_sensitive",
              "skipped_query"
            ],
            "description": "Stav zapečetěný v balíčku (zaznamenávají ho metadata.json, forensic_log.json, chain_of_custody.json a evidence.pdf). Samotný balíček se nikdy nemění; rovná se status, pokud dodatečná kontrola nevyřešila čekající úlohu."
          },
          "method": {
            "type": "string",
            "nullable": true,
            "enum": [
              "spn2_authenticated",
              "spn_anonymous",
              null
            ]
          },
          "requested_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "snapshot_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Veřejná kopie ve Wayback Machine, vždy https://web.archive.org/web/{snapshot_timestamp}/{url}."
          },
          "snapshot_timestamp": {
            "type": "string",
            "nullable": true,
            "description": "Časové razítko Wayback YYYYMMDDhhmmss (UTC)."
          },
          "snapshot_offset_seconds": {
            "type": "integer",
            "nullable": true,
            "description": "Čas snímku minus čas záznamu v sekundách (záporné: před záznamem)."
          },
          "resolved_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Kdy dodatečná kontrola plánovače zaznamenala konečný výsledek; null, když byl zapečetěný stav konečný."
          },
          "job_id": {
            "type": "string",
            "nullable": true,
            "description": "ID úlohy Save Page Now (autentizované požadavky)."
          },
          "follow_up_pending": {
            "type": "boolean",
            "description": "true, dokud plánovač ještě musí načíst stav úlohy."
          },
          "skip_reason": {
            "type": "string",
            "nullable": true,
            "description": "Proč URL nebyla odeslána, když je status skipped, skipped_sensitive nebo skipped_query: credentials_in_url, sensitive_path, opaque_path_segment, sensitive_fragment, sensitive_parameter_name, opaque_parameter_value, query_string (u starších řádků samotný stav)."
          },
          "resolved": {
            "type": "object",
            "nullable": true,
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "created",
                  "recent_existing",
                  "failed",
                  "rate_limited",
                  "unresolved"
                ]
              },
              "job_status": {
                "type": "string",
                "nullable": true,
                "description": "success, error nebo pending podle úlohy Save Page Now, null, pokud ji nebylo možné načíst."
              },
              "snapshot_url": {
                "type": "string",
                "nullable": true,
                "description": "https://web.archive.org/web/<14 digits>/<URL>, null, pokud chybí nebo není platná."
              },
              "snapshot_timestamp": {
                "type": "string",
                "nullable": true
              },
              "checked_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "reason": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "no_request_time",
                  "capture_deleted",
                  "capture_failed",
                  null
                ],
                "description": "Proč odpověď úlohy chybí: no_request_time (řádek nemá čas požadavku, od kterého by se naplánovala čtení), capture_deleted nebo capture_failed (záznam byl přesunut do koše nebo selhal, zatímco úloha čekala, takže se dodatečná kontrola neprovedla; u záznamu obnoveného z koše do 30 minut od požadavku se dodatečná kontrola provede znovu). Jinak null."
              }
            },
            "description": "Záznam o dodatečné kontrole (historie) jako pevná projekce: snapshot_url jen tehdy, když jde o platnou URL snímku Wayback pro snapshot_timestamp; reason jen tehdy, když dodatečná kontrola skončila bez odpovědi úlohy."
          }
        }
      },
      "CaptureStorage": {
        "type": "object",
        "description": "Doba uchování, duplicitní kopie a (u automatických záznamů) historie verzí.",
        "properties": {
          "retention": {
            "type": "object",
            "properties": {
              "years": {
                "type": "integer",
                "example": 10
              },
              "counted_from": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "Pozdější z hodnot created_at a posledního známého použití: poslední kontrola, která zjistila, že se stránka nezměnila, nebo okamžik, kdy tento záznam nahradil novější záznam téhož automatického záznamu."
              },
              "earliest_deletion_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "counted_from plus počet let, přibližně: smazání proběhne až při některém dalším průchodu plánovače a pozdější kontroly ho mohou posunout. Při právní blokaci null."
              },
              "legal_hold": {
                "type": "boolean"
              }
            }
          },
          "duplicate_copy": {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "none",
                  "pending",
                  "stored",
                  "not_copied"
                ],
                "description": "stored: druhá kopie balíčku (a jeho povýšeného důkazu OTS) se uchovává v samostatném bucketu v jiném regionu EU a maže se spolu s originálem. pending: probíhá kopírování (minuty). none: testovací balíčky a balíčky z doby před existencí duplikátu, dokud nejsou zkopírovány."
              },
              "copied_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              }
            }
          },
          "version": {
            "type": "object",
            "description": "Jen automatické záznamy.",
            "properties": {
              "superseded_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "superseded_by": {
                "type": "string",
                "nullable": true
              },
              "unchanged_first_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true,
                "description": "První kontrola (on_change), která zjistila, že se text stránky od tohoto záznamu nezměnil."
              },
              "unchanged_last_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "unchanged_checks": {
                "type": "integer",
                "description": "Zaznamenané kontroly beze změny (nejvýše jedna za hodinu)."
              }
            }
          }
        }
      },
      "WebhookEventType": {
        "type": "string",
        "enum": [
          "capture.completed",
          "capture.failed",
          "certify.completed",
          "certify.failed",
          "redaction.completed",
          "redaction.failed",
          "monitor.change_detected",
          "capture.anchor_confirmed",
          "schedule.paused"
        ],
        "description": "Událost z katalogu (tag Webhooky)."
      },
      "WebhookSubscriptionFilters": {
        "type": "object",
        "description": "Nejvýše jedno z host a schedule_id. Odběr pak dostává jen události řádků s tímto hostem (název hostitele zachycené URL malými písmeny) nebo daného automatického záznamu. `{}` pro žádný filtr.",
        "properties": {
          "host": {
            "type": "string",
            "example": "www.example.com"
          },
          "schedule_id": {
            "type": "string",
            "example": "sch_a1B2c3D4e5F6g7H8"
          }
        }
      },
      "WebhookSubscription": {
        "type": "object",
        "properties": {
          "subscription_id": {
            "type": "string",
            "example": "whs_a1B2c3D4e5F6g7H8"
          },
          "url": {
            "type": "string",
            "description": "https endpoint, na který se události odesílají metodou POST."
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "filters": {
            "$ref": "#/components/schemas/WebhookSubscriptionFilters"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "env": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "Prostředí přístupového údaje, kterým byl vytvořen. Ostrý odběr dostává jen události ostrých řádků, testovací jen události testovacích řádků."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": "string",
            "enum": [
              "key",
              "session"
            ],
            "description": "key: vytvořeno klíčem API; zneplatnění tohoto klíče odběr deaktivuje (disabled_reason key_revoked)."
          },
          "consecutive_failures": {
            "type": "integer",
            "description": "Neúspěšná doručení od posledního úspěšného."
          },
          "last_success_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_failure_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "last_error": {
            "type": "string",
            "nullable": true,
            "description": "Třída chyby posledního neúspěšného doručení (timeout, connection_failed, blocked_address, redirect_not_followed, http_<status>)."
          },
          "disabled_reason": {
            "type": "string",
            "nullable": true,
            "enum": [
              "gone",
              "failing",
              "key_revoked",
              null
            ],
            "description": "gone: endpoint odpověděl kódem 410. failing: všechna doručení po dobu 5 dnů selhala bez jediného úspěchu. key_revoked: klíč API, kterým byl vytvořen, byl zneplatněn. PATCH se status active ho znovu aktivuje."
          },
          "disabled_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        },
        "required": [
          "subscription_id",
          "url",
          "events",
          "filters",
          "description",
          "status",
          "env",
          "created_at",
          "created_by",
          "consecutive_failures",
          "last_success_at",
          "last_failure_at",
          "last_error",
          "disabled_reason",
          "disabled_at"
        ]
      },
      "WebhookSubscriptionCreated": {
        "type": "object",
        "properties": {
          "subscription_id": {
            "type": "string",
            "example": "whs_a1B2c3D4e5F6g7H8"
          },
          "url": {
            "type": "string",
            "description": "https endpoint, na který se události odesílají metodou POST."
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookEventType"
            }
          },
          "filters": {
            "$ref": "#/components/schemas/WebhookSubscriptionFilters"
          },
          "description": {
            "type": "string",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ]
          },
          "env": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ],
            "description": "Prostředí přístupového údaje, kterým byl vytvořen. Ostrý odběr dostává jen události ostrých řádků, testovací jen události testovacích řádků."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "created_by": {
            "type": "string",
            "enum": [
              "key",
              "session"
            ],
            "description": "key: vytvořeno klíčem API; zneplatnění tohoto klíče odběr deaktivuje (disabled_reason key_revoked)."
          },
          "secret": {
            "type": "string",
            "description": "whsec_, za nímž následuje standardní base64. Zobrazí se JEDNOU: každé doručení do tohoto odběru je jím podepsáno (Standard Webhooks). Uložte si ho hned; zpětně ho přečíst nelze. Opakování s Idempotency-Key do 24 hodin vrátí stejné tělo včetně tajného kódu."
          }
        },
        "required": [
          "subscription_id",
          "url",
          "events",
          "filters",
          "description",
          "status",
          "env",
          "created_at",
          "created_by",
          "secret"
        ]
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "example": "evt_a1B2c3D4e5F6g7H8"
          },
          "type": {
            "$ref": "#/components/schemas/WebhookEventType"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "env": {
            "type": "string",
            "enum": [
              "live",
              "test"
            ]
          },
          "data": {
            "type": "object",
            "description": "Tělo události tak, jak ho dostávají odběry, bez subscription_id a bez předem podepsaných odkazů (package_url, package_url_expires_at, upgraded_proof_url, compare.package_url)."
          }
        },
        "required": [
          "id",
          "type",
          "created_at",
          "env",
          "data"
        ]
      },
      "PrivateNote": {
        "type": "string",
        "nullable": true,
        "maxLength": 200,
        "description": "Vaše soukromá poznámka k záznamu (například \"záznam z mobilu\"), nejvýše 200 znaků, prostý text (pravidlo PlainText). Ukládá se jen u záznamu: NENÍ součástí zapečetěného balíčku důkazů (není v ZIP, PDF, manifestu ani v žádném hashi) a nemá žádnou důkazní váhu, lze ji proto později změnit nebo vymazat přes PATCH /v1/captures/{capture_id}, aniž by to ovlivnilo důkazy. Čte ji jen ten, kdo záznam pořídil. Pokud poznámku nechcete, pole vynechte nebo pošlete null či prázdný řetězec.",
        "example": "mobile capture"
      },
      "CaptureEvent": {
        "type": "object",
        "description": "Jedna událost řetězce událostí záznamů účtu. hash = SHA-256 (hex) kanonického JSON hashovaných polí (v, chain, seq, type, capture_id, manifest_sha256, actor, access, detail, at, prev_hash; klíče seřazené, bez bílých znaků, chybějící hodnoty jako null). prev_hash je hash předchozí události, pro seq 1 je to 64 nul.",
        "properties": {
          "v": {
            "type": "integer",
            "enum": [
              1
            ]
          },
          "chain": {
            "type": "string",
            "description": "Účet: uid u osobních záznamů, org_<org_id> u záznamů firmy."
          },
          "seq": {
            "type": "integer",
            "minimum": 1
          },
          "type": {
            "type": "string",
            "enum": [
              "trash",
              "restore",
              "erase",
              "purge",
              "retention_deletion",
              "account_deletion",
              "company_deletion",
              "legal_hold_on",
              "legal_hold_off",
              "s3_legal_hold",
              "import"
            ]
          },
          "capture_id": {
            "type": "string"
          },
          "manifest_sha256": {
            "type": "string",
            "nullable": true,
            "description": "SHA-256 souboru manifest.json záznamu, načtený před jakýmkoli smazáním."
          },
          "actor": {
            "type": "string",
            "description": "uid jednajícího účtu, nebo system u úklidových běhů serveru."
          },
          "access": {
            "type": "string",
            "description": "author, company_owner, matter_owner nebo system."
          },
          "detail": {
            "type": "string",
            "nullable": true,
            "description": "legal_hold_on / legal_hold_off: zdroj blokace (manual, bulk, matter:<id>, derived:<capture_id>), nebo u zrušení systémem (actor system) jeho kód důvodu subscription_ended; s3_legal_hold: výsledek v S3 (on, off, failed, unsupported, none); import: druh importovaného balíčku. Žádný volný text."
          },
          "at": {
            "type": "string",
            "format": "date-time",
            "description": "Kdy byla událost zapsána do řetězce. Nikdy dříve než at předchozí události."
          },
          "prev_hash": {
            "type": "string"
          },
          "hash": {
            "type": "string"
          },
          "occurred_at": {
            "type": "string",
            "format": "date-time",
            "description": "Kdy byla samotná akce potvrzena (transakce změny stavu). Nehashuje se. Obvykle se od at liší jen v řádu milisekund; později jen tehdy, když server opakoval připojení do řetězce (akce se zaznamenává ve stejné transakci jako změna, takže žádná se neztratí)."
          }
        }
      },
      "CaptureEventAnchor": {
        "type": "object",
        "description": "Denní ukotvení řetězce v OpenTimestamps: head_hash je hash události to_seq, který pokrývá i všechny dřívější události.",
        "properties": {
          "anchor_id": {
            "type": "string"
          },
          "day": {
            "type": "string",
            "format": "date"
          },
          "from_seq": {
            "type": "integer"
          },
          "to_seq": {
            "type": "integer"
          },
          "head_hash": {
            "type": "string"
          },
          "ots_proof_base64": {
            "type": "string",
            "nullable": true,
            "description": "Důkaz OpenTimestamps (soubor .ots, base64) nad head_hash."
          },
          "ots_status": {
            "type": "string",
            "enum": [
              "pending",
              "bitcoin",
              "unconfirmed"
            ],
            "description": "pending: ots_proof_base64 obsahuje závazek kalendářů (ots verify se ptá kalendářů); bitcoin: byl nahrazen důkazem povýšeným na bitcoinový blok (bitcoin_block_height); unconfirmed: do 14 dnů nebyl vrácen žádný bitcoinový důkaz, uložený důkaz lze stále ověřit přes kalendáře."
          },
          "bitcoin_block_height": {
            "type": "integer",
            "nullable": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ImportSummary": {
        "type": "object",
        "description": "Tři úrovně ověřeného balíčku.",
        "properties": {
          "kind_label_key": {
            "type": "string",
            "description": "Klíč popisku druhu balíčku, import_kind_<kind>."
          },
          "integrity": {
            "type": "string",
            "enum": [
              "verified",
              "failed"
            ]
          },
          "time_anchor": {
            "type": "string",
            "enum": [
              "eidas_qualified",
              "eidas_qualified_revocation_unknown",
              "ots_bitcoin_attested_unconfirmed",
              "ots_pending",
              "none"
            ]
          },
          "provenance": {
            "type": "string",
            "nullable": true,
            "enum": [
              "issued_by_proofsnap",
              "unverified",
              "registered_by_extension_account",
              "not_registered",
              "unknown",
              null
            ]
          },
          "registered_at": {
            "type": "string",
            "format": "date-time",
            "description": "Kdy registr rozšíření zaznamenal balíček (provenance registered_by_extension_account)."
          },
          "issued_at": {
            "type": "string",
            "format": "date-time",
            "description": "Kdy registr API zaznamenal vydání (provenance issued_by_proofsnap)."
          }
        }
      },
      "Import": {
        "type": "object",
        "properties": {
          "import_id": {
            "type": "string",
            "example": "imp_a1B2c3D4e5F6g7H8i9J0"
          },
          "status": {
            "type": "string",
            "enum": [
              "uploading",
              "verifying",
              "accepted",
              "rejected",
              "duplicate",
              "expired"
            ]
          },
          "filename": {
            "type": "string"
          },
          "size_bytes": {
            "type": "integer"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "upload_expires_at": {
            "type": "string",
            "format": "date-time",
            "description": "Jen u uploading: dokončete před tímto časem (24 hodin po vytvoření)."
          },
          "finished_at": {
            "type": "string",
            "format": "date-time",
            "description": "Kdy import dosáhl konečného stavu."
          },
          "capture_id": {
            "type": "string",
            "description": "Jen accepted: nový záznam (stejné ID jako import)."
          },
          "duplicate_of": {
            "type": "string",
            "description": "Jen u duplicate: Váš záznam, který už tento manifest obsahuje."
          },
          "kind": {
            "type": "string",
            "enum": [
              "web_capture_v21",
              "web_capture_legacy",
              "session",
              "file_certification_single",
              "file_certification_combined",
              "api_capture",
              "api_certify",
              "api_compare",
              "api_redaction"
            ],
            "description": "Druh balíčku, jakmile je rozpoznán."
          },
          "summary": {
            "$ref": "#/components/schemas/ImportSummary"
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "rejected a expired: kódy důvodů, například file_mismatch, file_missing, unlisted_file, bad_signature, no_hashed_files, unknown_schema, zip_too_large, test_package, ots_digest_mismatch, eidas_token_failed, forensic_chain_broken, size_mismatch, upload_not_completed, verification_incomplete. Jen kódy, nikdy názvy souborů."
          },
          "zip_sha256": {
            "type": "string",
            "description": "SHA-256 nahraného ZIP, jakmile je spočítán."
          },
          "manifest_sha256": {
            "type": "string",
            "description": "SHA-256 souboru manifest.json balíčku (accepted i duplicate)."
          },
          "matter_id": {
            "type": "string",
            "description": "Spis uvedený při vytvoření importu."
          },
          "matter_assignment": {
            "type": "string",
            "enum": [
              "assigned",
              "skipped"
            ],
            "description": "accepted s matter_id: zda byl záznam přidán do spisu (skipped, když byl spis do té doby zapečetěn, archivován nebo už pro vás nebyl otevřený; import zůstává accepted)."
          },
          "upload": {
            "type": "object",
            "description": "Jen s ?upload=true, dokud je status uploading.",
            "properties": {
              "upload_id": {
                "type": "string"
              },
              "part_size": {
                "type": "integer"
              },
              "parts": {
                "type": "array",
                "description": "Předem podepsané PUT URL částí, které ještě nebyly přijaty; nahrajte přes PUT přesně size_bytes.",
                "items": {
                  "type": "object",
                  "properties": {
                    "part_number": {
                      "type": "integer"
                    },
                    "url": {
                      "type": "string"
                    },
                    "size_bytes": {
                      "type": "integer"
                    }
                  }
                }
              },
              "expires_at": {
                "type": "string",
                "format": "date-time",
                "nullable": true
              },
              "received": {
                "type": "array",
                "nullable": true,
                "items": {
                  "type": "object",
                  "properties": {
                    "part_number": {
                      "type": "integer"
                    },
                    "etag": {
                      "type": "string"
                    },
                    "size_bytes": {
                      "type": "integer"
                    }
                  }
                }
              },
              "completed": {
                "type": "boolean",
                "description": "Nahrávání už bylo dokončeno: odešlete complete znovu."
              }
            }
          }
        }
      },
      "ImportVerification": {
        "type": "object",
        "description": "Zpráva o ověření zaznamenaná při importu (bez obsahu souborů, bez podrobností ve volném textu).",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "kind": {
            "type": "string",
            "enum": [
              "web_capture_v21",
              "web_capture_legacy",
              "session",
              "file_certification_single",
              "file_certification_combined",
              "api_capture",
              "api_certify",
              "api_compare",
              "api_redaction"
            ]
          },
          "format": {
            "type": "string"
          },
          "kind_label_key": {
            "type": "string"
          },
          "evidence_id": {
            "type": "string",
            "description": "ID, které balíček nese (ps_..., FC-..., cap_..., cert_..., cmp_..., red_...)."
          },
          "manifest_sha256": {
            "type": "string"
          },
          "zip_sha256": {
            "type": "string"
          },
          "anchor_sha256": {
            "type": "string",
            "description": "Hash, na který se časová razítka vztahují: hash manifestu, u certifikace jednoho souboru hash certifikovaného souboru."
          },
          "anchor_source": {
            "type": "string",
            "enum": [
              "manifest",
              "certified_file"
            ]
          },
          "checks": {
            "type": "object",
            "description": "structure, signature, files (listed, verified, presence_only, unhashed, os_junk_ignored), custody, forensic_chain, ots, eidas, test_mode.",
            "additionalProperties": true
          },
          "summary": {
            "$ref": "#/components/schemas/ImportSummary"
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "CaptureImport": {
        "type": "object",
        "description": "Jen u záznamu se source \"import\".",
        "properties": {
          "import_id": {
            "type": "string"
          },
          "package_kind": {
            "type": "string",
            "enum": [
              "web_capture_v21",
              "web_capture_legacy",
              "session",
              "file_certification_single",
              "file_certification_combined",
              "api_capture",
              "api_certify",
              "api_compare",
              "api_redaction"
            ]
          },
          "kind_label_key": {
            "type": "string"
          },
          "package_format": {
            "type": "string"
          },
          "original_evidence_id": {
            "type": "string"
          },
          "original_filename": {
            "type": "string",
            "nullable": true
          },
          "imported_at": {
            "type": "string",
            "format": "date-time"
          },
          "captured_at_basis": {
            "type": "string",
            "enum": [
              "package_claim"
            ],
            "description": "captured_at importovaného balíčku je čas, který balíček uvádí, nikdy čas, který zaznamenal ProofSnap."
          },
          "manifest_sha256": {
            "type": "string"
          },
          "zip_sha256": {
            "type": "string"
          },
          "summary": {
            "$ref": "#/components/schemas/ImportSummary"
          },
          "levels": {
            "type": "object",
            "properties": {
              "integrity": {
                "type": "string"
              },
              "time_anchor": {
                "type": "string"
              },
              "provenance": {
                "type": "string",
                "nullable": true
              }
            }
          },
          "verification": {
            "$ref": "#/components/schemas/ImportVerification"
          },
          "provenance": {
            "type": "object",
            "properties": {
              "level": {
                "type": "string"
              },
              "source": {
                "type": "string",
                "nullable": true,
                "enum": [
                  "api_ledger",
                  "extension_registry",
                  null
                ]
              },
              "issued_at": {
                "type": "string",
                "nullable": true
              },
              "registered_at": {
                "type": "string",
                "nullable": true
              },
              "reason": {
                "type": "string"
              }
            }
          }
        }
      },
      "Rule902DisabledWarnings": {
        "type": "array",
        "description": "Uvádí se jen tehdy, když požadavek žádal šablonu certifikace (include_rule_902: true, nebo u záznamu neprázdné evidence_pack.custodian), zatímco je šablona vypnutá. Požadavek byl přijat a příznak ignorován: rule_902_certification.pdf se nevygeneruje.",
        "items": {
          "type": "object",
          "properties": {
            "code": {
              "type": "string",
              "enum": [
                "RULE902_DISABLED"
              ]
            },
            "message": {
              "type": "string",
              "example": "The FRE 902 certification template (rule_902_certification.pdf) is currently disabled. include_rule_902 was accepted and ignored: the package does not contain the template."
            }
          },
          "required": [
            "code",
            "message"
          ]
        }
      }
    }
  }
}
