Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.corti.ai/llms.txt

Use this file to discover all available pages before exploring further.

Classic continues to work today and be deprecated as soon as the Guided Documents Beta surface moves into general availability. The exact sunset timeline will be communicated via the upcoming changes log.New integrations should build on the Beta surface (POST /documents + the /documents/sections and /documents/templates authoring API). Existing Classic integrations should plan their migration using this guide.

Why migrate

The Guided surface is the path forward. Documents Classic will be deprecated once Beta reaches general availability — see the callout above. Migrating before the sunset gives you time to validate parity and gain the new capabilities. Documents Classic uses string keys (templateKey: "corti-soap", key: "corti-hpi") and a fixed override surface (nameOverride, writingStyleOverride, formatRuleOverride, additionalInstructionsOverride, contentOverride) attached to POST /interactions/{id}/documents. The new API treats sections and templates as first-class, UUID-addressable, versioned resources and moves generation to POST /documents — interaction-optional, with a single consistent request shape across four template-supply paths. Concretely you gain:
  • Typed, schema-controlled outputs (outputSchema) instead of free-text formatting rules — see Section Schemas.
  • Versioning & publish lifecycle for your own sections and templates — see Create a Section.
  • Drift-proof generation snapshots — every call records the resolved template aggregate it used.
  • Interaction-optional context — pass explicit context (text / transcript / facts) or an interactionId — they are currently mutually exclusive; combining is on the roadmap.
SDK helpers for the migration are planned. Until they land, this guide walks you through the mapping manually. The mapping is mostly mechanical — most of the work is one-time discovery (finding the right Standard UUIDs for your locales).

Mental-model shift

Three things change about how you think about templates and sections:
  1. String keys → UUIDs. templateKey: "corti-soap" becomes templateId: "<some-uuid>". Section keys behave the same way.
  2. Per-locale UUIDs. Each Corti Standard section and template is published as a separate resource per locale. The English corti-hpi and the German corti-hpi share the same key but have different UUIDs. Your discovery step must include the lang filter.
  3. Source-aware library. LIST /documents/sections and LIST /documents/templates return your own resources alongside Corti Standards. Each item carries a source field — corti for Corti Standards, user for API-client–authored resources in your project — so you can filter client-side. Server-side query params today are lang, region, specialty, label and published. See Corti Standards.

Endpoint mapping

ClassicNew
GET /templatesLIST /documents/templates (filter via lang, region, specialty, label; filter on source client-side to scope to Corti Standards vs. your own)
GET /templates/{key}GET /documents/templates/{templateID} (after resolving the key + locale to a UUID via the list endpoint)
GET /templateSectionsLIST /documents/sections (same filtering)
POST /interactions/{id}/documents (with templateKey)POST /documentsPath 1 (plain templateRef)
POST /interactions/{id}/documents (with template.sections[] + overrides)POST /documentsPath 2 (templateRef + overrides) or Path 3 (assemblyTemplate) — see below

Field mapping — Classic overrides → new

Where a Classic override sat under template.sections[].keyOverride, the new equivalent lives under overrides.sections[].generation.* on a templateRef or assemblyTemplate request.
Classic fieldNew equivalentNotes
template.descriptionoverrides.instructions.prompt (Path 2) or assemblyTemplate.instructions.prompt (Path 3)Template-level prompt
template.additionalInstructionsOverrideoverrides.instructions.promptTemplate-level
sections[].keysections[].sectionId (Path 2) / sectionRefs[].sectionId (Path 3)Per-locale UUID — resolve once via LIST /documents/sections?lang=... (filter on source: "corti" client-side if scoping to Standards)
sections[].nameOverridesections[].generation.headingSection heading override
sections[].writingStyleOverridesections[].generation.instructions.writingStylePrompt
sections[].contentOverridesections[].generation.instructions.contentPrompt
sections[].additionalInstructionsOverridesections[].generation.instructions.miscPromptFree-form section-level guidance
sections[].formatRuleOverrideNo 1:1 — use outputSchemaSee note below
outputLanguageoutputLanguageUnchanged
namen/a on the request — track in your own system if neededThe response carries the auto-generated templateId you can use to identify the call
context: [{ type: "facts" | "transcript" | "string", data: ... }]context: [{ type: "text" | "transcript" | "facts", ... }] or interactionIdContext input is more flexible in the new API. Classic accepts exactly one context.type per call — facts or transcript or string, never mixed. The Beta surface lets you combine context types in a single context array (e.g. a referral letter as text + a transcript + a few facts items in one call). Alternatively, supply interactionId to pull all non-discarded facts and transcripts attached to that interaction implicitly — no manual context wiring. context and interactionId are mutually exclusive today (combining them is on the roadmap). Note on facts: in the new API each facts item carries one fact (vs. Classic’s data[] array). The documented fact shape requires only text; group is supported as an optional free-form string. See Input context.

