> ## 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.

# Versioning & publishing

> Iterate, version and publish clinical document sections and templates on the Corti API with an explicit draft-then-promote lifecycle — previously published versions stay live until you explicitly publish a new one

Sections and templates share the same draft-then-promote lifecycle. Every time you change a section's prompts/schema or a template's instructions/composition, you create a new **version**. New versions are **not** published automatically — your previously published version stays live until you explicitly publish a new one. That gives you safe iteration in production: drafts are private to your project until promotion, and consumers continue to see the previously published version.

<Tip>Treat unpublished versions as drafts. You can `GET` the list of versions, inspect each, and only publish once you're confident.</Tip>

***

## Versioning a section

Once a section exists, iterate by creating new versions.

<CodeGroup>
  ```ts title="JavaScript" expandable theme={null}
  // Replace these with your values
  const SECTION_ID = "<your-section-id>";

  const version = await client.documents.sections.versions.create(SECTION_ID, {
    generation: {
      heading: "Clinical Findings",
      instructions: {
        contentPrompt: "Extract all relevant clinical findings, grouped by body system where applicable.",
        writingStylePrompt: "Concise, professional, with grouped subheadings when relevant.",
      },
      outputSchema: { type: "string" },
    },
  });
  ```

  ```csharp title="C# .NET" expandable theme={null}
  using Corti;

  // Replace these with your values
  const string SectionId = "<your-section-id>";

  var version = await client.Documents.Sections.Versions.CreateAsync(
      SectionId,
      new GuidedSectionsCreateVersionRequest
      {
          Generation = new GuidedSectionGenerationPartial
          {
              Heading = "Clinical Findings",
              Instructions = new GuidedSectionInstructionsPartial
              {
                  ContentPrompt = "Extract all relevant clinical findings, grouped by body system where applicable.",
                  WritingStylePrompt = "Concise, professional, with grouped subheadings when relevant.",
              },
              OutputSchema = new GuidedStringNode(),
          },
      });
  ```

  ```python title="Python" expandable theme={null}
  import requests

  # Replace these with your values
  ENVIRONMENT = "<eu-or-us>"
  SECTION_ID = "<your-section-id>"
  TENANT = "<your-tenant-name>"
  TOKEN = "<your-access-token>"

  response = requests.post(
      f"https://api.{ENVIRONMENT}.corti.app/v2/documents/sections/{SECTION_ID}/versions",
      headers={
          "Authorization": f"Bearer {TOKEN}",
          "Tenant-Name": TENANT,
          "Content-Type": "application/json",
      },
      json={
          "generation": {
              "heading": "Clinical Findings",
              "instructions": {
                  "contentPrompt": "Extract all relevant clinical findings, grouped by body system where applicable.",
                  "writingStylePrompt": "Concise, professional, with grouped subheadings when relevant.",
              },
              "outputSchema": {"type": "string"},
          },
      },
  )
  response.raise_for_status()
  version = response.json()
  ```

  ```bash title="cURL" expandable theme={null}
  # Replace these with your values
  ENVIRONMENT="<eu-or-us>"
  SECTION_ID="<your-section-id>"
  TENANT="<your-tenant-name>"
  TOKEN="<your-access-token>"

  curl --request POST \
    --url "https://api.${ENVIRONMENT}.corti.app/v2/documents/sections/${SECTION_ID}/versions" \
    --header "Authorization: Bearer ${TOKEN}" \
    --header "Tenant-Name: ${TENANT}" \
    --header "Content-Type: application/json" \
    --data '{
      "generation": {
        "heading": "Clinical Findings",
        "instructions": {
          "contentPrompt": "Extract all relevant clinical findings, grouped by body system where applicable.",
          "writingStylePrompt": "Concise, professional, with grouped subheadings when relevant."
        },
        "outputSchema": { "type": "string" }
      }
    }'
  ```
</CodeGroup>

The response returns the new version with an auto-incremented `versionNumber`.

