Foliant

Templates / Delivery note

Delivery note

Packing list with quantities, article numbers and a receipt signature. Lands in the parcel or gets emailed with the tracking number.

1 page, A4. Rendered in 56 ms. 10 inputs, all optional.

Download .typ Open preview

Rendered Delivery note template, first page
First page, rendered from the source below with the sample inputs.

Inputs

Everything variable comes in through sys.inputs. Missing keys fall back to sensible defaults, so an agent can send only what it knows.

KeySample value
carrierDHL, 00340434161234567
customerNorthwind Traders
date2026-09-28
items
JSON, 229 chars
[
  {
    "sku": "MS-1001",
    "name": "Desk lamp, matte black",
    "ordered": "12",
    "shipped": "12"
  },
  {
    "sku": "MS-2043",
    "name": "Cable tray 120 cm",
    "ordered": "20",
    "shipped": "18"
  },
  {
    "sku": "MS-3300",
    "name": "Monitor arm, dual",
    "ordered": "6",
    "shipped": "6"
  }
]
logologo.png
noDN-88213
note2 cable trays follow next week (backorder).
orderSO-4471
senderMeridian Warehouse
ship_toNorthwind Traders, Receiving, Kastanienallee 7, 10435 Berlin

Render it

After copying the template into your account:

curl -X POST https://api.foliant.dev/v1/render \
  -H "Authorization: Bearer $FOLIANT_API_KEY" \
  -H "Content-Type: application/json" \
  -o delivery-note.pdf -d @- <<'JSON'
{ "template": "delivery-note.typ",
  "inputs": {
    "carrier": "DHL, 00340434161234567",
    "customer": "Northwind Traders",
    "date": "2026-09-28",
    "items": "[{\"sku\":\"MS-1001\",\"name\":\"Desk lamp, matte black\",\"ordered\":\"12\",\"shipped\":\"12\"},{\"sku\":\"MS-2043\",\"name\":\"Cable tray 120 cm\",\"ordered\":\"20\",\"shipped\":\"18\"},{\"sku\":\"MS-3300\",\"name\":\"Monitor arm, dual\",\"ordered\":\"6\",\"shipped\":\"6\"}]",
    "logo": "logo.png",
    "no": "DN-88213",
    "note": "2 cable trays follow next week (backorder).",
    "order": "SO-4471",
    "sender": "Meridian Warehouse",
    "ship_to": "Northwind Traders, Receiving, Kastanienallee 7, 10435 Berlin"
  } }
JSON

Through MCP, render_document with template: "delivery-note.typ" and the same inputs; get_template or fetch lists the keys.

Source

template.typ, 25 lines
#let input(k, default: "") = sys.inputs.at(k, default: default)
#let items = json(bytes(input("items", default: "[]")))
#let logo = input("logo")
#set page(paper: "a4", margin: 20mm)
#set text(font: "Noto Sans", size: 10pt, fill: rgb("1a1917"))
#grid(columns: (1fr, auto), align: (left, right),
  if logo != "" { image(logo, width: 36mm) } else { text(size: 15pt, weight: 700)[#input("sender")] },
  [#text(size: 18pt, weight: 700)[Delivery note] \ #text(fill: luma(110))[#input("no")]])
#v(8mm)
#grid(columns: (1fr, 1fr, 1fr), gutter: 8mm,
  [#text(size: 8pt, fill: luma(110))[SHIP TO] \ #input("ship_to")],
  [#text(size: 8pt, fill: luma(110))[ORDER] \ #input("order") \ #text(size: 8pt, fill: luma(110))[DATE] \ #input("date")],
  [#text(size: 8pt, fill: luma(110))[CARRIER] \ #input("carrier")])
#v(8mm)
#table(columns: (auto, 1fr, auto, auto, auto), align: (left, left, right, right, center), inset: 7pt,
  stroke: (x, y) => if y == 0 { (bottom: 0.8pt) } else { (bottom: 0.3pt + luma(200)) },
  [*SKU*], [*Article*], [*Ordered*], [*Shipped*], [*Check*],
  ..items.map(i => (raw(i.sku), i.name, i.ordered, if i.shipped != i.ordered { text(fill: rgb("b8341c"))[#i.shipped] } else { i.shipped }, sym.square)).flatten())
#v(5mm)
#if input("note") != "" [#text(size: 9.5pt)[*Note:* #input("note")]]
#v(1fr)
#grid(columns: (1fr, 1fr), gutter: 20mm,
  [#line(length: 100%, stroke: 0.5pt) #text(size: 8.5pt, fill: luma(110))[Packed by, date]],
  [#line(length: 100%, stroke: 0.5pt) #text(size: 8.5pt, fill: luma(110))[Received in good order: name, date, signature]])