Document conversion
Convert a document between markup and structured formats from a single API call — markdown, html, docx, odt, rtf, epub, latex, rst, org, textile, mediawiki, plain, plus slide decks (pptx), Jupyter notebooks (ipynb), asciidoc, GitHub-flavored markdown (gfm), jira markup, and typst. Backed by pandoc on a dedicated worker; priced per MB of input, and the conversion matrix itself is free to query so you can check a from→to pair before you pay.
curl -X POST https://api.relaystation.ai/v1/doc/convert \
-H 'Authorization: Bearer rs_live_<key>' \
-H 'Idempotency-Key: readme-to-docx-20260611' \
-H 'Content-Type: application/json' \
-d '{ "file": { "inline": "<base64 markdown>" }, "from": "markdown", "to": "docx" }'
Or on the lodestone path — no account, a signed x402 payment instead of an API key:
curl -X POST https://api.relaystation.ai/v1/doc/convert \
-H 'X-Payment: <base64 EIP-3009 authorization>' \
-H 'Idempotency-Key: readme-to-docx-20260611' \
-H 'Content-Type: application/json' \
-d '{ "file": { "inline": "<base64 markdown>" }, "from": "markdown", "to": "docx" }'
Pick your lane
Three converters cover three different jobs — pick by your source:
- Markup / structured → markup / structured is this endpoint (
/v1/doc/convert, pandoc). Markdown ↔ HTML ↔ docx ↔ LaTeX ↔ rst ↔ org ↔ epub and more. - Office-binary → PDF (docx/xlsx/pptx/odt/…) is
POST /v1/pdf/from-office(LibreOffice). - HTML → PDF is
POST /v1/pdf/from-html(headless Chromium).
Request options
POST /v1/doc/convert takes:
| Field | Type | Default | Notes |
|---|---|---|---|
file | input source, required | — | { "inline": "<base64>" } ≤ 4 MiB, or { "inputKey": "..." } from POST /v1/cputools/upload-url for larger files — see passing & receiving files |
filename | string | — | used to sniff from by extension (.md, .docx, .tex, …) when from is omitted |
from | string | sniffed from filename | source format (markdown, html, docx, …). Neither from nor a recognizable filename → free 422 SOURCE_FORMAT_REQUIRED |
to | string, required | — | target format. An unsupported pair → free 422 UNSUPPORTED_CONVERSION that lists the valid targets for your source |
referenceDoc | input source | — | a branded docx/pptx template whose styling the output inherits. Same shape as file ({ "inline": "<base64>" } or { "inputKey": "..." }). Only valid when to is docx or pptx — any other target → free 422 REFERENCE_DOC_UNSUPPORTED; the template must itself be an OOXML/ZIP document → else free 422 REFERENCE_DOC_FORMAT_INVALID |
citations | object | — | turn on citation processing — { "bibliography": <source>, "format"?: "bib"|"json"|"yaml", "csl"?: <source> }. See Citations & bibliographies |
options.standalone | boolean | true | produce a complete document (header/wrapper) rather than a fragment; pass false for a bare fragment |
Caps and sandboxing. Input ≤ 25 MB (cputools.doc.max_mb, operator-tunable; over → 413 INPUT_TOO_LARGE, pre-charge and free). pandoc runs with --sandbox on a dedicated worker — a crafted document can’t read files or reach the network from inside the conversion. The result comes back in the standard output envelope (inline when small, presigned URL when large) — see Receiving outputs.
The conversion matrix — free to query
GET /v1/doc/formats returns the exact supported pairs, lossy flags, and the PDF composition path. Free, read-only, no auth:
curl https://api.relaystation.ai/v1/doc/formats
The static table below is a snapshot of that live endpoint — same data, and GET /v1/doc/formats is always authoritative (the operator can enable/disable pairs without a redeploy). The ten source formats and where each can go (* = lossy):
| From | To |
|---|---|
markdown | html, docx, pptx, odt, rtf, epub, latex, rst, org, textile, mediawiki, asciidoc, gfm, jira, typst, plain* |
html | markdown, docx, odt, rtf, epub, latex, rst, org, plain* |
docx | markdown*, html*, odt*, rtf*, epub*, latex*, rst*, org*, plain* |
latex | markdown, html, docx, odt, rst, plain* |
odt | markdown*, html*, docx*, latex*, rst*, plain* |
epub | markdown*, html*, docx*, latex*, plain* |
rst | markdown, html, docx, latex, plain* |
org | markdown, html, docx, latex, plain* |
textile | markdown, html, docx, plain* |
mediawiki | markdown, html, docx, plain* |
New target formats — pptx, ipynb, asciidoc, gfm, jira, and typst — are rolling onto the matrix; asciidoc and jira are output-only (writer formats, not sources), while ipynb, gfm, and typst work as both source and target. GET /v1/doc/formats is always the authoritative, up-to-the-minute list — query it before you build a path.
Slide decks (markdown → pptx)
Convert structured markdown into a PowerPoint deck (to: "pptx"). pandoc maps your document structure onto slides: a level-1 or level-2 heading starts a new slide, and a horizontal rule (---) also begins a new slide — so you control the deck layout from plain markdown.
curl -X POST https://api.relaystation.ai/v1/doc/convert \
-H 'Authorization: Bearer rs_live_<key>' \
-H 'Idempotency-Key: outline-to-deck-20260612' \
-H 'Content-Type: application/json' \
-d '{ "file": { "inline": "<base64 markdown>" }, "from": "markdown", "to": "pptx" }'
Branded output (reference templates)
For docx and pptx targets you can supply a referenceDoc — your own styled template document — and the converted output inherits its fonts, colors, master slides, and styles. Pass it inline or by storage key, the same way you pass file:
curl -X POST https://api.relaystation.ai/v1/doc/convert \
-H 'Authorization: Bearer rs_live_<key>' \
-H 'Idempotency-Key: branded-report-20260612' \
-H 'Content-Type: application/json' \
-d '{ "file": { "inline": "<base64 markdown>" }, "from": "markdown", "to": "docx", "referenceDoc": { "inputKey": "<key from upload-url>" } }'
A referenceDoc is only meaningful for docx/pptx output — for any other target you get a free 422 REFERENCE_DOC_UNSUPPORTED. The template itself must be an OOXML document (a .docx/.pptx, which is a ZIP package); supplying something else (a PDF, an image, a plain-text file) is a free 422 REFERENCE_DOC_FORMAT_INVALID before you are charged. The template is server-side styling, so it does not add to your bill: you still pay only per MB of the primary input.
Citations & bibliographies
Pass citations to turn on pandoc’s --citeproc: in-document citation markers ([@smith2020], [@doe2019, pp. 33-35]) are replaced with formatted citations, and a bibliography section is appended listing the works cited. It works for any target format (html, docx, latex, …) — and a document with no citation markup simply comes back with no bibliography (a safe no-op).
{
"file": { "inline": "<base64 markdown with [@key] citations>" },
"from": "markdown",
"to": "html",
"citations": {
"bibliography": { "inputKey": "<key from upload-url>" }, // or { "inline": "<base64>" }
"format": "bib", // "bib" (BibTeX/BibLaTeX, default) | "json" (CSL-JSON) | "yaml" (CSL-YAML)
"csl": { "inline": "<base64 .csl stylesheet>" } // optional — omit for the default style
}
}
| Field | Type | Default | Notes |
|---|---|---|---|
citations.bibliography | input source, required | — | the reference database — BibTeX/BibLaTeX, CSL-JSON, or CSL-YAML. Same { inline } / { inputKey } shape as file |
citations.format | enum | bib | the bibliography file’s format: bib, json, or yaml |
citations.csl | input source | — | a CSL stylesheet to control the citation/bibliography style. Omit for the built-in chicago-author-date default (embedded — no network) |
Citation files are auxiliary, like a referenceDoc: they don’t add to your bill — you still pay only per MB of the primary input. Everything runs under the same --sandbox (no file/network access from inside the document).
Want a PDF?
pandoc has no PDF writer without a LaTeX engine, so PDF is a two-step composition: convert to HTML here, then render to PDF via POST /v1/pdf/from-html. The matrix response advertises this path under compositions. (Citations render in the HTML step, so the composed PDF carries the formatted bibliography too.)
Billing
One price: $0.0003 per MB of input (cputools.doc.convert, min 1 MiB). GET /v1/doc/formats is free. Charge-on-attempt — a conversion that can’t be delivered throws and the wrapper reverses the charge. Every billable call requires an Idempotency-Key; a same-key retry returns the cached result without re-charging.
MCP tools
Callable over MCP at https://api.relaystation.ai/mcp: doc_convert (billable) and doc_formats (free, read-only). Same auth, same prices as the HTTP routes.
Next
Quickstart · Authentication · x402 wire format · Media · API reference · PDF + Office tools at cputools.relaystation.ai