<CodeGroup>
  ```ts title="JavaScript" theme={null}
  // Replace these with your values
  const SECTION_ID = "<your-section-id>";
  const VERSION_ID = "<your-version-id>";

  await client.documents.sections.versions.publish(SECTION_ID, VERSION_ID);
  ```

  ```csharp title="C# .NET" theme={null}
  using Corti;

  // Replace these with your values
  const string SectionId = "<your-section-id>";
  const string VersionId = "<your-version-id>";

  await client.Documents.Sections.Versions.PublishAsync(SectionId, VersionId);
  ```

  ```python title="Python" theme={null}
  import requests

  # Replace these with your values
  ENVIRONMENT = "<eu-or-us>"
  SECTION_ID = "<your-section-id>"
  TENANT = "<your-tenant-name>"
  TOKEN = "<your-access-token>"
  VERSION_ID = "<your-version-id>"

  response = requests.post(
      f"https://api.{ENVIRONMENT}.corti.app/v2/documents/sections/{SECTION_ID}/versions/{VERSION_ID}/publish",
      headers={
          "Authorization": f"Bearer {TOKEN}",
          "Tenant-Name": TENANT,
      },
  )
  response.raise_for_status()
  status = response.json()
  ```

  ```bash title="cURL" theme={null}
  # Replace these with your values
  ENVIRONMENT="<eu-or-us>"
  SECTION_ID="<your-section-id>"
  TENANT="<your-tenant-name>"
  TOKEN="<your-access-token>"
  VERSION_ID="<your-version-id>"

  curl --request POST \
    --url "https://api.${ENVIRONMENT}.corti.app/v2/documents/sections/${SECTION_ID}/versions/${VERSION_ID}/publish" \
    --header "Authorization: Bearer ${TOKEN}" \
    --header "Tenant-Name: ${TENANT}"
  ```
</CodeGroup>

A successful publish returns `{ "status": "published" }` and the section's `publishedVersion` will reflect the new version on subsequent `GET` calls.

***

## Versioning a template

Once a template exists, iterate by creating new versions. The published version stays live until you explicitly publish a new one.

<CodeGroup>
  ```ts title="JavaScript" expandable theme={null}
  // Replace these with your values
  const SECTION_ID_1 = "<your-section-id>";
  const SECTION_ID_2 = "<your-section-id>";
  const SECTION_ID_NEW = "<your-section-id>";
  const TEMPLATE_ID = "<your-template-id>";

  const version = await client.documents.templates.versions.create(TEMPLATE_ID, {
    generation: {
      instructions: {
        prompt: "Produce a structured consultation note. Address the patient in second person.",
      },
      sections: [
        { sectionId: SECTION_ID_1, orderIndex: 0 },
        { sectionId: SECTION_ID_2, orderIndex: 1 },
        { sectionId: SECTION_ID_NEW, orderIndex: 2 },
      ],
    },
  });
  ```

  ```csharp title="C# .NET" expandable theme={null}
  using Corti;

  // Replace these with your values
  const string SectionId1 = "<your-section-id>";
  const string SectionId2 = "<your-section-id>";
  const string SectionIdNew = "<your-section-id>";
  const string TemplateId = "<your-template-id>";

  var version = await client.Documents.Templates.Versions.CreateAsync(
      TemplateId,
      new GuidedTemplatesCreateVersionRequest
      {
          Generation = new GuidedTemplatesVersionGeneration
          {
              Instructions = new GuidedTemplateInstructionsPartial
              {
                  Prompt = "Produce a structured consultation note. Address the patient in second person.",
              },
              Sections = new[]
              {
                  new GuidedTemplatesVersionSectionRequest { SectionId = SectionId1, OrderIndex = 0 },
                  new GuidedTemplatesVersionSectionRequest { SectionId = SectionId2, OrderIndex = 1 },
                  new GuidedTemplatesVersionSectionRequest { SectionId = SectionIdNew, OrderIndex = 2 },
              },
          },
      });
  ```

  ```python title="Python" expandable theme={null}
  import requests

  # Replace these with your values
  ENVIRONMENT = "<eu-or-us>"
  SECTION_ID_1 = "<your-section-id>"
  SECTION_ID_2 = "<your-section-id>"
  SECTION_ID_NEW = "<your-section-id>"
  TEMPLATE_ID = "<your-template-id>"
  TENANT = "<your-tenant-name>"
  TOKEN = "<your-access-token>"

  response = requests.post(
      f"https://api.{ENVIRONMENT}.corti.app/v2/documents/templates/{TEMPLATE_ID}/versions",
      headers={
          "Authorization": f"Bearer {TOKEN}",
          "Tenant-Name": TENANT,
          "Content-Type": "application/json",
      },
      json={
          "generation": {
              "instructions": {
                  "prompt": "Produce a structured consultation note. Address the patient in second person.",
              },
              "sections": [
                  {"sectionId": SECTION_ID_1, "orderIndex": 0},
                  {"sectionId": SECTION_ID_2, "orderIndex": 1},
                  {"sectionId": SECTION_ID_NEW, "orderIndex": 2},
              ],
          },
      },
  )
  response.raise_for_status()
  version = response.json()
  ```

  ```bash title="cURL" expandable theme={null}
  # Replace these with your values
  ENVIRONMENT="<eu-or-us>"
  SECTION_ID_1="<your-section-id>"
  SECTION_ID_2="<your-section-id>"
  SECTION_ID_NEW="<your-section-id>"
  TEMPLATE_ID="<your-template-id>"
  TENANT="<your-tenant-name>"
  TOKEN="<your-access-token>"

  curl --request POST \
    --url "https://api.${ENVIRONMENT}.corti.app/v2/documents/templates/${TEMPLATE_ID}/versions" \
    --header "Authorization: Bearer ${TOKEN}" \
    --header "Tenant-Name: ${TENANT}" \
    --header "Content-Type: application/json" \
    --data "{
      \"generation\": {
        \"instructions\": {
          \"prompt\": \"Produce a structured consultation note. Address the patient in second person.\"
        },
        \"sections\": [
          { \"sectionId\": \"${SECTION_ID_1}\", \"orderIndex\": 0 },
          { \"sectionId\": \"${SECTION_ID_2}\", \"orderIndex\": 1 },
          { \"sectionId\": \"${SECTION_ID_NEW}\", \"orderIndex\": 2 }
        ]
      }
    }"
  ```