About formatRuleOverride

Classic used formatRuleOverride as a free-text format instruction (e.g. “single paragraph in running text” or “use fixed subheadings: Diagnosis:[content]\n\nAssessment:[content]”). The new API replaces this with typed outputSchema formatting primitives:
  • array.itemFormat (bullet, numbered, plain, or custom {item})
  • object.fieldFormat — per-field iteration template using generic {key} / {value} placeholders (e.g. "{key}: {value}\n" inline, "{key}\n{value}\n" block), or a fully custom layout referencing specific field keys (e.g. "{test}: {result}")
This is more powerful but not a drop-in replacement. Two migration paths:
  1. Fork the section with a new outputSchema (Recipe 2 of the Customization Cookbook). One-time setup; persistent.
  2. Override outputSchema at runtime on the guided-synthesis call. Note that outputSchema overrides are wholesale — you must submit the full schema, not a partial. See Customization Cookbook — override semantics.
See Section Schemas for design patterns that cover most Classic formatRuleOverride use cases.

Discovery — resolve Classic keys to UUIDs

Migration starts with a one-time discovery step: for each (key, locale) pair you use in Classic, find the corresponding UUID in the new API.
// Filter by language, region, specialty, label, and/or publish status.
// All four filter params are repeatable arrays. `label` values use "key:value".
const sections = await client.documents.sections.list({
  lang: ["en"],
  region: ["USA"],
  specialty: ["dermatology"],
  label: ["customer:acme"],
  published: true,
});
The response includes each section’s id, key, languages, regions, specialties and publishedVersion. Build a (key, locale [, region, specialty]) → sectionId map in your service. Do the same for templates via LIST /documents/templates?lang=.... If you want to scope to Corti Standards only, filter the response on source === "corti" client-side.
Cache this mapping in your service. Corti Standard UUIDs are stable for the lifetime of a resource (only the underlying published version evolves silently — see Corti Standards limitations).

Step-by-step migration

1

Inventory your Classic usage

For each POST /interactions/{id}/documents call in your codebase, note:
  • which templateKey (or inline template.sections[]) you use,
  • which outputLanguage values you support,
  • which override fields are populated and whether they’re constant per integration or vary per request,
  • any use of documentationMode, disableGuardrails or the X-Corti-Retention-Policy header.
2

Build the key → UUID map

For every (Corti Standard key, locale) pair from step 1, call LIST /documents/sections?lang=... and LIST /documents/templates?lang=... (filter on source === "corti" client-side) and persist the mapping in your service. If your Classic integration used region- or specialty-specific variants, also pass region and specialty filters.
3

Pick a path per call site

  • If you used templateKey with no overridesPath 1 (plain templateRef).
  • If you used templateKey with overrides or inline template.sections[] that maps cleanly onto an existing template → Path 2 (templateRef + overrides).
  • If you assembled sections inline at request time (no stored template) → Path 3 (assemblyTemplate).
  • If you want to start fully fresh with inline section definitions → Path 4 (dynamicTemplate).
  • See Guided Synthesis — the four paths.
4

Translate the request

Apply the field-mapping table above. The biggest change is moving from template.sections[].key + *Override to overrides.sections[].sectionId + generation.*. See the side-by-side example below.
5

Update response handling

Classic responses returned a document with sections[] (each with key, name, text). The new POST /documents response wraps everything in a document object — its templateId, templateVersionId, and document.stringDocument (a {sectionId: renderedString} map — keyed by section UUID, not slug/key) and/or document.structuredDocument, plus a top-level usageInfo.creditsConsumed. See Guided Synthesis — response shape.
6

Decide your interaction story

Classic was always interaction-scoped. The new endpoint is interaction-optional. If you still want facts/transcripts attached to an interaction to flow in implicitly, pass interactionId. If you’d rather pass everything explicitly, supply a context array. The two are mutually exclusive today — combining them is on the roadmap.

Worked example — Classic → new, side by side

The Classic snippet below assembles four sections with overrides on three of them. Compare it to the new equivalent.

Before (Classic)

POST /interactions/{id}/documents — Classic
const document = await client.documents.create(interactionId, {
  context: [
    {
      type: "facts",
      data: [
        { text: "32 year-old female", group: "demographics", source: "system" },
        { text: "itchy rash, started last week", group: "history-of-present-illness", source: "core" },
        { text: "allergic to birch pollen since childhood", group: "allergies", source: "core" },
        { text: "typical eczema appearance", group: "assessment", source: "core" },
        { text: "corticosteroid treatment for 2 weeks, taper-down 2 weeks", group: "plan", source: "core" },
        { text: "follow-up in 6 weeks", group: "plan", source: "core" },
      ],
    },
  ],
  template: {
    description: "Clinical dermatology note",
    sections: [
      {
        key: "corti-hpi",
        nameOverride: "Anamnesis",
        additionalInstructionsOverride: "- refer to patient as my case\n- do not include allergies",
      },
      { key: "corti-allergies" },
      {
        key: "corti-assessment",
        formatRuleOverride: "use fixed subheadings: **Diagnosis**:[content]\n\n**Assessment**:[content]:",
        writingStyleOverride: "telegraphic, clinical neutral",
      },
      {
        key: "corti-plan",
        formatRuleOverride: "Single paragraph in running text",
      },
    ],
  },
  outputLanguage: "en",
  name: "test of override customizations",
  documentationMode: "routed_parallel",
});

