Overview
Corti's Guided Documents API generates clinical documents from a single endpoint: POST /documents. Documents can be generated from:
Facts finalized during an interaction (including facts you add from your own systems)
Transcripts of a conversation
Existing documents or free-form text (e.g. referral letters, dictation)
Any combination of the above — or implicitly, by referencing an existing interaction
Generation is built on Templates and Sections — first-class, versioned, publishable resources that you can browse, create, and manage via the API. See Using Templates and Sections in the Corti API for the resource model.
⚠️ Already integrating with POST /interactions/{id}/documents and templateKey? That surface ("Documents Classic") is deprecated and will be shut down on January 18, 2027. It keeps working until then, but new integrations should build on Guided Documents. See the migration guide on docs.corti.ai.
💡 This feature requires human oversight of its outputs.
The Generate Document Endpoint
POST <https://api.eu.corti.app/v2/documents>
Every request needs three things:
Requirement | Field(s) |
A template supply — exactly one of four ways to define the document structure |
|
Input context — what the model reasons over |
|
Output language — BCP-47 tag (e.g. |
|
Full API reference: Generate a structured document.
The Four Template-Supply Paths
Path | What you supply | Use when |
Path 1 — | A stored template's UUID | Production traffic; the template already encodes everything you need. No side-effects. |
Path 2 — | A stored template plus per-call tweaks | Keep your base template, but patch a section's heading, prompts, or output schema for a single call. |
Path 3 — | A list of stored sections in your chosen order | Compose a document on the fly, e.g. EHR-field-driven notes. |
Path 4 — | Fully inline section definitions | Prototyping and one-off generations; nothing is saved first. |
Supply exactly one of the three template fields — passing zero, or more than one, returns a 422 error.
Path 1: Stored Templates
Corti maintains a curated library of standard templates (SOAP, H&P, nursing note, and more), each published per language. Retrieve available templates with LIST /documents/templates — filterable by lang, region, specialty, and label — and use the template's id (UUID) in your request.
curl --request POST \
--url <https://api.eu.corti.app/v2/documents> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Tenant-Name: <tenant-name>' \
--data '{
"outputLanguage": "en-US",
"interactionId": "<your-interaction-id>",
"templateRef": {
"templateId": "<your-template-id>"
}
}'
By default the template's currently published version is used. To pin an exact version for reproducibility, also pass templateVersionId.
Path 2: Stored Template + Overrides
Keep the base template, but customize individual sections for a single call. Section-level overrides live under overrides.sections[].generation:
Field | Purpose |
| Override the section heading (title) |
| Guide what input content gets assigned to the section |
| Prompt the writing style (e.g. telegraphic, plain language) |
| Free-form additional instructions |
| Control the output's shape and format (typed schema — replaces the old |
See Document Generation: Customizing Sections — Best Practices for prompting guidance.
Path 3: Assemble Stored Sections
If no template matches your need but the right sections exist, assemble them at request time. List sections with LIST /documents/sections (same filters), then reference them by UUID — the order of sectionRefs determines the order of sections in the document.
curl --request POST \
--url <https://api.eu.corti.app/v2/documents> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Tenant-Name: <tenant-name>' \
--data '{
"outputLanguage": "en-US",
"interactionId": "<your-interaction-id>",
"assemblyTemplate": {
"name": "Allergy follow-up note",
"instructions": {
"prompt": "Produce a focused follow-up note for an allergy consultation."
},
"sectionRefs": [
{ "sectionId": "<your-section-id>" },
{ "sectionId": "<your-section-id>" },
{
"sectionId": "<your-section-id>",
"overrides": {
"generation": {
"heading": "Impression",
"instructions": { "writingStylePrompt": "Telegraphic; no narrative." }
}
}
}
]
}
}'
Path 4: Fully Inline (Dynamic Template)
Define the template and every section inline — headings, prompts, and output schemas — without saving anything. Ideal for iterating on prompt design before promoting sections to your stored library. See Path 4 — dynamicTemplate on docs.corti.ai.
Providing Input Context
Tell the model what to reason over — supply exactly one of:
Option | Behavior |
| You pass the input explicitly. Items are combinable: mix |
| The API implicitly pulls all non-discarded facts and transcripts attached to the referenced interaction. |
context and interactionId are currently mutually exclusive.
Context item types:
| Required field | Use when |
|
| Pasting a referral letter, dictation, EHR field, or any free-form snippet |
|
| Feeding a conversation transcript directly |
|
| Supplying clinical facts explicitly |
Example — mixed context with a stored template and one override:
curl --request POST \
--url <https://api.eu.corti.app/v2/documents> \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Tenant-Name: <tenant-name>' \
--data '{
"outputLanguage": "en-US",
"context": [
{ "type": "text", "text": "Referral letter: Patient referred by GP for evaluation of a persistent rash." },
{
"type": "facts",
"facts": [
{ "text": "32 year-old female", "group": "demographics" },
{ "text": "itchy rash, started last week", "group": "history-of-present-illness" },
{ "text": "allergic to birch pollen since childhood", "group": "allergies" }
]
}
],
"templateRef": {
"templateId": "<your-template-id>",
"overrides": {
"sections": [
{
"sectionId": "<your-section-id>",
"generation": {
"heading": "Anamnesis",
"instructions": { "miscPrompt": "Refer to the patient as my case." }
}
}
]
}
}
}'
💡 Don't pass unnecessary metadata (timestamps, segment indices) in context items — it bloats input token usage without benefit.
The Response
A successful call returns 201 Created (the document is persisted) along with:
document.sections— every section in template order, with itssectionIdand renderedheadingdocument.stringDocument— an object keyed by section UUID containing each section's Markdown outputdocument.structuredDocument— present when sections declare anoutputSchema; values are typed to each schemadocument.templateId/document.templateVersionId— the exact template version that produced the document, for full traceabilityusageInfo.creditsConsumed— credits consumed by the request
Retention: if you do not want the generated document saved, add the header X-Corti-Retention-Policy: none. The document is generated and returned as usual (HTTP 200), but not persisted.
Good to Know
Drift-proof snapshots: every call except a plain
templateRef(Path 1) auto-generates a template aggregate snapshotting the resolved template and sections. Aggregates are retained for 30 days — convert them into permanent project-owned resources if you need them longer.All-or-nothing generation: if any step of generation fails, the entire request fails. You will never receive a partial document. If you need per-section resilience, generate sections in separate requests.
No duplicate sections: the same
sectionIdcannot be used twice in one request.Migrating from Classic? The
documentationModeanddisableGuardrailsparameters do not yet have equivalents onPOST /documents. If your integration relies on them, reach out to support before cutting traffic over.