</CodeGroup>

<CodeGroup>
  ```ts title="JavaScript" theme={null}
  // Replace these with your values
  const TEMPLATE_ID = "<your-template-id>";
  const VERSION_ID = "<your-version-id>";

  await client.documents.templates.versions.publish(TEMPLATE_ID, VERSION_ID);
  ```

  ```csharp title="C# .NET" theme={null}
  using Corti;

  // Replace these with your values
  const string TemplateId = "<your-template-id>";
  const string VersionId = "<your-version-id>";

  await client.Documents.Templates.Versions.PublishAsync(TemplateId, VersionId);
  ```

  ```python title="Python" theme={null}
  import requests

  # Replace these with your values
  ENVIRONMENT = "<eu-or-us>"
  TEMPLATE_ID = "<your-template-id>"
  TENANT = "<your-tenant-name>"
  TOKEN = "<your-access-token>"
  VERSION_ID = "<your-version-id>"

  response = requests.post(
      f"https://api.{ENVIRONMENT}.corti.app/v2/documents/templates/{TEMPLATE_ID}/versions/{VERSION_ID}/publish",
      headers={
          "Authorization": f"Bearer {TOKEN}",
          "Tenant-Name": TENANT,
      },
  )
  response.raise_for_status()
  status = response.json()
  ```

  ```bash title="cURL" theme={null}
  # Replace these with your values
  ENVIRONMENT="<eu-or-us>"
  TEMPLATE_ID="<your-template-id>"
  TENANT="<your-tenant-name>"
  TOKEN="<your-access-token>"
  VERSION_ID="<your-version-id>"

  curl --request POST \
    --url "https://api.${ENVIRONMENT}.corti.app/v2/documents/templates/${TEMPLATE_ID}/versions/${VERSION_ID}/publish" \
    --header "Authorization: Bearer ${TOKEN}" \
    --header "Tenant-Name: ${TENANT}"
  ```
</CodeGroup>

A successful publish returns `{ "status": "published" }` and subsequent `GET /documents/templates/{templateID}` reflects the new `publishedVersion`.

<Note>Publishing a template version validates that every referenced section has a published version. Fix any unpublished sections before retrying the publish.</Note>

## Independent versioning — what a template version captures

Sections and templates are versioned **independently**. A template version records:

* the template's instructions,
* which sections it references,
* the ordering of those sections.

It does **not** pin a specific version of each referenced section — sections always resolve to their own published version at request time. So reverting a template version reverts the composition and template instructions, but each section still uses its latest published version.

<Note>
  This means reverting a template version does **not** roll back changes you made to individual sections. For example, if you edit section A, add a new section B to the template, then edit section C, reverting only the template keeps all three section changes. Reverting each section individually would restore its prior prompts and schema, but not affect the template's composition. And because sections are shared across templates, reverting a section affects every template that references it.

  **Practical takeaway:** if you need to roll back a template *and* its sections to a known-good state, revert the template version first, then revert the individual section versions. There is no single operation that reverts both at once.
</Note>