After (new — Path 3 assemblyTemplate)

This Classic call assembled sections inline, so Path 3 is the right target. (If you’d instead been calling a stored template by templateKey, you’d use Path 2.) formatRuleOverride on corti-assessment and corti-plan does not have a runtime equivalent on its own — for that you’d either supply a full outputSchema in the override (wholesale replacement) or create an inheriting section ahead of time with the desired schema. The example below uses inline outputSchema overrides to keep the migration in one request.
POST /documents — Path 3 (assemblyTemplate)
const result = await client.documents.generate({
  outputLanguage: "en-US",
  context: [
    {
      type: "facts",
      fact: { text: "32 year-old female" },
    },
    { type: "facts", fact: { text: "itchy rash, started last week" } },
    { type: "facts", fact: { text: "allergic to birch pollen since childhood" } },
    { type: "facts", fact: { text: "typical eczema appearance" } },
    { type: "facts", fact: { text: "corticosteroid treatment for 2 weeks, taper-down 2 weeks" } },
    { type: "facts", fact: { text: "follow-up in 6 weeks" } },
  ],
  assemblyTemplate: {
    name: "Clinical dermatology note",
    instructions: {
      prompt: "Clinical dermatology note.",
    },
    sectionRefs: [
      {
        // corti-hpi (en) UUID, resolved once via LIST /documents/sections?lang=en (filter source === "corti" client-side)
        sectionId: "<your-section-id>",
        overrides: {
          heading: "Anamnesis",
          instructions: {
            miscPrompt: "- refer to patient as my case\n- do not include allergies",
          },
        },
      },
      { sectionId: "<your-section-id>" },
      {
        sectionId: "<your-section-id>",
        overrides: {
          instructions: {
            writingStylePrompt: "telegraphic, clinical neutral",
          },
          // formatRuleOverride → typed outputSchema (wholesale replacement).
          // See /textgen/section-schemas for design patterns.
          outputSchema: {
            type: "object",
            fieldFormat: "**Diagnosis**: {diagnosis}\n\n**Assessment**: {assessment}",
            fields: [
              { key: "diagnosis",  description: "Diagnosis", value: { type: "string" } },
              { key: "assessment", description: "Assessment narrative", value: { type: "string" } },
            ],
          },
        },
      },
      {
        sectionId: "<your-section-id>",
        overrides: {
          // formatRuleOverride: "Single paragraph in running text" → tighten the schema
          // and use writingStylePrompt to nudge prose vs. bullets.
          instructions: {
            writingStylePrompt: "Single paragraph in running prose; no bullets, no line breaks.",
          },
          outputSchema: { type: "string" },
        },
      },
    ],
  },
});

Behavior notes on the example

  • One fact per context item in the new API. Classic packed all facts under a single data[]; the new shape uses one item with type: "facts" and a single fact per item.
  • nameOverrideheading, writingStyleOverridewritingStylePrompt, additionalInstructionsOverridemiscPrompt, contentOverridecontentPrompt — mechanical renames.
  • formatRuleOverride rewrites as an outputSchema — wholesale replacement of the section’s schema for this call. The example uses fieldFormat to lock the fixed subheadings, and a plain string schema to force single-paragraph prose.
  • The response is document.stringDocument (and document.structuredDocument for the assessment section because its schema is an object) — not the Classic sections[] array. The wrapping shape is { document: { ... }, usageInfo: { creditsConsumed } }.

Features being aligned

A handful of Classic features don’t yet have a public equivalent on POST /documents:
  • documentationMode: routed_parallel — the Documentation Mode flag.
  • X-Corti-Retention-Policy: none header — opt-out of database persistence per request.
  • disableGuardrails — toggle documentation guardrails per request.
If your Classic integration relies on any of these, reach out to help@corti.ai or your Corti contact for the planned equivalent before cutting traffic over. Otherwise, the mapping above covers everyday usage.

Quick reference

Guided Synthesis

Full reference for POST /documents and the four template-supply paths.

Customization Cookbook

Seven recipes from “use Corti Standards as-is” to “your own + customer inheritance + per-call override.”

Section Schemas

Schema patterns that replace Classic formatRuleOverride and unlock typed outputs.

Corti Standards

The library and discovery patterns you’ll use to resolve Classic keys to UUIDs.