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ÈRESwith aPagecolumn).
Choose Input Mode
Object mode (recommended for documents)
Use objectId 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:
POST /api/v1/rendering/jobsstarts a job.- Poll
GET /api/v1/rendering/jobs/statusuntil terminal status. - On
COMPLETED, download fromdownloadUrl(or fallback tofileUri).
Terminal statuses:
COMPLETEDFAILEDCANCELEDTERMINATEDTIMED_OUT
SDK Usage (Recommended)
The SDK already performs start + polling for you:
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({
objectId: "<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):
import { WorkflowExecutionStatus } from "@vertesia/common";
const started = await client.store.rendering.start({
objectId: "<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.downloadUrl);
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
objectIdfor content views; keep inline only for workflow message export actions.
Template and Options
Both modes support:
templateUrltemplateLogoUrl(studio-hosted URL for PDF template logo override)useDefaultTemplatepandocOptionsmetadata(PDF header/footer fields)
Notes:
- TOC is enabled by default for both PDF and DOCX.
- If needed, disable TOC with
pandocOptions: ["--toc=false"].
Example:
{
"objectId": "<OBJECT_ID>",
"format": "pdf",
"metadata": {
"documentId": "REP-2026-02",
"agentName": "Research Agent"
}
}
API Reference
For complete request/response details, see:
