---
title: "Markdown Export Guide"
source: "https://docs.vertesiahq.com/content/markdown-export"
markdown: "https://docs.vertesiahq.com/llms/content/markdown-export.md"
---

# Markdown Export Guide

This guide explains how to export markdown to `PDF` or `DOCX` with Vertesia rendering jobs.

Use this when you need:

- report exports from stored markdown documents
- workflow message exports from inline markdown
- non-blocking UX (start + poll + download)

TOC behavior:
- The renderer adds a native Table of Contents automatically for both PDF and DOCX.
- Do not add manual TOC tables in markdown (for example `TABLE DES MATIÈRES` with a `Page` column).

## Choose Input Mode

### Object mode (recommended for documents)

Use `object_id` when the markdown already exists as a content object.

Benefits:
- reproducible exports
- easier auditing and reruns
- no large payloads in request body

### Inline mode (recommended for workflow messages)

Use `content` when rendering ephemeral markdown generated during a run (for example message summaries or final answers).

Benefits:
- no need to create an object first
- fast export path for UI message actions

## Rendering Flow

Rendering is asynchronous:

1. `POST /api/v1/rendering/jobs` starts a job.
2. Poll `GET /api/v1/rendering/jobs/status` until terminal status.
3. On `COMPLETED`, download from `download_url` (or fallback to `file_uri`).

Terminal statuses:
- `COMPLETED`
- `FAILED`
- `CANCELED`
- `TERMINATED`
- `TIMED_OUT`

## SDK Usage (Recommended)

The SDK already performs start + polling for you:

```typescript
import { VertesiaClient, MarkdownRenditionFormat } from "@vertesia/client";

const client = new VertesiaClient({
  site: "api.vertesia.io",
  apikey: "<YOUR_API_KEY>",
});

// Object mode
const pdf = await client.store.rendering.render({
  object_id: "<OBJECT_ID>",
  format: MarkdownRenditionFormat.pdf,
  title: "Portfolio Report",
});

// Inline mode (workflow message export)
const docx = await client.store.rendering.render({
  content: "# Message Export\n\nRendered from inline markdown.",
  format: MarkdownRenditionFormat.docx,
  title: "Message Export",
});
```

## Manual Polling (Advanced)

Use manual polling when you need custom behavior (cancel buttons, global queue, telemetry):

```typescript
import { WorkflowExecutionStatus } from "@vertesia/common";

const started = await client.store.rendering.start({
  object_id: "<OBJECT_ID>",
  format: "pdf",
});

while (true) {
  const status = await client.store.rendering.getStatus(
    started.workflow_id!,
    started.workflow_run_id!,
  );

  if (status.status === WorkflowExecutionStatus.COMPLETED) {
    console.log(status.download_url);
    break;
  }

  if (
    status.status === WorkflowExecutionStatus.FAILED ||
    status.status === WorkflowExecutionStatus.CANCELED ||
    status.status === WorkflowExecutionStatus.TERMINATED ||
    status.status === WorkflowExecutionStatus.TIMED_OUT
  ) {
    throw new Error(status.error || "Rendering failed");
  }

  await new Promise((r) => setTimeout(r, 1500));
}
```

## UX Recommendations

- Disable export buttons while a render is running.
- Show a compact “Exporting…” status.
- Surface clear error messages from terminal failure statuses.
- Prefer `object_id` for content views; keep inline only for workflow message export actions.

## Template and Options

Both modes support:
- `template_url`
- `template_logo_url` (studio-hosted URL for PDF template logo override)
- `use_default_template`
- `pandoc_options`
- `metadata` (PDF header/footer fields)

Notes:
- TOC is enabled by default for both PDF and DOCX.
- If needed, disable TOC with `pandocOptions: ["--toc=false"]`.

Example:

```json
{
  "object_id": "<OBJECT_ID>",
  "format": "pdf",
  "metadata": {
    "document_id": "REP-2026-02",
    "agent_name": "Research Agent"
  }
}
```

## API Reference

For complete request/response details, see:
- [/api/rendering](/api/rendering)