Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Multipart mode

POST /render with Content-Type: multipart/form-data.

Fields

FieldRequiredRepeatablePurpose
templateyesnoThe entry-point .typ source. Filename becomes the in-bundle path.
inputsnonoJSON document. Exposed to the template as sys.inputs.data (stringified).
assetsnoyesAny additional file (image, .typ for imports, data file). Filename = path.

Response

  • 200 — body is the compiled PDF, Content-Type: application/pdf.
  • 400 — malformed request: missing template, invalid inputs JSON, unknown field, etc.
  • 422 — compile error. Body is the Typst diagnostic.
  • 408 — compile took longer than the configured timeout. The worker was killed.
  • 413 — multipart body or resulting PDF exceeded the configured size limit.
  • 503 — server at its concurrent-compile limit. Retry later.

Reading inputs in the template

The inputs field is stringified and exposed as sys.inputs.data. Decode it once at the top of the template:

#let d = json.decode(sys.inputs.data)

= Invoice for #d.customer

#table(
  columns: 2,
  ..for line in d.line_items {
    (line.description, str(line.amount))
  }
)

This single-key contract keeps the protocol simple: arbitrary JSON in, arbitrary structure available in the template.

Imports across multiple files

Send each additional .typ file as an assets field. The filename becomes the path used in #import:

curl -sS -o out.pdf \
  -X POST https://typst.floomatik.com/render \
  -F "template=@main.typ" \
  -F "assets=@components/header.typ;filename=header.typ" \
  -F "assets=@components/footer.typ;filename=footer.typ"
// main.typ
#import "header.typ": page_header
#import "footer.typ": page_footer

#page_header()
= Body content
#page_footer()

Images

Same mechanism. Send each image as an assets field; reference by filename in image():

curl -sS -o report.pdf \
  -X POST https://typst.floomatik.com/render \
  -F "template=@report.typ" \
  -F "assets=@brand/logo.png" \
  -F "assets=@charts/q4.svg"
#image("logo.png", width: 40%)
== Q4 Results
#image("q4.svg")

SVG and PNG are both supported (Typst handles raster and vector). Asset bytes go through verbatim — no transcoding.

Error responses are plain text

A 422 from a broken template looks like:

compile failed: unknown variable: name

Suitable for logging or surfacing back to a UI.