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 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:

  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 downloadUrl (or fallback to fileUri).

Terminal statuses:

  • COMPLETED
  • FAILED
  • CANCELED
  • TERMINATED
  • TIMED_OUT

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 objectId for content views; keep inline only for workflow message export actions.

Template and Options

Both modes support:

  • templateUrl
  • templateLogoUrl (studio-hosted URL for PDF template logo override)
  • useDefaultTemplate
  • pandocOptions
  • 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:

{
  "objectId": "<OBJECT_ID>",
  "format": "pdf",
  "metadata": {
    "documentId": "REP-2026-02",
    "agentName": "Research Agent"
  }
}

API Reference

For complete request/response details, see:

Was this page helpful?