{"openapi":"3.0.3","info":{"title":"Alighieria API","version":"1.0.0","description":"The Alighieria API brings the editorial engine behind\n[alighieria.com](https://www.alighieria.com) to your own tools: upload a\nmanuscript once, then run corrections, translations, dossiers, synopses,\nindexes, EPUBs, AI detection, plagiarism checks and marketing content on it.\n\nEvery request goes to `https://api.alighieria.com/api/v1` over HTTPS and\nreturns JSON, except artifact downloads, which return files.\n\n## Quickstart\n\nEvery workflow follows the same three steps:\n\n1. **Upload** a source file with `POST /process-document` and keep its `id`.\n2. **Launch** a job (for example `POST /generate-synopsis`) with that id as\n   `doc_id`. You get `202 Accepted` and a job `id` straight away.\n3. **Poll** `GET /resource/{resource_type}/{id}?fields=status` until\n   `resource_status` is `completed`, then read the result with\n   `GET /resource/{resource_type}/{id}` or download the artifact.\n\nCreate a key in the [dashboard](https://app.alighieria.com/account). Every\nendpoint below has a ready-to-run code sample and a **Test request** button.\n\n## Python SDK\n\nThe official [`alighieria`](https://pypi.org/project/alighieria/) package\n(Python 3.10 or later) wraps every endpoint below, with sync and async\nclients. It waits for jobs, downloads artifacts, raises typed errors and\nretries only when a repeat cannot charge you twice.\n\n```bash\npip install alighieria\n```\n\n```python\nfrom alighieria import Alighieria\n\nclient = Alighieria()  # reads ALIGHIERIA_API_KEY\n\ndocument = client.documents.upload(\n    \"the_long_winter.docx\", title=\"The Long Winter\", author=\"Ana P\u00e9rez\"\n).wait()\n\nrun = client.corrections.create(document.id, correction_types=[\"editorial\"]).wait()\nrun.download(\"corrected/\")\n```\n\nThe [package page](https://pypi.org/project/alighieria/) has the full guide:\njobs, conversations, errors, retries and the async client.\n\n## TypeScript SDK\n\nThe official [`alighieria`](https://www.npmjs.com/package/alighieria) npm\npackage (Node 20 or later) does the same for TypeScript and JavaScript: fully\ntyped, with no dependencies, for ESM and CommonJS.\n\n```bash\nnpm install alighieria\n```\n\n```ts\nimport Alighieria from \"alighieria\";\n\nconst client = new Alighieria(); // reads ALIGHIERIA_API_KEY\n\nconst document = await client.documents.upload({\n  file: \"the_long_winter.docx\",\n  title: \"The Long Winter\",\n  author: \"Ana P\u00e9rez\",\n});\nawait document.wait();\n\nconst run = await client.corrections.create({\n  doc_id: document.id,\n  correction_types: [\"editorial\"],\n});\nawait run.wait();\nawait run.download(\"corrected/\");\n```\n\nEvery endpoint below shows its call in both SDKs.\n\n## Authentication\n\nSend your key in the `X-API-Key` header on every request. `GET /health` is\nthe only public endpoint. Keys are secret: call the API from your backend,\nnever from a browser or mobile app. A missing, invalid or revoked key returns\n`401`; a key without permission for an operation returns `403`.\n\n## Asynchronous jobs\n\nUploads and generation jobs run in the background. Launch endpoints answer\n`202 Accepted` with:\n\n```json\n{\n  \"status\": \"success\",\n  \"message\": \"Synopsis generation started\",\n  \"id\": \"6650f1c2e4b0a1d2c3f4a5b6\",\n  \"resource_type\": \"synopsis\",\n  \"resource_status\": \"processing\",\n  \"source_id\": \"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx\"\n}\n```\n\nPoll `GET /resource/{resource_type}/{id}?fields=status` until\n`resource_status` leaves `processing`. Status polls have their own limit\n(60/min, see Rate limits below): poll every 5 to 10 seconds, and back off\non long jobs.\n\n| `resource_status` | Meaning |\n| --- | --- |\n| `processing` | Queued or running. `progress` (0\u2013100) is included when available. |\n| `completed` | Finished. Read it with `fields=full` or download the artifact. |\n| `partial` | Finished with gaps (for example, one correction family failed). |\n| `error`, `failed` | Did not finish. Credits reserved for the job are released. |\n\nMost jobs take from a few seconds to a few minutes; full corrections, AI\ndetection and plagiarism checks of long books can take longer.\n\n## Errors\n\nErrors use standard HTTP status codes and a stable JSON envelope:\n\n```json\n{ \"status\": \"error\", \"message\": \"Missing required parameters: doc_id\" }\n```\n\n`message` is meant for people and logs; branch on the status code. When the\nfix is on the account side, the body also carries a `code`:\n\n```json\n{ \"status\": \"error\", \"message\": \"Subscription is not active\", \"code\": \"inactive_subscription\" }\n```\n\n`code` is `no_subscription` or `inactive_subscription` (`403`),\n`insufficient_credits` (`402`) or `turn_in_progress` (`409`). A `403`\nwithout `code` means the key lacks the permission.\n\n| Code | When |\n| --- | --- |\n| `400` | Missing or invalid parameter. |\n| `401` | Missing, invalid or revoked API key. |\n| `402` | Not enough credits. |\n| `403` | The key lacks permission, the subscription is inactive, or the resource belongs to someone else. |\n| `404` | The resource does not exist. |\n| `409` | Conflicting state: a run is already active, the artifact is not ready, or an idempotency key was reused. |\n| `413` | File or request body larger than 100 MB. |\n| `429` | Rate limit exceeded. See `Retry-After`. |\n| `500` | Unexpected error. Retry with exponential backoff. |\n| `503` | A dependency is temporarily unavailable. Retry later. |\n\n## Rate limits\n\nLimits apply per user: every API key of your account shares the same\ncounters, so creating or rotating a key does not reset them. Each endpoint\nhas its own counter:\n\n| Endpoints | Limit |\n| --- | --- |\n| `POST /generate-content` | 20/min |\n| Other launches, `process-document`, `markdown-document`, every `/conversations` route and downloads | 10/min |\n| Status polls (`GET /resource/{resource_type}/{id}?fields=status`) | 60/min |\n| Lists and reads (`/resource` with `fields=full`, `/documents`, `/generations`, `/subscription`, `/resource-types`) | 10/min, 30/hour and 100/day |\n\nResponses include `X-RateLimit-Limit`, `X-RateLimit-Remaining` and\n`X-RateLimit-Reset`. A `429` also carries `Retry-After` (seconds): wait that\nlong before retrying.\n\n## Credits\n\nGeneration jobs and conversation turns consume credits from your\nsubscription. Uploads are free except PDFs, which cost 1 credit per 100\npages, rounded up: a 250-page PDF costs 3 credits, whatever its `doc_type`.\nWhen the balance is too low the request fails with `402` before any work\nstarts. Check your balance with `GET /subscription`. Correction runs report\ntheir cost in `costs` and `total_cost`; conversation turns report\n`task_cost`.\n\n## Idempotency\n\n`POST /generate-corrections` and `POST /markdown-document` accept an\n`X-Idempotency-Key` header (a UUID is ideal). For 24 hours, retrying with the\nsame key and the same request replays the first response instead of running\nthe job twice. Reusing a key with a different request, or while the first\nrequest is still running, returns `409`.\n\nThe key is matched against the exact request bytes. Multipart bodies include\na random boundary, so send idempotent requests as JSON or\n`application/x-www-form-urlencoded`.\n\nOther launch endpoints are not idempotent: a retry starts a new job and\ncharges again. Before retrying after a timeout, check `GET /generations` for\na job you already started.\n\n## Language and locale\n\nTwo separate parameters control language:\n\n- **`language`** sets the language of the generated text (dossiers,\n  translations, content): `spanish`, `catalan`, `galician`, `basque`,\n  `english`, `french`, `italian`, `portuguese`, `german` or `hebrew`. Any\n  other value is rejected with `400`. The EPUB builder takes a BCP 47 code\n  such as `es` or `en-US`.\n- **`locale`** (`es`, `en` or `fr`, default `es`) sets the language of\n  response messages, report labels and notification emails. Unknown values\n  fall back to `es`.\n\n## Conversations\n\n`/conversations` lets you chat with a processed document. Create a\nconversation for a completed `doc_id`, send turns with\n`POST /conversations/{id}/turns` and read the full history with\n`GET /conversations/{id}`. Turns answer synchronously, with no polling: the\nreply is in `assistant_message`, the passages it relied on in `sources`, and\nthe credits used in `task_cost`.\n\nCreating a conversation is free. Each turn is charged by the text the\nassistant processes (the document, the conversation history and its reply)\nand the web searches it runs, so long conversations cost more per turn.\n\n## Markdown documents\n\nIf your text is already digital, skip the upload step:\n`POST /markdown-document` stores markdown as a book, style guide or analysis\ntemplate, and it is ready to use immediately.\n\n## Support\n\nWrite to [info@alighieria.com](mailto:info@alighieria.com) with the request\ntime and endpoint. Never include your API key.\n","contact":{"name":"Alighieria API Support","email":"info@alighieria.com","url":"https://www.alighieria.com"},"termsOfService":"https://www.alighieria.com/terminos","license":{"name":"Proprietary","url":"https://www.alighieria.com/terminos"}},"servers":[{"url":"https://api.alighieria.com"}],"security":[{"ApiKeyAuth":[]}],"tags":[{"name":"Health","description":"Check that the API is up. No API key required."},{"name":"Account","description":"Your subscription, permissions and credit balance."},{"name":"Documents","description":"Source files every job reads: manuscripts, style guides, brand voices, analysis templates and index sources. Upload a file with `POST /process-document`, or store markdown directly with `POST /markdown-document`."},{"name":"Generation","description":"Asynchronous jobs. Each launch returns `202` with a job `id`; poll `GET /resource/{resource_type}/{id}?fields=status` until it finishes, then read the result or download the artifact."},{"name":"Conversations","description":"Chat with a processed document. Turns answer synchronously and report the credits used in `task_cost`."},{"name":"Resources","description":"Poll, read, list and delete documents and job results."},{"name":"Download","description":"Download the files produced by completed jobs: annotated DOCX, PDF reports, IDML, EPUB."}],"x-tagGroups":[{"name":"Get started","tags":["Health","Account"]},{"name":"Inputs","tags":["Documents"]},{"name":"Jobs","tags":["Generation","Resources","Download"]},{"name":"Chat","tags":["Conversations"]}],"externalDocs":{"description":"Create and manage API keys","url":"https://app.alighieria.com/account"},"paths":{"/health":{"get":{"summary":"Check API health","description":"Returns `200` while the API accepts requests. No API key required; use it\nfor uptime monitors and connectivity checks.","responses":{"200":{"description":"The API is up.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Success"},"example":{"status":"success","message":"API is operational"}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"tags":["Health"],"security":[],"operationId":"getHealth","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nclient.health()"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nawait client.health();"}]}},"/subscription":{"get":{"summary":"Get your subscription","description":"Plan, billing period, credit balance and next reload date of the account\nthat owns the API key, plus the permissions of the key itself. Check\n`credits_left` before launching large jobs to avoid `402` responses.","responses":{"200":{"description":"The subscription of the key owner.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Subscription"}}}]},"example":{"status":"success","message":"Subscription retrieved successfully","data":{"plan":"Superior","period":"monthly","status":"active","started_at":"2026-03-01T09:30:00Z","credits_left":420,"next_credit_reload_at":"2026-10-01T09:30:00Z","permissions":["create:document","read:resources"]}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The account has no subscription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"No subscription found"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Account"],"operationId":"getSubscription","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nsubscription = client.subscription.retrieve()\nprint(subscription.plan, subscription.credits_left)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst subscription = await client.subscription.retrieve();\nconsole.log(subscription.plan, subscription.credits_left);"}]}},"/process-document":{"post":{"summary":"Upload a document","description":"Upload the source file that jobs read. The returned `id` is the `doc_id`\nevery generation endpoint expects.\n\n| `doc_type` | Use it for | Pass the id as |\n| :-- | :-- | :-- |\n| *(omitted)* | A manuscript or book | `doc_id` |\n| `guide` | A house style guide | `guide_id` in `/generate-corrections` |\n| `brand_voice` | Brand voice notes | `brand_voice_id` in `/generate-content` |\n| `analysis_template` | A custom dossier structure | `analysis_template_id` in `/generate-dossier` |\n| `index_source` | An existing book index | `index_source_id` in `/generate-index` |\n\nAccepted formats: PDF, DOCX, EPUB, XML, IDML and Markdown, up to\n100 MB. Legacy Word `.doc` files are rejected: save them as `.docx`.\nIndex sources accept PDF, DOCX, EPUB and XML (PDFs up to 50 pages).\nSend either `file` or `file_url`, not both.\n\nProcessing is asynchronous: poll\n`GET /resource/{resource_type}/{id}?fields=status` until it is\n`completed`. Uploads are free except PDFs, which cost 1 credit per 100\npages, rounded up (a 250-page PDF costs 3 credits).","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/UploadDocumentRequest"},"encoding":{"file":{"contentType":"application/octet-stream"}}}}},"responses":{"202":{"description":"Processing started.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["id","resource_type","resource_status"],"properties":{"id":{"type":"string","description":"Document id. Use it as `doc_id` (or `guide_id`, etc.)."},"resource_type":{"type":"string","enum":["document","guide","brand_voice","analysis_template","index_source"]},"resource_status":{"type":"string","enum":["processing"]}}}]},"example":{"status":"success","message":"Word processing started","id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","resource_type":"document","resource_status":"processing"}}}},"400":{"description":"Missing field, unsupported format, or invalid URL.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing_author":{"summary":"Missing author","value":{"status":"error","message":"Missing required parameters: author"}},"no_source":{"summary":"Neither file nor file_url","value":{"status":"error","message":"You must provide either a file upload or a file URL"}},"format":{"summary":"Unsupported format","value":{"status":"error","message":"Invalid file type, only PDF, DOCX, EPUB, XML, IDML and Markdown files are accepted"}},"legacy_word":{"summary":"Legacy Word (.doc)","value":{"status":"error","message":"Legacy Word (.doc) files are not supported. Save the file as .docx and upload it again."}},"url":{"summary":"URL rejected (not HTTPS, private or unreachable)","value":{"status":"error","message":"URL is not allowed"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Documents"],"operationId":"uploadDocument","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\ndocument = client.documents.upload(\n    \"the_long_winter.docx\", title=\"The Long Winter\", author=\"Ana P\u00e9rez\"\n)\ndocument.wait()\nprint(document.id)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst document = await client.documents.upload({\n  file: \"the_long_winter.docx\",\n  title: \"The Long Winter\",\n  author: \"Ana P\u00e9rez\",\n});\nawait document.wait();\nconsole.log(document.id);"}]}},"/markdown-document":{"post":{"summary":"Create or update a markdown document","description":"Store markdown text as a manuscript (`docs`), style guide (`guides`) or\nanalysis template (`analysis_templates`). Unlike uploads, the document is\n`completed` immediately: use its `doc_id` in jobs right away. It is free.\n\nOmit `doc_id` to create a document (`201`). Send the `doc_id` of a\nmarkdown document you created to replace its content (`200`).\n\nSend `X-Idempotency-Key` to make retries safe.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkdownDocumentWrite"}}}},"responses":{"201":{"description":"Document created.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkdownDocument"},"example":{"status":"success","message":"Markdown document created successfully","doc_id":"md_8b6f3e2a-1c4d-4f7a-9e2b-5d3c1a0f9e8d","collection":"guides","title":"House style guide","file_type":"md","word_count":14,"status_resource":"completed"}}}},"200":{"description":"Document updated.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarkdownDocument"},"example":{"status":"success","message":"Markdown document updated successfully","doc_id":"md_8b6f3e2a-1c4d-4f7a-9e2b-5d3c1a0f9e8d","collection":"guides","title":"House style guide (2026)","file_type":"md","word_count":8,"status_resource":"completed"}}}},"400":{"description":"Invalid body, or `doc_id` is not a markdown document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing field","value":{"status":"error","message":"content is required"}},"too_long":{"summary":"Content too long","value":{"status":"error","message":"content exceeds 2000000 characters"}},"not_markdown":{"summary":"Target was uploaded as a file","value":{"status":"error","message":"Only markdown documents can be updated through this endpoint"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"`doc_id` does not exist in that collection.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Document not found"}}}},"409":{"$ref":"#/components/responses/Conflict"},"429":{"$ref":"#/components/responses/RateLimited"}},"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"tags":["Documents"],"operationId":"upsertMarkdownDocument","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nguide = client.documents.create_markdown(\n    title=\"House style\", content=\"# Serial commas\\n...\", collection=\"guides\"\n)\nprint(guide.doc_id)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst guide = await client.documents.createMarkdown({\n  title: \"House style\",\n  content: \"# Serial commas\\n...\",\n  collection: \"guides\",\n});\nconsole.log(guide.doc_id);"}]},"get":{"summary":"Get a markdown document","description":"Returns the stored markdown `content` of a manuscript, style guide or\nanalysis template you own.","responses":{"200":{"description":"The document and its markdown.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/MarkdownDocument"},{"type":"object","properties":{"content":{"type":"string","description":"Markdown source."}}}]},"example":{"status":"success","message":"Markdown document retrieved successfully","doc_id":"md_8b6f3e2a-1c4d-4f7a-9e2b-5d3c1a0f9e8d","collection":"guides","title":"House style guide","author":"Editorial team","description":"","content":"# Style guide\n\n- Use the serial comma.","file_type":"md","word_count":8,"status_resource":"completed"}}}},"400":{"description":"`collection` or `doc_id` is missing or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"collection must be docs, guides, or analysis_templates"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The document does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Document not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"parameters":[{"name":"collection","in":"query","required":true,"schema":{"$ref":"#/components/schemas/MarkdownCollection"}},{"name":"doc_id","in":"query","required":true,"schema":{"type":"string"}}],"tags":["Documents"],"operationId":"getMarkdownDocument","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nguide = client.documents.retrieve_markdown(\"MARKDOWN_DOC_ID\", collection=\"guides\")\nprint(guide.content)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst guide = await client.documents.retrieveMarkdown(\"MARKDOWN_DOC_ID\", {\n  collection: \"guides\",\n});\nconsole.log(guide.content);"}]}},"/documents":{"get":{"summary":"List documents","description":"Your uploaded manuscripts, newest first by default. Style guides, brand\nvoices and analysis templates are not included; read them with\n`GET /resource/{resource_type}/{id}`.","responses":{"200":{"description":"A page of documents.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/DocumentSummary"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}]},"example":{"status":"success","message":"Documents retrieved successfully","data":[{"id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","title":"The Long Winter","author":"Ana P\u00e9rez","status":"completed","created_at":"2026-09-30T10:12:00Z","description":"Second draft, after structural edit"}],"pagination":{"total":1,"limit":50,"offset":0,"has_next":false,"has_prev":false}}}}},"400":{"description":"Invalid `status`, `limit` or `offset`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"status":{"summary":"Unknown status","value":{"status":"error","message":"Invalid status. Use processing, completed, error, partial, or failed."}},"limit":{"summary":"Limit out of range","value":{"status":"error","message":"limit must be between 1 and 100"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"status","in":"query","required":false,"description":"Return only documents in this state.","schema":{"$ref":"#/components/schemas/ResourceStatus"}},{"name":"search","in":"query","required":false,"description":"Case-insensitive substring of the title or author, matched literally.","schema":{"type":"string"}},{"name":"sort","in":"query","required":false,"schema":{"type":"string","enum":["created_at","title"],"default":"created_at"}},{"$ref":"#/components/parameters/Order"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"tags":["Documents"],"operationId":"listDocuments","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nfor document in client.documents.iter(search=\"winter\"):\n    print(document.id, document.title)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nfor await (const document of client.documents.iter({ search: \"winter\" })) {\n  console.log(document.id, document.title);\n}"}]}},"/generate-corrections":{"post":{"summary":"Correct a manuscript","description":"Runs one or more correction families over a document in a single job:\n\n| Family | What it finds | Notes |\n| :-- | :-- | :-- |\n| `editorial` | Spelling, grammar, punctuation and style | Applies your `guide_id` when sent |\n| `raccord` | Continuity errors: names, dates, descriptions that change | Report only |\n| `fact_checking` | Verifiable claims that look wrong, with web sources | |\n| `layout` | Widows, orphans, short last lines and bad hyphenation | PDF documents only |\n\nThe `202` response reports the credits per family in `costs` and the sum in\n`total_cost`. Poll `GET /resource/correction_run/{id}?fields=status`\n(`suites` shows each family's progress), read the findings with\n`fields=full`, and download the annotated file (tracked-changes DOCX,\nannotated PDF or IDML, matching the source format) with\n`GET /download-corrections`.\n\nOnly one active run per document. Send `X-Idempotency-Key` with a JSON or\nform-urlencoded body to make retries safe.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorrectionRunRequest"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/CorrectionRunRequest"},"encoding":{"correction_types":{"style":"form","explode":true}}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/CorrectionRunRequest"}}}},"responses":{"202":{"description":"Run started.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/JobAccepted"},{"type":"object","properties":{"correction_types":{"type":"array","items":{"$ref":"#/components/schemas/CorrectionFamily"}},"suites":{"type":"array","description":"Same as `correction_types`.","items":{"$ref":"#/components/schemas/CorrectionFamily"}},"costs":{"type":"object","description":"Credits reserved per family.","additionalProperties":{"type":"integer"}},"total_cost":{"type":"integer","description":"Credits reserved for the whole run."}}}]},"example":{"status":"success","message":"Correction run started","id":"6650f1c2e4b0a1d2c3f4a5b6","resource_status":"processing","resource_type":"correction_run","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","suites":["editorial","raccord"],"correction_types":["editorial","raccord"],"costs":{"editorial":18,"raccord":12},"total_cost":30}}}},"400":{"description":"Missing field, unknown family, `layout` on a non-PDF, or document still processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing_types":{"summary":"No families","value":{"status":"error","message":"correction_types is required"}},"not_ready":{"summary":"Document still processing","value":{"status":"error","message":"Document is not completed"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The document or style guide does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Document not found"}}}},"409":{"description":"A run is already active for this document, or the idempotency key conflicts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"active_run":{"summary":"Run already active","value":{"status":"error","message":"An active correction run already exists for this document"}},"key_reused":{"summary":"Key reused with another body","value":{"status":"error","message":"Idempotency key was reused with a different request payload"}},"in_progress":{"summary":"First request still running","value":{"status":"error","message":"Idempotent request is already in progress"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"$ref":"#/components/parameters/IdempotencyKey"}],"tags":["Generation"],"operationId":"createCorrectionRun","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nrun = client.corrections.create(\n    \"DOC_ID\", correction_types=[\"editorial\", \"raccord\"], guide_id=\"GUIDE_ID\"\n)\nrun.wait()\nprint(run.status, run.suites)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst run = await client.corrections.create({\n  doc_id: \"DOC_ID\",\n  correction_types: [\"editorial\", \"raccord\"],\n  guide_id: \"GUIDE_ID\",\n});\nawait run.wait();\nconsole.log(run.status, run.suites);"}]}},"/generate-translation":{"post":{"summary":"Translate a document","description":"Translates a completed document into `language`. Read the translated text\nwith `GET /resource/translation/{id}` once completed. When the source is an\nIDML file, also download the translated InDesign package with\n`GET /download-translation-idml`.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TranslationRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/TranslationRequest"}}}},"responses":{"202":{"description":"Translation started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"},"example":{"status":"success","message":"Translation generation started","id":"6650f1c2e4b0a1d2c3f4a5b9","resource_status":"processing","resource_type":"translation","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx"}}}},"400":{"description":"Missing `doc_id`, or `language` missing or unknown.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"language is missing","value":{"status":"error","message":"Missing required parameters: language"}},"unknown":{"summary":"Unknown language","value":{"status":"error","message":"language must be one of: spanish, catalan, galician, basque, english, french, italian, portuguese, german, hebrew"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createTranslation","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\ntranslation = client.translations.create(\"DOC_ID\", language=\"french\")\ntranslation.wait()\nprint(translation.result().content)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst translation = await client.translations.create({ doc_id: \"DOC_ID\", language: \"french\" });\nawait translation.wait();\nconsole.log((await translation.result()).content);"}]}},"/generate-translation-review":{"post":{"summary":"Review a translation","description":"Compares a translation with its original and reports the passages where\nit departs from the source. Upload and process both documents first. Read the findings with `GET /resource/translation_review/{id}` and,\nwhen produced, download the annotated files with\n`GET /download-translation-review-docx` or\n`GET /download-translation-review-pdf`.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TranslationReviewRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/TranslationReviewRequest"}}}},"responses":{"202":{"description":"Review started. `source_id` is the translation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"},"example":{"status":"success","message":"Translation_review generation started","id":"6650f1c2e4b0a1d2c3f4a5ba","resource_status":"processing","resource_type":"translation_review","source_id":"9c1e3f2a-7d5b-8a4e-0f9c-6f5e4d3c2b1a_the_long_winter_en_docx"}}}},"400":{"description":"Missing ids, or both ids are the same document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Missing required parameters: translation_doc_id"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createTranslationReview","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nreview = client.translation_reviews.create(\n    original_doc_id=\"ORIGINAL_DOC_ID\", translation_doc_id=\"TRANSLATION_DOC_ID\"\n)\nreview.wait()\nprint(review.result().findings)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst review = await client.translationReviews.create({\n  original_doc_id: \"ORIGINAL_DOC_ID\",\n  translation_doc_id: \"TRANSLATION_DOC_ID\",\n});\nawait review.wait();\nconsole.log((await review.result()).findings);"}]}},"/generate-dossier":{"post":{"summary":"Generate a dossier","description":"Produces one of the two editorial documents from the web Dossier tab:\n\n- `kind=analysis`: an editorial dossier on the book. Send\n  `analysis_template_id` to follow your own structure. Result type:\n  `analysis`.\n- `kind=reading_report`: a publisher's reading report. Result type:\n  `report`.\n\nPoll with the `resource_type` returned in the `202` response.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/DossierRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/DossierRequest"}}}},"responses":{"202":{"description":"Job started.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/JobAccepted"},{"type":"object","properties":{"resource_type":{"type":"string","enum":["analysis","report"]}}}]},"examples":{"analysis":{"summary":"kind=analysis","value":{"status":"success","message":"Analysis generation started","id":"6650f1c2e4b0a1d2c3f4a5bb","resource_status":"processing","resource_type":"analysis","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx"}},"reading_report":{"summary":"kind=reading_report","value":{"status":"success","message":"Report generation started","id":"6650f1c2e4b0a1d2c3f4a5bc","resource_status":"processing","resource_type":"report","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx"}}}}}},"400":{"description":"Missing `doc_id`, invalid `kind` or unknown `language`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"kind":{"summary":"Invalid kind","value":{"status":"error","message":"kind must be analysis or reading_report"}},"language":{"summary":"Unknown language","value":{"status":"error","message":"language must be one of: spanish, catalan, galician, basque, english, french, italian, portuguese, german, hebrew"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createDossier","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\ndossier = client.dossiers.create(\"DOC_ID\", kind=\"reading_report\", language=\"english\")\ndossier.wait()\nprint(dossier.result().content)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst dossier = await client.dossiers.create({\n  doc_id: \"DOC_ID\",\n  kind: \"reading_report\",\n  language: \"english\",\n});\nawait dossier.wait();\nconsole.log((await dossier.result()).content);"}]}},"/generate-synopsis":{"post":{"summary":"Generate a synopsis","description":"Writes a synopsis of a completed document. Read it from `content` with\n`GET /resource/synopsis/{id}` once completed.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/SynopsisRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/SynopsisRequest"}}}},"responses":{"202":{"description":"Synopsis started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"},"example":{"status":"success","message":"Synopsis generation started","id":"6650f1c2e4b0a1d2c3f4a5b8","resource_status":"processing","resource_type":"synopsis","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx"}}}},"400":{"description":"Missing `doc_id`, or `word_count` or `tone` out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"word_count":{"summary":"word_count out of range","value":{"status":"error","message":"word_count must be an integer between 100 and 500"}},"tone":{"summary":"Unknown tone","value":{"status":"error","message":"tone must be one of: entusiasta, misterioso, sobrio, descriptivo"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createSynopsis","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nsynopsis = client.synopses.create(\"DOC_ID\", word_count=300)\nsynopsis.wait()\nprint(synopsis.result().content)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst synopsis = await client.synopses.create({ doc_id: \"DOC_ID\", word_count: 300 });\nawait synopsis.wait();\nconsole.log((await synopsis.result()).content);"}]}},"/generate-content":{"post":{"summary":"Generate marketing content","description":"Writes channel-ready content about one or more completed books. Read the\nresult from `content` with `GET /resource/content/{id}`.\n\n| `content_type` | Output | Books |\n| :-- | :-- | :-- |\n| `thread_x` | X thread about a book | 1 |\n| `story_x` | X thread weaving several books around a concept | 1\u20133 |\n| `launch_x` | Short X launch post with a conceptual tone | 1 |\n| `mention_x` | X post (up to 280 characters) announcing an award | 1 |\n| `micropost_ig` | Instagram educational carousel | 1 |\n| `author_profile_ig` | Instagram carousel portraying the author | 1 |\n| `story_ig` | Instagram ideas carousel across several books | 1\u20133 |\n| `quotes_ig` | Selection of notable quotes | 1 |\n| `catalog_ig` | Monthly highlights carousel from a press catalogue | 1 |\n| `mention_ig` | Award announcement blurb and photo caption | 1 |\n| `write_up_ig` | Instagram carousel from a press article | 1 |\n| `curiosity_tiktok` | To-camera TikTok script | 1 |\n| `story_web` | Feature article weaving several books around a concept | 1\u20133 |\n| `press_web` | Press release | 1 |\n\nGroup pieces of one campaign with `plan_id` and `plan_name`. Send a\n`brand_voice_id` to match your house voice.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ContentRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/ContentRequest"}}}},"responses":{"202":{"description":"Content generation started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"},"example":{"status":"success","message":"Content generation started","id":"6650f1c2e4b0a1d2c3f4a5bd","resource_status":"processing","resource_type":"content"}}}},"400":{"description":"Unknown `content_type` or `language`, malformed `doc_ids`, or wrong number of books.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"doc_ids":{"summary":"doc_ids is not a JSON array","value":{"status":"error","message":"Invalid doc_ids format: doc_ids must be a JSON array"}},"too_many":{"summary":"Too many books","value":{"status":"error","message":"content_type 'thread_x' accepts at most 1 document(s)"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createContent","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nthread = client.content.create(\"thread_x\", doc_ids=[\"DOC_ID\"], language=\"english\")\nthread.wait()\nprint(thread.result().content)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst thread = await client.content.create({\n  content_type: \"thread_x\",\n  doc_ids: [\"DOC_ID\"],\n  language: \"english\",\n});\nawait thread.wait();\nconsole.log((await thread.result()).content);"}]}},"/generate-index":{"post":{"summary":"Build a book index","description":"Builds a terms index with page references. The fields you send choose the\nmode:\n\n| Mode | Send | Requirements |\n| :-- | :-- | :-- |\n| Automatic | `original_doc_id` | A completed, paginated PDF |\n| From an existing index | `original_doc_id` + `index_source_id` | An index uploaded with `doc_type=index_source` |\n| Translated edition | `original_doc_id` + `translated_doc_id` + `index_source_id` | Two completed, paginated PDFs and the original's index |\n\nIn translated mode, `index_term_mode` decides whether headings are\ntranslated (`translate`, default) or kept as in the source (`preserve`).\nRead the result with `GET /resource/index/{id}`.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/IndexRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/IndexRequest"}}}},"responses":{"202":{"description":"Index started. `source_id` is the translated document in translated mode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"},"example":{"status":"success","message":"Index generation started","id":"6650f1c2e4b0a1d2c3f4a5be","resource_status":"processing","resource_type":"index","source_id":"7a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d_the_long_winter_pdf"}}}},"400":{"description":"Invalid field combination or documents that do not meet the mode requirements.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing_source":{"summary":"Translated mode without index source","value":{"status":"error","message":"index_source_id is required when translated_doc_id is present"}},"not_pdf":{"summary":"Automatic mode on a non-PDF","value":{"status":"error","message":"Automatic index generation requires a completed, paginated PDF"}},"term_mode":{"summary":"index_term_mode outside translated mode","value":{"status":"error","message":"index_term_mode is only supported in translated mode"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createIndex","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nindex = client.indexes.create(\"DOC_ID\")\nindex.wait()\nprint(index.result().content)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst index = await client.indexes.create({ original_doc_id: \"DOC_ID\" });\nawait index.wait();\nconsole.log((await index.result()).content);"}]}},"/generate-epub":{"post":{"summary":"Build an EPUB","description":"Converts a completed DOCX into an EPUB 3.3 with the metadata you send.\nDownload it with `GET /download-epub` once completed.\n\nAdd a cover with `cover` (file upload) or `cover_url` (public HTTPS URL,\nup to 10 MB): JPG, PNG, GIF, WebP, SVG, TIFF or BMP. `subjects` are\ngenerated from the text when omitted.","requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/EpubRequest"},"encoding":{"cover":{"contentType":"image/*"}}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/EpubRequest"}}}},"responses":{"202":{"description":"EPUB build started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"},"example":{"status":"success","message":"Epub generation started","id":"6650f1c2e4b0a1d2c3f4a5bf","resource_status":"processing","resource_type":"epub","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx"}}}},"400":{"description":"Missing metadata, unsupported cover, or cover URL rejected.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing metadata","value":{"status":"error","message":"Missing required parameters: language"}},"cover_url":{"summary":"Cover URL rejected","value":{"status":"error","message":"URL is not allowed"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createEpub","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nepub = client.epubs.create(\n    \"DOC_ID\", title=\"The Long Winter\", author=\"Ana P\u00e9rez\", language=\"en\", cover=\"cover.jpg\"\n)\nepub.wait()\nepub.download(\"the_long_winter.epub\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst epub = await client.epubs.create({\n  doc_id: \"DOC_ID\",\n  title: \"The Long Winter\",\n  author: \"Ana P\u00e9rez\",\n  language: \"en\",\n  cover: \"cover.jpg\",\n});\nawait epub.wait();\nawait epub.download(\"the_long_winter.epub\");"}]}},"/generate-ocr":{"post":{"summary":"Run OCR on a scanned PDF","description":"Extracts the text of a scanned (image-only) PDF into an editable DOCX.\nDownload it with `GET /download-ocr` once completed. To run other jobs on\nthe result, upload that DOCX with `POST /process-document`.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/OcrRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/OcrRequest"}}}},"responses":{"202":{"description":"OCR started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"},"example":{"status":"success","message":"Ocr generation started","id":"6650f1c2e4b0a1d2c3f4a5c0","resource_status":"processing","resource_type":"ocr","source_id":"7a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d_scanned_edition_pdf"}}}},"400":{"description":"The document is not a PDF.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Document is not a PDF. OCR is only available for PDF documents."}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The document does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Document not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createOcr","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nocr = client.ocr.create(\"DOC_ID\")\nocr.wait()\nocr.download(\"the_long_winter.docx\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst ocr = await client.ocr.create({ doc_id: \"DOC_ID\" });\nawait ocr.wait();\nawait ocr.download(\"the_long_winter.docx\");"}]}},"/generate-ai-detection":{"post":{"summary":"Detect AI-generated text and, optionally, plagiarism","description":"Estimates which passages of a document were written or heavily assisted\nby AI. `fields=full` on `GET /resource/detection/{id}` returns the\neditorial report, the sampling summary and the analysed `chunks`;\nannotated files are available from `GET /download-detection-docx` and\n`GET /download-detection-pdf`.\n\n| `detection_scope` | Words analysed (W = document words) |\n| :-- | :-- |\n| `screening` | Samples up to 5,000 words |\n| `standard` | Samples up to 15,000 words |\n| `complete` | All W words |\n\nCredits: `ceil(60 \u00d7 analysed words / 10,000)`. The document needs at least\n50 words.\n\nWith `plagiarism_check=true` the job also screens the whole document for\nliteral or near-literal copies of web pages: about one distinctive 10\u201316\nword phrase every 1,000 words is searched and the candidate pages are\naligned against the document. Only those isolated phrases leave\nAlighieria, never the document. It does not detect paraphrases,\ntranslations or offline books. The add-on costs\n`ceil(rate \u00d7 W / 10,000)` more credits, needs the\n`generate:plagiarism_check` permission, and the response adds\n`plagiarism_check_id`. The detection stays `processing` until both parts\nfinish (`fields=status` reports each one under `parts`); it is\n`completed` when at least one part completed, and a failed part is not\ncharged. `fields=full` adds a `plagiarism` block with the report and\npaginated findings, and the annotated file marks both AI passages and\nsuspected copies.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/AiDetectionRequest"}},"multipart/form-data":{"schema":{"$ref":"#/components/schemas/AiDetectionRequest"}}}},"responses":{"202":{"description":"Detection started.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"},"example":{"status":"success","message":"Detection generation started","id":"6650f1c2e4b0a1d2c3f4a5c1","resource_status":"processing","resource_type":"detection","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx"}}}},"400":{"description":"Invalid scope or document too short.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"scope":{"summary":"Invalid scope","value":{"status":"error","message":"Invalid detection_scope. Expected 'screening', 'standard', or 'complete'."}},"short":{"summary":"Document too short","value":{"status":"error","message":"Document must contain at least 50 words for AI detection."}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"$ref":"#/components/responses/PaymentRequired"},"403":{"$ref":"#/components/responses/Forbidden"},"503":{"description":"The plagiarism add-on is temporarily unavailable.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Plagiarism check is temporarily unavailable"}}}},"404":{"description":"The document does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Document not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Generation"],"operationId":"createAiDetection","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\ndetection = client.ai_detection.create(\n    \"DOC_ID\", detection_scope=\"standard\", plagiarism_check=True\n)\ndetection.wait()\ndetection.download(\"report.pdf\", format=\"pdf\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst detection = await client.aiDetection.create({\n  doc_id: \"DOC_ID\",\n  detection_scope: \"standard\",\n  plagiarism_check: true,\n});\nawait detection.wait();\nawait detection.download(\"report.pdf\", { format: \"pdf\" });"}]}},"/conversations":{"post":{"summary":"Start a conversation","description":"Opens a conversation bound to a completed document. Then send messages\nwith `POST /conversations/{conversation_id}/turns`. Creating the\nconversation is free; each turn is charged.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversationRequest"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/CreateConversationRequest"}}}},"responses":{"201":{"description":"Conversation created.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["id","doc_id","resource_type","resource_status"],"properties":{"id":{"type":"string","description":"Conversation id."},"doc_id":{"type":"string"},"resource_type":{"type":"string","enum":["conversation"]},"resource_status":{"type":"string","enum":["active"]}}}]},"example":{"status":"success","message":"Conversation created successfully","id":"6650f1c2e4b0a1d2c3f4a5b7","doc_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","resource_type":"conversation","resource_status":"active"}}}},"400":{"description":"`doc_id` is missing or the document is still processing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing doc_id","value":{"status":"error","message":"doc_id is required"}},"processing":{"summary":"Document not ready","value":{"status":"error","message":"Document is not completed"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The document does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Document not found"}}}},"429":{"$ref":"#/components/responses/RateLimited"}},"tags":["Conversations"],"operationId":"createConversation","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nconversation = client.conversations.create(\"DOC_ID\")\nprint(conversation.id)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst conversation = await client.conversations.create({ doc_id: \"DOC_ID\" });\nconsole.log(conversation.id);"}]},"get":{"summary":"List conversations","description":"Your conversations, most recently active first, without their history.","responses":{"200":{"description":"A page of conversations.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Conversation"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}]},"example":{"status":"success","message":"Conversations retrieved successfully","data":[{"id":"6650f1c2e4b0a1d2c3f4a5b7","doc_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","title":"The Long Winter","resource_type":"conversation","resource_status":"active","created_at":"2026-09-30T10:15:00Z","updated_at":"2026-09-30T10:21:42Z","task_cost":3}],"pagination":{"total":1,"limit":50,"offset":0,"has_next":false,"has_prev":false}}}}},"400":{"description":"Invalid `limit` or `offset`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"limit must be between 1 and 100"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"}},"parameters":[{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"tags":["Conversations"],"operationId":"listConversations","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nfor conversation in client.conversations.iter():\n    print(conversation.id, conversation.title)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nfor await (const conversation of client.conversations.iter()) {\n  console.log(conversation.id, conversation.title);\n}"}]}},"/conversations/{conversation_id}":{"get":{"summary":"Get a conversation","description":"The conversation and its full message history, oldest first.","responses":{"200":{"description":"The conversation with its history.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["data"],"properties":{"data":{"allOf":[{"$ref":"#/components/schemas/Conversation"},{"type":"object","properties":{"history":{"type":"array","items":{"$ref":"#/components/schemas/ConversationMessage"}}}}]}}}]},"example":{"status":"success","message":"Conversation retrieved successfully","data":{"id":"6650f1c2e4b0a1d2c3f4a5b7","doc_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","title":"The Long Winter","resource_type":"conversation","resource_status":"active","created_at":"2026-09-30T10:15:00Z","updated_at":"2026-09-30T10:16:05Z","task_cost":3,"history":[{"role":"user","content":"Which chapters introduce the narrator's brother?","created_at":"2026-09-30T10:15:40Z"},{"role":"assistant","content":"He first appears in chapter 3, during the harvest scene, and returns in chapter 11.","created_at":"2026-09-30T10:16:05Z","task_cost":3}]}}}}},"400":{"$ref":"#/components/responses/InvalidConversationId"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/ConversationNotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"parameters":[{"$ref":"#/components/parameters/ConversationId"}],"tags":["Conversations"],"operationId":"getConversation","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nconversation = client.conversations.retrieve(\"CONVERSATION_ID\")\nfor message in conversation.history:\n    print(message.role, message.content)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst conversation = await client.conversations.retrieve(\"CONVERSATION_ID\");\nfor (const message of conversation.history) {\n  console.log(message.role, message.content);\n}"}]},"delete":{"summary":"Delete a conversation","description":"Permanently deletes the conversation and its history. The document is\nnot affected.","responses":{"200":{"description":"Conversation deleted.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["id"],"properties":{"id":{"type":"string"}}}]},"example":{"status":"success","message":"Conversation deleted successfully","id":"6650f1c2e4b0a1d2c3f4a5b7"}}}},"400":{"$ref":"#/components/responses/InvalidConversationId"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/ConversationNotFound"},"429":{"$ref":"#/components/responses/RateLimited"}},"parameters":[{"$ref":"#/components/parameters/ConversationId"}],"tags":["Conversations"],"operationId":"deleteConversation","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nclient.conversations.delete(\"CONVERSATION_ID\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nawait client.conversations.delete(\"CONVERSATION_ID\");"}]}},"/conversations/{conversation_id}/turns":{"post":{"summary":"Send a message","description":"Sends a message and waits for the assistant's answer (synchronous `200`,\nno polling). The assistant reads the whole document on every turn and\nsearches the web when a question needs outside facts; cited pages come\nback in `sources`.\n\nEach turn is charged by the text the assistant processes (the document,\nthe conversation history and its reply) and the web searches it runs:\none credit per started 0.06 USD of model cost, reported in `task_cost`.\nBefore answering, a hold large enough for a long turn is placed on your\nbalance, so keep some margin; a turn that costs more than the hold is\nstill charged in full while your balance covers it. One turn at a time\nper conversation: wait for the answer before sending the next message.\nUse a generous client timeout (120 seconds).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationTurnRequest"}},"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/ConversationTurnRequest"}}}},"responses":{"200":{"description":"The assistant's answer.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["assistant_message","task_cost","sources","id"],"properties":{"assistant_message":{"type":"string","description":"Answer in markdown."},"task_cost":{"type":"integer","description":"Credits charged for this turn."},"sources":{"type":"array","description":"Web pages cited by the answer. Empty when no search was needed.","items":{"$ref":"#/components/schemas/ConversationSource"}},"id":{"type":"string","description":"Conversation id."}}}]},"example":{"status":"success","message":"Conversation turn completed","assistant_message":"He first appears in chapter 3, during the harvest scene, and returns in chapter 11.","task_cost":3,"sources":[],"id":"6650f1c2e4b0a1d2c3f4a5b7"}}}},"400":{"description":"Missing message, invalid id, or the document has no text.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing message","value":{"status":"error","message":"message is required"}},"no_text":{"summary":"Document without text","value":{"status":"error","message":"Document content not available for this chat"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"402":{"description":"Not enough credits for the hold.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Insufficient credits"}}}},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/ConversationNotFound"},"409":{"description":"The assistant is still answering the previous message.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"The assistant is already answering in this chat"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"description":"The answer could not be generated. The hold is released.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Error generating conversation turn"}}}}},"parameters":[{"$ref":"#/components/parameters/ConversationId"}],"tags":["Conversations"],"operationId":"sendConversationMessage","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nturn = client.conversations.send(\"CONVERSATION_ID\", \"Where does the brother first appear?\")\nprint(turn.assistant_message, turn.task_cost)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst turn = await client.conversations.send(\n  \"CONVERSATION_ID\",\n  \"Where does the brother first appear?\",\n);\nconsole.log(turn.assistant_message, turn.task_cost);"}]}},"/resource/{resource_type}/{resource_id}":{"get":{"summary":"Get a resource","description":"The single endpoint to poll jobs and read their results.\n\n- **`fields=status`** returns a small snapshot (`resource_status`,\n  `progress`, per-family `suites` for correction runs). Use it to poll.\n- **`fields=full`** (default) returns the result. The id comes back as\n  `_id` and the source document as `source_id`. `content` holds the\n  generated text for synopses, dossiers, translations and marketing\n  content.\n\nSome types add paginated detail to `fields=full`:\n\n| Type | Extra fields | Filters |\n| :-- | :-- | :-- |\n| `correction_run` | `findings`, `findings_pagination` | `family`, `basis`, `page`, `severity` |\n| `detection` | `chunks`, `chunks_pagination`; with the plagiarism add-on, `plagiarism` (report, `findings`, `findings_pagination`) | `category`, `severity` (plagiarism findings) |\n\n`offset` and `limit` page through findings and chunks (default 50, max\n100). AI detection returns every chunk unless you send `offset` or\n`limit`; plagiarism findings page with `findings_offset` and\n`findings_limit`. With the plagiarism add-on, `fields=status` adds\n`parts` (`ai` and `plagiarism`, each with `status` and `progress`).","responses":{"200":{"description":"The resource. `data` depends on `fields` and the resource type.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["data"],"properties":{"data":{"anyOf":[{"$ref":"#/components/schemas/ResourceStatusSnapshot"},{"$ref":"#/components/schemas/ResourceDetail"}]}}}]},"examples":{"poll_processing":{"summary":"fields=status, still running","value":{"status":"success","message":"Resource retrieved successfully","data":{"id":"6650f1c2e4b0a1d2c3f4a5b6","resource_type":"correction_run","resource_status":"processing","created_at":"2026-09-30T10:15:00Z","progress":70,"source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","suites":{"editorial":{"status":"completed","progress":100,"finding_count":212},"raccord":{"status":"processing","progress":40}}}}},"synopsis_full":{"summary":"fields=full, synopsis","value":{"status":"success","message":"Resource retrieved successfully","data":{"_id":"6650f1c2e4b0a1d2c3f4a5b8","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","status":"completed","created_at":"2026-09-30T10:15:00Z","title":"The Long Winter","author":"Ana P\u00e9rez","tone":"neutral","instructions":"","progress":100,"content":"In a mountain village cut off by the first snow, two brothers..."}}},"correction_findings":{"summary":"fields=full, correction run findings","value":{"status":"success","message":"Resource retrieved successfully","data":{"_id":"6650f1c2e4b0a1d2c3f4a5b6","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","status":"completed","title":"The Long Winter","suites_requested":["editorial","raccord"],"findings":[{"id":"TYP-001","family":"editorial","page":12,"page_end":12,"basis":"guide","original":"Its a cold morning.","corrected":"It's a cold morning.","explanation":"Missing apostrophe in the contraction.","error_span":"Its"},{"id":"RAC-001","family":"raccord","page":48,"page_end":131,"severity":"moderate","category":"character","passage_a":"Marta's eyes were green as moss.","passage_b":"She looked at him with her dark brown eyes.","explanation":"Marta's eye colour changes between chapters.","suggestion":"Keep one eye colour throughout."}],"findings_pagination":{"total":213,"limit":50,"offset":0,"has_next":true,"has_prev":false}}}}}}}},"400":{"description":"Unknown type, malformed id, or invalid filter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"type":{"summary":"Unknown resource type","value":{"status":"error","message":"Invalid resource type. Use /api/v1/resource-types to see available types."}},"id":{"summary":"Malformed id","value":{"status":"error","message":"Invalid resource ID format"}},"limit":{"summary":"Invalid pagination","value":{"status":"error","message":"limit must be between 1 and 100"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"$ref":"#/components/parameters/ResourceTypePath"},{"$ref":"#/components/parameters/ResourceIdPath"},{"name":"fields","in":"query","required":false,"description":"`status` to poll, `full` for the result.","schema":{"type":"string","enum":["status","full"],"default":"full"}},{"name":"offset","in":"query","required":false,"description":"Findings or chunks to skip.","schema":{"type":"integer","minimum":0,"default":0}},{"name":"limit","in":"query","required":false,"description":"Findings or chunks per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"family","in":"query","required":false,"description":"Correction runs only. Return findings of one family.","schema":{"type":"string","enum":["editorial","raccord","fact_checking","layout"]}},{"name":"basis","in":"query","required":false,"description":"Correction runs only. `guide` returns findings that enforce your style guide.","schema":{"type":"string","enum":["guide","general"]}},{"name":"page","in":"query","required":false,"description":"Correction runs only. Return findings on this page.","schema":{"type":"integer","minimum":1}},{"name":"severity","in":"query","required":false,"description":"Correction runs, and detections with the plagiarism add-on (`low`, `medium` or `high` for plagiarism findings).","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Detections with the plagiarism add-on only. Category of the plagiarism findings.","schema":{"type":"string","enum":["attributed_quote","epigraph","common_phrase","public_domain","suspected_copy"]}},{"name":"findings_offset","in":"query","required":false,"description":"Detections with the plagiarism add-on only. Plagiarism findings to skip.","schema":{"type":"integer","minimum":0,"default":0}},{"name":"findings_limit","in":"query","required":false,"description":"Detections with the plagiarism add-on only. Plagiarism findings per page.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"tags":["Resources"],"operationId":"getResource","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\njob = client.jobs.retrieve(\"correction_run\", \"JOB_ID\")  # status poll\nprint(job.status, job.progress)\n\nresult = job.result(family=\"editorial\", limit=50)  # full result\nprint(result.findings)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst job = await client.jobs.retrieve(\"correction_run\", \"JOB_ID\"); // status poll\nconsole.log(job.status, job.progress);\n\nconst result = await job.result({ family: \"editorial\", limit: 50 }); // full result\nconsole.log(result.findings);"}]},"delete":{"summary":"Delete a resource","description":"Deletes a document or job result and its files. Deleting a document does\nnot delete the jobs generated from it. A correction run cannot be deleted\nwhile it is running.","responses":{"200":{"description":"Resource deleted.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["resource_type","resource_id"],"properties":{"resource_type":{"$ref":"#/components/schemas/ResourceType"},"resource_id":{"type":"string"}}}]},"example":{"status":"success","message":"Resource deleted successfully","resource_type":"synopsis","resource_id":"6650f1c2e4b0a1d2c3f4a5b8"}}}},"400":{"description":"Unknown resource type.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Invalid resource type. Use /api/v1/resource-types to see available types."}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"description":"The correction run is still running.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Active correction runs cannot be deleted"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"$ref":"#/components/parameters/ResourceTypePath"},{"$ref":"#/components/parameters/ResourceIdPath"}],"tags":["Resources"],"operationId":"deleteResource","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nclient.jobs.delete(\"synopsis\", \"JOB_ID\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nawait client.jobs.delete(\"synopsis\", \"JOB_ID\");"}]}},"/generations":{"get":{"summary":"List generations","description":"Every job you launched (corrections, translations, dossiers, EPUBs\u2026),\nnewest first. Filter by `type` or `source_id` to find the jobs of one\ndocument; for example, check here before retrying a launch that timed out.\nIndex sources are only listed when you ask for `type=index_source`.","responses":{"200":{"description":"A page of jobs.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["data","pagination"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/GenerationSummary"}},"pagination":{"$ref":"#/components/schemas/Pagination"}}}]},"example":{"status":"success","message":"Generations retrieved successfully","data":[{"id":"6650f1c2e4b0a1d2c3f4a5b6","resource_type":"correction_run","resource_status":"completed","status":"completed","source_id":"3f2a9c1e-5b7d-4e8a-9c0f-1a2b3c4d5e6f_the_long_winter_docx","title":"The Long Winter","author":"Ana P\u00e9rez","description":"","created_at":"2026-09-30T10:15:00Z","updated_at":"2026-09-30T10:24:00Z"}],"pagination":{"total":1,"limit":50,"offset":0,"has_next":false,"has_prev":false}}}}},"400":{"description":"Invalid `type`, `status`, `limit` or `offset`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"type":{"summary":"Unknown type","value":{"status":"error","message":"Invalid generation type"}},"status":{"summary":"Unknown status","value":{"status":"error","message":"Invalid status. Use processing, completed, error, partial, or failed."}},"limit":{"summary":"Limit out of range","value":{"status":"error","message":"limit must be between 1 and 100"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"type","in":"query","required":false,"description":"Return only jobs of this type.","schema":{"$ref":"#/components/schemas/GenerationType"}},{"name":"source_id","in":"query","required":false,"description":"Return only jobs generated from this document.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ResourceStatus"}},{"name":"sort","in":"query","required":false,"description":"Jobs without the field (`updated_at` is `null` on jobs never updated) sort as oldest.","schema":{"type":"string","enum":["created_at","updated_at"],"default":"created_at"}},{"$ref":"#/components/parameters/Order"},{"$ref":"#/components/parameters/Limit"},{"$ref":"#/components/parameters/Offset"}],"tags":["Resources"],"operationId":"listGenerations","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nfor job in client.jobs.iter(type=\"correction_run\", status=\"completed\"):\n    print(job.id, job.title)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nfor await (const job of client.jobs.iter({ type: \"correction_run\", status: \"completed\" })) {\n  console.log(job.id, job.title);\n}"}]}},"/resource-types":{"get":{"summary":"List resource types","description":"Every `resource_type` you can poll, read or delete, with a short\ndescription. `requires_source` marks types produced from a document.","responses":{"200":{"description":"Available resource types.","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"type":"object","required":["resource_type","name","description"],"properties":{"resource_type":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"requires_source":{"type":"boolean","description":"Present (and `true`) when the type is generated from a document."}}}}}}]},"example":{"status":"success","message":"Resource types retrieved successfully","data":[{"resource_type":"document","name":"Document","description":"Processed text documents (PDF, DOCX, EPUB, XML, Markdown, or IDML)"},{"resource_type":"synopsis","name":"Synopsis","description":"Book synopsis.","requires_source":true}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"tags":["Resources"],"operationId":"listResourceTypes","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nfor resource_type in client.jobs.resource_types():\n    print(resource_type.resource_type, resource_type.name)"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nfor (const resourceType of await client.jobs.resourceTypes()) {\n  console.log(resourceType.resource_type, resourceType.name);\n}"}]}},"/download-corrections":{"get":{"summary":"Download corrections","description":"Downloads the corrected file of a completed correction run, in the\nformat of the source: DOCX with tracked changes and comments, annotated\nPDF, or IDML. `correction_run_id` is accepted as an alias of\n`correction_id`.","responses":{"200":{"description":"The file, sent as an attachment.","headers":{"Content-Disposition":{"description":"`attachment; filename=...`","schema":{"type":"string"}}},"content":{"application/vnd.openxmlformats-officedocument.wordprocessingml.document":{"schema":{"type":"string","format":"binary"}},"application/pdf":{"schema":{"type":"string","format":"binary"}},"application/vnd.adobe.indesign-idml-package":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"`correction_id` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing id","value":{"status":"error","message":"Missing correction_id parameter"}},"malformed":{"summary":"Malformed id","value":{"status":"error","message":"Invalid correction_id format"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The job does not exist, or it has no file of this kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Correction run not found"}}}},"409":{"description":"The run has not produced its file yet. Poll the run and retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Combined artifact is not ready"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"correction_id","in":"query","required":true,"description":"Job id returned by `POST /generate-corrections`.","schema":{"type":"string"}}],"tags":["Download"],"operationId":"downloadCorrections","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nrun = client.corrections.retrieve(\"CORRECTION_RUN_ID\")\nrun.download(\"corrected/\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst run = await client.corrections.retrieve(\"CORRECTION_RUN_ID\");\nawait run.download(\"corrected/\");"}]}},"/download-translation-idml":{"get":{"summary":"Download translated IDML","description":"Downloads the translated InDesign package of a completed translation.\nOnly available when the source document was an IDML file.","responses":{"200":{"description":"The file, sent as an attachment.","headers":{"Content-Disposition":{"description":"`attachment; filename=...`","schema":{"type":"string"}}},"content":{"application/vnd.adobe.indesign-idml-package":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"`translation_id` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing id","value":{"status":"error","message":"Missing translation_id parameter"}},"malformed":{"summary":"Malformed id","value":{"status":"error","message":"Invalid translation_id format"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The job does not exist, or it has no file of this kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Unknown job","value":{"status":"error","message":"Translation not found"}},"no_file":{"summary":"Job finished without this file","value":{"status":"error","message":"Translated IDML file not available"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"translation_id","in":"query","required":true,"description":"Job id returned by `POST /generate-translation`.","schema":{"type":"string"}}],"tags":["Download"],"operationId":"downloadTranslationIdml","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\ntranslation = client.translations.retrieve(\"TRANSLATION_ID\")\ntranslation.download(\"translated.idml\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst translation = await client.translations.retrieve(\"TRANSLATION_ID\");\nawait translation.download(\"translated.idml\");"}]}},"/download-translation-review-docx":{"get":{"summary":"Download translation review (DOCX)","description":"Downloads the annotated DOCX of a completed translation review, when one was produced.","responses":{"200":{"description":"The file, sent as an attachment.","headers":{"Content-Disposition":{"description":"`attachment; filename=...`","schema":{"type":"string"}}},"content":{"application/vnd.openxmlformats-officedocument.wordprocessingml.document":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"`translation_review_id` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing id","value":{"status":"error","message":"Missing translation_review_id parameter"}},"malformed":{"summary":"Malformed id","value":{"status":"error","message":"Invalid translation_review_id format"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The job does not exist, or it has no file of this kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Unknown job","value":{"status":"error","message":"Translation review not found"}},"no_file":{"summary":"Job finished without this file","value":{"status":"error","message":"DOCX file not available for this review"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"translation_review_id","in":"query","required":true,"description":"Job id returned by `POST /generate-translation-review`.","schema":{"type":"string"}}],"tags":["Download"],"operationId":"downloadTranslationReviewDocx","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nreview = client.translation_reviews.retrieve(\"TRANSLATION_REVIEW_ID\")\nreview.download(\"review.docx\", format=\"docx\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst review = await client.translationReviews.retrieve(\"TRANSLATION_REVIEW_ID\");\nawait review.download(\"review.docx\", { format: \"docx\" });"}]}},"/download-translation-review-pdf":{"get":{"summary":"Download translation review (PDF)","description":"Downloads the PDF report of a completed translation review, when one was produced.","responses":{"200":{"description":"The file, sent as an attachment.","headers":{"Content-Disposition":{"description":"`attachment; filename=...`","schema":{"type":"string"}}},"content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"`translation_review_id` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing id","value":{"status":"error","message":"Missing translation_review_id parameter"}},"malformed":{"summary":"Malformed id","value":{"status":"error","message":"Invalid translation_review_id format"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The job does not exist, or it has no file of this kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Unknown job","value":{"status":"error","message":"Translation review not found"}},"no_file":{"summary":"Job finished without this file","value":{"status":"error","message":"PDF file not available for this review"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"translation_review_id","in":"query","required":true,"description":"Job id returned by `POST /generate-translation-review`.","schema":{"type":"string"}}],"tags":["Download"],"operationId":"downloadTranslationReviewPdf","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nreview = client.translation_reviews.retrieve(\"TRANSLATION_REVIEW_ID\")\nreview.download(\"review.pdf\", format=\"pdf\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst review = await client.translationReviews.retrieve(\"TRANSLATION_REVIEW_ID\");\nawait review.download(\"review.pdf\", { format: \"pdf\" });"}]}},"/download-epub":{"get":{"summary":"Download EPUB","description":"Downloads the EPUB built by a completed EPUB job.","responses":{"200":{"description":"The file, sent as an attachment.","headers":{"Content-Disposition":{"description":"`attachment; filename=...`","schema":{"type":"string"}}},"content":{"application/epub+zip":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"`epub_id` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing id","value":{"status":"error","message":"Missing epub_id parameter"}},"malformed":{"summary":"Malformed id","value":{"status":"error","message":"Invalid epub_id format"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The job does not exist, or it has no file of this kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Unknown job","value":{"status":"error","message":"EPUB not found"}},"no_file":{"summary":"Job finished without this file","value":{"status":"error","message":"EPUB file not available"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"epub_id","in":"query","required":true,"description":"Job id returned by `POST /generate-epub`.","schema":{"type":"string"}}],"tags":["Download"],"operationId":"downloadEpub","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nepub = client.epubs.retrieve(\"EPUB_ID\")\nepub.download(\"the_long_winter.epub\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst epub = await client.epubs.retrieve(\"EPUB_ID\");\nawait epub.download(\"the_long_winter.epub\");"}]}},"/download-ocr":{"get":{"summary":"Download OCR result","description":"Downloads the editable DOCX produced by a completed OCR job.","responses":{"200":{"description":"The file, sent as an attachment.","headers":{"Content-Disposition":{"description":"`attachment; filename=...`","schema":{"type":"string"}}},"content":{"application/vnd.openxmlformats-officedocument.wordprocessingml.document":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"`ocr_id` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing id","value":{"status":"error","message":"Missing ocr_id parameter"}},"malformed":{"summary":"Malformed id","value":{"status":"error","message":"Invalid ocr_id format"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The job does not exist, or it has no file of this kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Unknown job","value":{"status":"error","message":"OCR record not found"}},"no_file":{"summary":"Job finished without this file","value":{"status":"error","message":"OCR file not available"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"ocr_id","in":"query","required":true,"description":"Job id returned by `POST /generate-ocr`.","schema":{"type":"string"}}],"tags":["Download"],"operationId":"downloadOcr","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\nocr = client.ocr.retrieve(\"OCR_ID\")\nocr.download(\"the_long_winter.docx\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst ocr = await client.ocr.retrieve(\"OCR_ID\");\nawait ocr.download(\"the_long_winter.docx\");"}]}},"/download-detection-docx":{"get":{"summary":"Download AI detection (DOCX)","description":"Downloads the document annotated with the AI detection results.","responses":{"200":{"description":"The file, sent as an attachment.","headers":{"Content-Disposition":{"description":"`attachment; filename=...`","schema":{"type":"string"}}},"content":{"application/vnd.openxmlformats-officedocument.wordprocessingml.document":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"`detection_id` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing id","value":{"status":"error","message":"Missing detection_id parameter"}},"malformed":{"summary":"Malformed id","value":{"status":"error","message":"Invalid detection_id format"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The job does not exist, or it has no file of this kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Unknown job","value":{"status":"error","message":"AI detection not found"}},"no_file":{"summary":"Job finished without this file","value":{"status":"error","message":"DOCX file not available for this AI detection"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"detection_id","in":"query","required":true,"description":"Job id returned by `POST /generate-ai-detection`.","schema":{"type":"string"}}],"tags":["Download"],"operationId":"downloadAiDetectionDocx","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\ndetection = client.ai_detection.retrieve(\"DETECTION_ID\")\ndetection.download(\"report.docx\", format=\"docx\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst detection = await client.aiDetection.retrieve(\"DETECTION_ID\");\nawait detection.download(\"report.docx\", { format: \"docx\" });"}]}},"/download-detection-pdf":{"get":{"summary":"Download AI detection (PDF)","description":"Downloads the PDF report of a completed AI detection.","responses":{"200":{"description":"The file, sent as an attachment.","headers":{"Content-Disposition":{"description":"`attachment; filename=...`","schema":{"type":"string"}}},"content":{"application/pdf":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"`detection_id` is missing or malformed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Missing id","value":{"status":"error","message":"Missing detection_id parameter"}},"malformed":{"summary":"Malformed id","value":{"status":"error","message":"Invalid detection_id format"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"The job does not exist, or it has no file of this kind.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"missing":{"summary":"Unknown job","value":{"status":"error","message":"AI detection not found"}},"no_file":{"summary":"Job finished without this file","value":{"status":"error","message":"PDF file not available for this AI detection"}}}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}},"parameters":[{"name":"detection_id","in":"query","required":true,"description":"Job id returned by `POST /generate-ai-detection`.","schema":{"type":"string"}}],"tags":["Download"],"operationId":"downloadAiDetectionPdf","x-codeSamples":[{"lang":"Python","label":"Python SDK","source":"from alighieria import Alighieria\n\nclient = Alighieria()\n\ndetection = client.ai_detection.retrieve(\"DETECTION_ID\")\ndetection.download(\"report.pdf\", format=\"pdf\")"},{"lang":"TypeScript","label":"TypeScript SDK","source":"import Alighieria from \"alighieria\";\n\nconst client = new Alighieria();\n\nconst detection = await client.aiDetection.retrieve(\"DETECTION_ID\");\nawait detection.download(\"report.pdf\", { format: \"pdf\" });"}]}}},"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Your secret API key. Create and rotate keys in the\n[Alighieria dashboard](https://app.alighieria.com/account).\nSend it on every request; never expose it in browser or mobile code.\n"}},"headers":{"X-RateLimit-Limit":{"description":"Requests allowed in the current window.","schema":{"type":"integer","example":10}},"X-RateLimit-Remaining":{"description":"Requests left in the current window.","schema":{"type":"integer","example":0}},"X-RateLimit-Reset":{"description":"Unix timestamp (seconds) when the current window resets.","schema":{"type":"integer","example":1790850000}},"Retry-After":{"description":"Seconds to wait before retrying.","schema":{"type":"integer","example":42}}},"parameters":{"ResourceTypePath":{"name":"resource_type","in":"path","required":true,"description":"Resource type. Must match the type returned when the resource was created.","schema":{"$ref":"#/components/schemas/ResourceType"}},"ResourceIdPath":{"name":"resource_id","in":"path","required":true,"description":"Resource id (`id` field of the creation response).","schema":{"type":"string"}},"ConversationId":{"name":"conversation_id","in":"path","required":true,"description":"Conversation id returned by `POST /conversations`.","schema":{"type":"string"}},"Limit":{"name":"limit","in":"query","required":false,"description":"Page size.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},"Offset":{"name":"offset","in":"query","required":false,"description":"Number of items to skip.","schema":{"type":"integer","minimum":0,"default":0}},"Order":{"name":"order","in":"query","required":false,"description":"Sort direction.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},"IdempotencyKey":{"name":"X-Idempotency-Key","in":"header","required":false,"description":"Unique key (a UUID is ideal) that makes retries safe. Within 24 hours,\na retry with the same key and the same request replays the original\nresponse instead of running the operation twice. Reusing a key with a\ndifferent request returns `409`.\n","schema":{"type":"string","maxLength":255}}},"schemas":{"AiDetectionRequest":{"type":"object","required":["doc_id","detection_scope"],"properties":{"doc_id":{"type":"string","description":"A completed document."},"detection_scope":{"type":"string","enum":["screening","standard","complete"]},"plagiarism_check":{"type":"boolean","default":false,"description":"Also screen the whole document for plagiarism on the web."},"excluded_domains":{"type":"string","description":"With `plagiarism_check`, domains whose pages never count as a source (for example the author's own website), as a JSON array or a comma-separated list. Subdomains are included. At most 20."},"locale":{"$ref":"#/components/schemas/Locale"}}},"ContentRequest":{"type":"object","required":["content_type","doc_ids"],"properties":{"content_type":{"$ref":"#/components/schemas/ContentType"},"doc_ids":{"type":"string","description":"JSON-encoded array of completed document ids, sent as a single\nstring field. See the table for how many each type accepts.\n"},"instructions":{"type":"string","description":"Extra guidance (angle, audience, call to action)."},"language":{"allOf":[{"$ref":"#/components/schemas/OutputLanguage"}],"description":"Output language (used by `press_web`)."},"brand_voice_id":{"type":"string","description":"Brand voice uploaded with `doc_type=brand_voice`."},"plan_id":{"type":"string","description":"Your id to group pieces of one campaign."},"plan_name":{"type":"string","description":"Label for that campaign."},"locale":{"$ref":"#/components/schemas/Locale"}}},"ContentType":{"type":"string","enum":["micropost_ig","author_profile_ig","curiosity_tiktok","thread_x","story_web","story_ig","story_x","write_up_ig","quotes_ig","press_web","launch_x","catalog_ig","mention_ig","mention_x"]},"Conversation":{"type":"object","required":["id","doc_id","resource_type","resource_status"],"properties":{"id":{"type":"string"},"doc_id":{"type":"string"},"title":{"type":"string"},"resource_type":{"type":"string","enum":["conversation"]},"resource_status":{"type":"string","example":"active"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"task_cost":{"type":"integer","description":"Total credits charged in this conversation."}}},"ConversationMessage":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["user","assistant"]},"content":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"task_cost":{"type":"integer","description":"Credits charged for this turn (assistant messages)."}}},"ConversationSource":{"type":"object","properties":{"title":{"type":"string"},"uri":{"type":"string","format":"uri"}}},"ConversationTurnRequest":{"type":"object","required":["message"],"properties":{"message":{"type":"string","description":"Your question or instruction about the document."},"locale":{"allOf":[{"$ref":"#/components/schemas/Locale"}],"description":"Defaults to the conversation locale."}}},"CorrectionFamily":{"type":"string","enum":["editorial","raccord","fact_checking","layout"]},"CorrectionFinding":{"type":"object","description":"One finding of a correction run. The shared envelope is always present;\nthe remaining fields depend on `family`:\n\n- `editorial`: `original`, `corrected`, `explanation`, `error_span`.\n- `fact_checking`: the editorial fields plus `sources`.\n- `raccord`: `category`, `passage_a`, `passage_b`, `explanation`, `suggestion`.\n- `layout`: `kind`, `quoted_text`, `location`, `evidence`,\n  `adjacent_line_text`, `continuity_text`.\n","required":["id","family"],"properties":{"id":{"type":"string"},"family":{"type":"string","enum":["editorial","raccord","fact_checking","layout"]},"page":{"type":"integer","nullable":true},"page_end":{"type":"integer","nullable":true},"severity":{"type":"string","description":"`critical`, `moderate` or `minor` when the family reports it."},"basis":{"type":"string","enum":["guide","general"],"description":"`guide` when the finding enforces your style guide."},"original":{"type":"string"},"corrected":{"type":"string"},"explanation":{"type":"string"},"error_span":{"type":"string"},"sources":{"type":"array","items":{"type":"object","additionalProperties":true}},"category":{"type":"string"},"passage_a":{"type":"string"},"passage_b":{"type":"string"},"suggestion":{"type":"string"},"kind":{"type":"string"},"quoted_text":{"type":"string"},"location":{"type":"string"},"evidence":{"type":"string"},"adjacent_line_text":{"type":"string"},"continuity_text":{"type":"string"}}},"CorrectionRunRequest":{"type":"object","required":["doc_id","correction_types"],"properties":{"doc_id":{"type":"string","description":"A completed document."},"correction_types":{"type":"array","minItems":1,"uniqueItems":true,"description":"Families to run. In form bodies, repeat the field or send a\ncomma-separated list (`editorial,raccord`).\n","items":{"$ref":"#/components/schemas/CorrectionFamily"}},"guide_id":{"type":"string","description":"Style guide (`doc_type=guide` upload or markdown guide) applied by `editorial`."},"locale":{"$ref":"#/components/schemas/Locale"}}},"CorrectionSuites":{"type":"object","description":"Progress per correction family, keyed by family. Only for `correction_run`.","additionalProperties":{"type":"object","properties":{"status":{"$ref":"#/components/schemas/ResourceStatus"},"progress":{"type":"integer","minimum":0,"maximum":100},"finding_count":{"type":"integer"}}},"example":{"editorial":{"status":"completed","progress":100,"finding_count":212},"raccord":{"status":"processing","progress":40}}},"CreateConversationRequest":{"type":"object","required":["doc_id"],"properties":{"doc_id":{"type":"string","description":"A completed document."},"locale":{"$ref":"#/components/schemas/Locale"}}},"DetectionChunk":{"type":"object","description":"One analysed passage of an AI detection.","properties":{"_id":{"type":"string"},"index":{"type":"integer"},"start_index":{"type":"integer"},"end_index":{"type":"integer"},"word_count":{"type":"integer"},"chapter":{"type":"string"},"position_pct":{"type":"number"},"kind":{"type":"string"},"sampled":{"type":"boolean"},"content":{"type":"string"},"result":{"type":"object","additionalProperties":true,"description":"Classifier output for the passage."},"status":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"DocumentSummary":{"type":"object","properties":{"id":{"type":"string","description":"Document id (`doc_id`)."},"title":{"type":"string"},"author":{"type":"string"},"description":{"type":"string"},"status":{"$ref":"#/components/schemas/ResourceStatus"},"created_at":{"type":"string","format":"date-time"}}},"DossierRequest":{"type":"object","required":["doc_id","kind"],"properties":{"doc_id":{"type":"string","description":"A completed document."},"kind":{"type":"string","enum":["analysis","reading_report"]},"language":{"allOf":[{"$ref":"#/components/schemas/OutputLanguage"}],"description":"Language of the dossier."},"analysis_template_id":{"type":"string","description":"Analysis template to follow. Only for `kind=analysis`."},"locale":{"$ref":"#/components/schemas/Locale"}}},"EpubRequest":{"type":"object","required":["doc_id","title","author","language"],"properties":{"doc_id":{"type":"string","description":"A completed DOCX document."},"title":{"type":"string"},"author":{"type":"string","description":"Main author."},"language":{"type":"string","description":"BCP 47 language code of the book."},"subtitle":{"type":"string"},"authors":{"type":"string","description":"Additional authors, comma-separated."},"contributors":{"type":"string","description":"JSON array of contributors with MARC relator roles\n(`trl` translator, `edt` editor, `ill` illustrator\u2026).\n"},"isbn":{"type":"string"},"publisher":{"type":"string"},"date":{"type":"string","format":"date","description":"Publication date."},"description":{"type":"string","description":"Blurb shown by ebook stores and readers."},"subjects":{"type":"string","description":"Comma-separated BISAC or Thema codes, or keywords."},"rights":{"type":"string"},"collection":{"type":"string","description":"Series name."},"collection_position":{"type":"integer","description":"Position in the series."},"cover":{"type":"string","format":"binary","description":"Cover image. Send `cover` or `cover_url`."},"cover_url":{"type":"string","format":"uri","description":"Public HTTPS URL of the cover image."},"locale":{"$ref":"#/components/schemas/Locale"}}},"Error":{"type":"object","description":"Every error response uses this envelope.","required":["status","message"],"properties":{"status":{"type":"string","enum":["error"]},"message":{"type":"string","description":"Human-readable explanation. Safe to log; do not parse it."},"code":{"$ref":"#/components/schemas/ErrorCode"}},"example":{"status":"error","message":"Missing required parameters: doc_id"}},"ErrorCode":{"type":"string","description":"Machine-readable reason, present only on errors you can act on. Branch\non it instead of `message`.\n\n| `code` | Status | Meaning |\n| :-- | :-- | :-- |\n| `no_subscription` | `403` | The account has no subscription. |\n| `inactive_subscription` | `403` | The subscription expired, is unpaid or was canceled. |\n| `insufficient_credits` | `402` | The balance does not cover the request. |\n| `turn_in_progress` | `409` | The assistant is still answering in this conversation. |\n","enum":["no_subscription","inactive_subscription","insufficient_credits","turn_in_progress"]},"GenerationSummary":{"type":"object","properties":{"id":{"type":"string"},"resource_type":{"$ref":"#/components/schemas/GenerationType"},"resource_status":{"$ref":"#/components/schemas/ResourceStatus"},"status":{"$ref":"#/components/schemas/ResourceStatus"},"source_id":{"type":"string"},"title":{"type":"string","description":"Title of the source document."},"author":{"type":"string"},"description":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time","nullable":true,"description":"Last status change; `null` if the job was never updated."}}},"GenerationType":{"type":"string","description":"Resource types produced by generation jobs.","enum":["synopsis","analysis","report","translation_review","correction_run","translation","index","index_source","ocr","epub","content","detection"]},"IndexRequest":{"type":"object","required":["original_doc_id"],"properties":{"original_doc_id":{"type":"string","description":"The book to index (the original edition in translated mode)."},"translated_doc_id":{"type":"string","description":"Translated edition. Requires `index_source_id`."},"index_source_id":{"type":"string","description":"Existing index of the original, uploaded with `doc_type=index_source`."},"index_term_mode":{"type":"string","enum":["translate","preserve"],"default":"translate","description":"Translated mode only."},"locale":{"$ref":"#/components/schemas/Locale"}}},"JobAccepted":{"description":"The job was queued. Poll\n`GET /resource/{resource_type}/{id}?fields=status` until\n`resource_status` is no longer `processing`.\n","allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","required":["id","resource_type","resource_status"],"properties":{"id":{"type":"string","description":"Id of the new resource."},"resource_type":{"$ref":"#/components/schemas/GenerationType"},"resource_status":{"type":"string","enum":["processing"]},"source_id":{"type":"string","description":"Source document id, when the job reads one."}}}]},"Locale":{"type":"string","enum":["es","en","fr"],"default":"es","description":"Language of the response messages, labels and notification emails.\nIt does **not** change the language of the generated content (see\n`language`). Unknown values fall back to `es`.\n"},"MarkdownCollection":{"type":"string","enum":["docs","guides","analysis_templates"],"description":"`docs` is a manuscript, `guides` a style guide, `analysis_templates` an analysis template."},"MarkdownDocument":{"allOf":[{"$ref":"#/components/schemas/Success"},{"type":"object","properties":{"doc_id":{"type":"string","description":"Use it as `doc_id`, `guide_id` or `analysis_template_id`."},"collection":{"$ref":"#/components/schemas/MarkdownCollection"},"title":{"type":"string"},"author":{"type":"string"},"description":{"type":"string"},"file_type":{"type":"string","enum":["md"]},"word_count":{"type":"integer"},"status_resource":{"type":"string","enum":["completed"],"description":"Always `completed`; markdown needs no processing."}}}]},"MarkdownDocumentWrite":{"type":"object","required":["collection","title","content"],"properties":{"collection":{"$ref":"#/components/schemas/MarkdownCollection"},"title":{"type":"string"},"content":{"type":"string","maxLength":2000000,"description":"Markdown source."},"author":{"type":"string"},"description":{"type":"string"},"doc_id":{"type":"string","description":"Id of a markdown document to update. Omit to create one."}}},"OcrRequest":{"type":"object","required":["doc_id"],"properties":{"doc_id":{"type":"string","description":"An uploaded PDF."},"locale":{"$ref":"#/components/schemas/Locale"}}},"OutputLanguage":{"type":"string","enum":["spanish","catalan","galician","basque","english","french","italian","portuguese","german","hebrew"],"description":"Language of the generated content. Case-insensitive; any other value returns `400`."},"Pagination":{"type":"object","required":["total","limit","offset","has_next","has_prev"],"properties":{"total":{"type":"integer","description":"Items matching the filters."},"limit":{"type":"integer"},"offset":{"type":"integer"},"has_next":{"type":"boolean"},"has_prev":{"type":"boolean"}},"example":{"total":128,"limit":50,"offset":0,"has_next":true,"has_prev":false}},"PlagiarismFinding":{"type":"object","description":"A passage that matches a public web page.","properties":{"finding_id":{"type":"string"},"index":{"type":"integer"},"category":{"type":"string","enum":["attributed_quote","epigraph","common_phrase","public_domain","suspected_copy"],"description":"Only `suspected_copy` points to possible plagiarism; the rest are legitimate uses."},"severity":{"type":"string","enum":["low","medium","high"]},"justification":{"type":"string"},"classified":{"type":"boolean"},"start":{"type":"integer","description":"Start offset in the document text."},"end":{"type":"integer"},"words":{"type":"integer"},"position_pct":{"type":"number"},"chapter":{"type":"string"},"quoted":{"type":"boolean","description":"The passage is inside quotation marks."},"at_section_start":{"type":"boolean"},"text_excerpt":{"type":"string"},"source_url":{"type":"string","format":"uri"},"source_title":{"type":"string"},"source_excerpt":{"type":"string"},"similarity":{"type":"number","description":"Text similarity with the source."},"additional_sources":{"type":"array","items":{"type":"object","additionalProperties":true}},"source_count":{"type":"integer"}}},"ResourceDetail":{"type":"object","description":"Full resource (`fields=full`). Common fields are listed; each type\nadds its own (for example `content`, `language`, `suites`,\n`aggregate`, `report`).\n","additionalProperties":true,"properties":{"_id":{"type":"string","description":"Resource id."},"source_id":{"type":"string","description":"Source document id."},"status":{"$ref":"#/components/schemas/ResourceStatus"},"progress":{"type":"integer"},"created_at":{"type":"string","format":"date-time"},"title":{"type":"string","description":"Title of the source document."},"author":{"type":"string"},"content":{"description":"Generated output (text or structured, depending on the type)."},"findings":{"type":"array","description":"`correction_run` only (plagiarism findings are in `plagiarism.findings` of a detection).","items":{"anyOf":[{"$ref":"#/components/schemas/CorrectionFinding"},{"$ref":"#/components/schemas/PlagiarismFinding"}]}},"findings_pagination":{"$ref":"#/components/schemas/Pagination"},"chunks":{"type":"array","description":"`detection` only.","items":{"$ref":"#/components/schemas/DetectionChunk"}},"chunks_pagination":{"$ref":"#/components/schemas/Pagination"}}},"ResourceStatus":{"type":"string","description":"Lifecycle of an asynchronous resource.\n\n| Value | Meaning |\n| --- | --- |\n| `processing` | Queued or running. Keep polling. |\n| `completed` | Finished. Fetch it with `fields=full` or download the artifact. |\n| `partial` | Finished with some parts missing (for example, one correction family failed). |\n| `error` / `failed` | Did not finish. Credits reserved for the job are released. |\n","enum":["processing","completed","partial","error","failed"]},"ResourceStatusSnapshot":{"type":"object","required":["id","resource_type","resource_status"],"properties":{"id":{"type":"string"},"resource_type":{"$ref":"#/components/schemas/ResourceType"},"resource_status":{"$ref":"#/components/schemas/ResourceStatus"},"created_at":{"type":"string","format":"date-time"},"progress":{"type":"integer","minimum":0,"maximum":100,"description":"Completion percentage, when the job reports it."},"source_id":{"type":"string","description":"Source document id, when the resource has one."},"suites":{"$ref":"#/components/schemas/CorrectionSuites"}}},"ResourceType":{"type":"string","enum":["document","guide","brand_voice","analysis_template","synopsis","analysis","report","translation_review","correction_run","translation","index","index_source","ocr","epub","content","detection"]},"Subscription":{"type":"object","required":["plan","period","status","credits_left"],"properties":{"plan":{"type":"string","description":"Commercial plan name, as shown in the dashboard."},"period":{"type":"string","enum":["monthly","yearly"]},"status":{"type":"string","description":"`active` while the subscription is paid up."},"started_at":{"type":"string","format":"date-time","nullable":true},"credits_left":{"type":"integer","description":"Credits available right now."},"next_credit_reload_at":{"type":"string","format":"date-time","nullable":true,"description":"When the balance is next topped up."},"permissions":{"type":"array","items":{"type":"string"},"description":"Permissions of the calling key. `[\"*\"]` means all."}}},"Success":{"type":"object","description":"Fields shared by every successful JSON response.","required":["status","message"],"properties":{"status":{"type":"string","enum":["success"]},"message":{"type":"string"}}},"SynopsisRequest":{"type":"object","required":["doc_id"],"properties":{"doc_id":{"type":"string","description":"A completed document."},"word_count":{"type":"integer","minimum":100,"maximum":500,"default":500,"description":"Target length in words."},"tone":{"type":"string","enum":["entusiasta","misterioso","sobrio","descriptivo"],"description":"Tone of the synopsis: enthusiastic, mysterious, sober or\ndescriptive. Omit it to let the tone follow the book.\n"},"instructions":{"type":"string","description":"Extra guidance (audience, what to emphasise, spoilers to avoid)."},"locale":{"$ref":"#/components/schemas/Locale"}}},"TranslationRequest":{"type":"object","required":["doc_id","language"],"properties":{"doc_id":{"type":"string","description":"A completed document."},"language":{"allOf":[{"$ref":"#/components/schemas/OutputLanguage"}],"description":"Target language."},"instructions":{"type":"string","description":"Extra guidance for the translator (register, glossary, names to keep)."},"locale":{"$ref":"#/components/schemas/Locale"}}},"TranslationReviewRequest":{"type":"object","required":["original_doc_id","translation_doc_id"],"properties":{"original_doc_id":{"type":"string","description":"The original (source-language) document."},"translation_doc_id":{"type":"string","description":"The translated document. Must be a different document."},"locale":{"$ref":"#/components/schemas/Locale"}}},"UploadDocumentRequest":{"type":"object","required":["title"],"properties":{"title":{"type":"string","description":"Title shown in lists, reports and notifications."},"author":{"type":"string","description":"Author name. Required unless `doc_type` is `index_source`."},"description":{"type":"string","description":"Free-text note for your own reference."},"file":{"type":"string","format":"binary","description":"The file to upload. Send `file` or `file_url`."},"file_url":{"type":"string","format":"uri","description":"Public HTTPS URL to fetch the file from. Send `file` or `file_url`."},"doc_type":{"type":"string","enum":["guide","brand_voice","analysis_template","index_source"],"description":"Omit to upload a manuscript."},"locale":{"$ref":"#/components/schemas/Locale"}}}},"responses":{"Unauthorized":{"description":"The `X-API-Key` header is missing, invalid or revoked.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Invalid or missing API key"}}}},"Forbidden":{"description":"The key lacks permission for this operation, or the account has no\nactive subscription. Subscription problems carry a `code`; a missing\npermission has none.\n","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"examples":{"permission":{"summary":"Missing permission","value":{"status":"error","message":"Insufficient permissions for this operation"}},"no_subscription":{"summary":"No subscription","value":{"status":"error","message":"Insufficient permissions for this operation","code":"no_subscription"}},"inactive_subscription":{"summary":"Inactive subscription","value":{"status":"error","message":"Subscription is not active","code":"inactive_subscription"}}}}}},"PaymentRequired":{"description":"Not enough credits left. Top up or wait for the next reload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Insufficient credits for this operation","code":"insufficient_credits"}}}},"NotFound":{"description":"The resource does not exist or belongs to another account.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Resource not found"}}}},"InvalidConversationId":{"description":"`conversation_id` is not a valid id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Invalid conversation ID format"}}}},"ConversationNotFound":{"description":"The conversation does not exist.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Conversation not found"}}}},"Conflict":{"description":"The request conflicts with the current state of the resource.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Idempotent request is already in progress"}}}},"PayloadTooLarge":{"description":"The file or the request body exceeds 100 MB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"File is too large. The maximum size is 100 MB."}}}},"RateLimited":{"description":"Too many requests. Wait `Retry-After` seconds before retrying.","headers":{"X-RateLimit-Limit":{"$ref":"#/components/headers/X-RateLimit-Limit"},"X-RateLimit-Remaining":{"$ref":"#/components/headers/X-RateLimit-Remaining"},"X-RateLimit-Reset":{"$ref":"#/components/headers/X-RateLimit-Reset"},"Retry-After":{"$ref":"#/components/headers/Retry-After"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Rate limit exceeded: 10 per 1 minute"}}}},"InternalError":{"description":"Unexpected server error. Safe to retry with backoff.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"status":"error","message":"Internal server error occurred"}}}}}}}
