297 × 210 mm
Packing slips
Wholesale pick list
A landscape A4 warehouse pick list: lines sorted by bin and grouped by zone with unit and weight subtotals, handling flags, picked and checked tick boxes, a carton count and weight log, picker and checker sign-off boxes and page numbers.
Opens Dynamic Document API with this template preloaded in a free workspace.
Template language features
- Loops
- Conditionals
- Macros
- Filters
- Number formatting
- Date formatting
- Barcode
- Grouping
- Repeating table headers
- Header & footer
- Page numbers
Filters such as format_currency and qrcode are described in the template language reference.
Variables
Derived from the sample data: 4 top-level fields, 32 paths in total. Send the same shape as data.
| Path | Type | Example |
|---|---|---|
| warehouse | object | |
| warehouse.name | string | "Granite Loop Supply Co." |
| warehouse.site | string | "Sparks Distribution Center" |
| warehouse.site_code | string | "SDC-2" |
| pick_ticket | object | |
| pick_ticket.number | string | "PK-2026-091733" |
| pick_ticket.wave | string | "W-0917-03" |
| pick_ticket.created_at | date | "2026-09-17T06:40:00-07:00" |
| pick_ticket.timezone | string | "America/Los_Angeles" |
| pick_ticket.priority | string | "Rush" |
| pick_ticket.dock_door | string | "D-07" |
| pick_ticket.ship_by | date | "2026-09-18" |
| pick_ticket.carrier | string | "Summit Freight Lines (LTL)" |
| pick_ticket.estimated_cartons | number | 12 |
| pick_ticket.estimated_pallets | number | 2 |
| order | object | |
| order.number | string | "SO-448120" |
| order.customer_po | string | "JRG-77215" |
| order.customer | string | "Juniper Row Grocers" |
| order.ship_to | string | "Juniper Row Grocers #14 ⏎ Receiving dock, 2150…" |
| order.instructions | string | "Build heavy cases on the bottom layer. Chilled…" |
| items | array<object> · 18 | |
| items[].zone | string | "C · Chilled room" |
| items[].bin | string | "C-02-1" |
| items[].sku | string | "GLS-30112" |
| items[].description | string | "Greek-style yogurt, plain" |
| items[].pack | string | "6 × 500 g" |
| items[].uom | string | "case" |
| items[].qty | number | 12 |
| items[].case_weight_lb | number | 7.4 |
| items[].weight_lb | number | 88.8 |
| items[].flag | string | "Chilled 34–40 °F" |
Sample data
Fictional records used for previews. Replace them with your own data when you call the API.
{
"warehouse": {
"name": "Granite Loop Supply Co.",
"site": "Sparks Distribution Center",
"site_code": "SDC-2"
},
"pick_ticket": {
"number": "PK-2026-091733",
"wave": "W-0917-03",
"created_at": "2026-09-17T06:40:00-07:00",
"timezone": "America/Los_Angeles",
"priority": "Rush",
"dock_door": "D-07",
"ship_by": "2026-09-18",
"carrier": "Summit Freight Lines (LTL)",
"estimated_cartons": 12,
"estimated_pallets": 2
},
"order": {
"number": "SO-448120",
"customer_po": "JRG-77215",
"customer": "Juniper Row Grocers",
"ship_to": "Juniper Row Grocers #14\nReceiving dock, 2150 Alder Creek Pkwy\nBoise, ID 83709",
"instructions": "Build heavy cases on the bottom layer. Chilled lines go into insulated liners and are loaded last, at the trailer doors."
},
"items": [
{ "zone": "C · Chilled room", "bin": "C-02-1", "sku": "GLS-30112", "description": "Greek-style yogurt, plain", "pack": "6 × 500 g", "uom": "case", "qty": 12, "case_weight_lb": 7.4, "weight_lb": 88.8, "flag": "Chilled 34–40 °F" },
{ "zone": "A · Ambient racking", "bin": "A-04-2C", "sku": "GLS-10671", "description": "Chickpeas in water, canned", "pack": "12 × 400 g", "uom": "case", "qty": 10, "case_weight_lb": 12.4, "weight_lb": 124.0, "flag": null },
{ "zone": "B · Bulk floor", "bin": "B-03", "sku": "GLS-20217", "description": "Spring water, still", "pack": "24 × 500 ml", "uom": "case", "qty": 20, "case_weight_lb": 27.6, "weight_lb": 552.0, "flag": "Heavy · team lift" },
{ "zone": "A · Ambient racking", "bin": "A-02-3B", "sku": "GLS-10442", "description": "Rolled oats, organic", "pack": "6 × 1 kg", "uom": "case", "qty": 8, "case_weight_lb": 13.8, "weight_lb": 110.4, "flag": null },
{ "zone": "M · Mezzanine small parts", "bin": "M-15-B", "sku": "GLS-40206", "description": "Nitrile gloves, size L", "pack": "10 × 100", "uom": "case", "qty": 2, "case_weight_lb": 9.9, "weight_lb": 19.8, "flag": null },
{ "zone": "A · Ambient racking", "bin": "A-07-1B", "sku": "GLS-11025", "description": "Olive oil, extra virgin", "pack": "6 × 750 ml", "uom": "case", "qty": 5, "case_weight_lb": 13.2, "weight_lb": 66.0, "flag": "Glass · keep upright" },
{ "zone": "C · Chilled room", "bin": "C-05-2", "sku": "GLS-30281", "description": "Oat drink, barista style", "pack": "6 × 1 l", "uom": "case", "qty": 9, "case_weight_lb": 14.2, "weight_lb": 127.8, "flag": "Chilled 34–40 °F" },
{ "zone": "A · Ambient racking", "bin": "A-11-2B", "sku": "GLS-11388", "description": "Ground coffee, medium roast", "pack": "8 × 340 g", "uom": "case", "qty": 6, "case_weight_lb": 7.1, "weight_lb": 42.6, "flag": null },
{ "zone": "B · Bulk floor", "bin": "B-01", "sku": "GLS-20104", "description": "Paper towel rolls, 2-ply", "pack": "30 rolls", "uom": "bale", "qty": 3, "case_weight_lb": 19.5, "weight_lb": 58.5, "flag": null },
{ "zone": "M · Mezzanine small parts", "bin": "M-12-A", "sku": "GLS-40033", "description": "Reusable produce bags", "pack": "50 bags", "uom": "pack", "qty": 2, "case_weight_lb": 1.8, "weight_lb": 3.6, "flag": null },
{ "zone": "A · Ambient racking", "bin": "A-04-1A", "sku": "GLS-10518", "description": "Basmati rice", "pack": "4 × 2 kg", "uom": "case", "qty": 6, "case_weight_lb": 18.6, "weight_lb": 111.6, "flag": null },
{ "zone": "C · Chilled room", "bin": "C-02-3", "sku": "GLS-30145", "description": "Unsalted butter", "pack": "20 × 250 g", "uom": "case", "qty": 4, "case_weight_lb": 11.5, "weight_lb": 46.0, "flag": "Chilled 34–40 °F" },
{ "zone": "B · Bulk floor", "bin": "B-05", "sku": "GLS-20390", "description": "Laundry detergent, unscented", "pack": "4 × 3 l", "uom": "case", "qty": 4, "case_weight_lb": 28.9, "weight_lb": 115.6, "flag": "Heavy · team lift" },
{ "zone": "A · Ambient racking", "bin": "A-09-4A", "sku": "GLS-11210", "description": "Dark chocolate bars, 70%", "pack": "20 × 100 g", "uom": "case", "qty": 4, "case_weight_lb": 5.3, "weight_lb": 21.2, "flag": null },
{ "zone": "M · Mezzanine small parts", "bin": "M-18-A", "sku": "GLS-40341", "description": "Thermal receipt rolls, 80 mm", "pack": "20 rolls", "uom": "box", "qty": 5, "case_weight_lb": 6.4, "weight_lb": 32.0, "flag": null },
{ "zone": "C · Chilled room", "bin": "C-06-1", "sku": "GLS-30307", "description": "Hummus, classic", "pack": "8 × 200 g", "uom": "case", "qty": 6, "case_weight_lb": 4.1, "weight_lb": 24.6, "flag": "Chilled 34–40 °F" },
{ "zone": "A · Ambient racking", "bin": "A-12-1C", "sku": "GLS-11470", "description": "Sea salt flakes", "pack": "12 × 250 g", "uom": "case", "qty": 3, "case_weight_lb": 7.3, "weight_lb": 21.9, "flag": null },
{ "zone": "M · Mezzanine small parts", "bin": "M-14-C", "sku": "GLS-40118", "description": "Price gun labels", "pack": "10 rolls", "uom": "box", "qty": 3, "case_weight_lb": 2.2, "weight_lb": 6.6, "flag": null }
]
}Source
The body markup with Jinja, the stylesheet placed in <head> and the header and footer settings.
{#- Warehouse pick list: lines sorted by bin, then grouped by zone so pickers walk each zone once. -#}
{%- set locale = "en-US" -%}
{%- set tz = pick_ticket.timezone | default("UTC") -%}
{%- set sorted_items = items | sort(attribute="bin") -%}
{%- set total_units = items | sum_by("qty") | int -%}
{%- set total_weight = items | sum_by("weight_lb") -%}
{%- set is_rush = pick_ticket.priority | lower == "rush" -%}
{%- macro signoff(role) -%}
<div class="signoff">
<p class="signoff-title">{{ role }}</p>
<div class="fields">
<div class="field wide"><span>Name</span></div>
<div class="field"><span>Start</span></div>
<div class="field"><span>Finish</span></div>
<div class="field wide tall"><span>Signature</span></div>
<div class="field"><span>Shorts</span></div>
<div class="field"><span>Date</span></div>
</div>
</div>
{%- endmacro %}
<header class="head">
<div class="title-block">
<p class="site">{{ warehouse.name }} · {{ warehouse.site }} ({{ warehouse.site_code }})</p>
<h1>Pick list</h1>
<div class="ticket-code">
{{ pick_ticket.number | barcode("code128", alt="Barcode " ~ pick_ticket.number) }}
</div>
</div>
<dl class="panel">
<div><dt>Sales order</dt><dd class="mono">{{ order.number }}</dd></div>
<div><dt>Customer PO</dt><dd class="mono">{{ order.customer_po }}</dd></div>
<div class="span"><dt>Ship to</dt><dd>{{ order.ship_to | nl2br }}</dd></div>
</dl>
<dl class="panel">
<div><dt>Wave</dt><dd class="mono">{{ pick_ticket.wave }}</dd></div>
<div><dt>Priority</dt><dd>{% if is_rush %}<span class="rush">{{ pick_ticket.priority }}</span>{% else %}{{ pick_ticket.priority }}{% endif %}</dd></div>
<div><dt>Dock door</dt><dd class="big">{{ pick_ticket.dock_door }}</dd></div>
<div><dt>Ship by</dt><dd class="big">{{ pick_ticket.ship_by | format_date("%a %b %d", locale) }}</dd></div>
<div class="span"><dt>Carrier</dt><dd>{{ pick_ticket.carrier }}</dd></div>
<div class="span"><dt>Released</dt><dd>{{ pick_ticket.created_at | format_date("%b %d, %Y at %H:%M", locale, tz) }}</dd></div>
</dl>
</header>
<section class="totals">
<div><span>Lines</span><strong>{{ items | length }}</strong></div>
<div><span>Units</span><strong>{{ total_units }}</strong></div>
<div><span>Est. weight</span><strong>{{ total_weight | format_number(locale, 1) }} lb</strong></div>
<div><span>Est. cartons</span><strong>{{ pick_ticket.estimated_cartons }}</strong></div>
<div><span>Pallets</span><strong>{{ pick_ticket.estimated_pallets }}</strong></div>
<p class="instructions"><b>Load notes</b> {{ order.instructions }}</p>
</section>
<table class="picks">
<thead>
<tr>
<th class="idx" scope="col">Seq</th>
<th class="bin" scope="col">Bin</th>
<th class="sku" scope="col">SKU</th>
<th scope="col">Description</th>
<th class="pack" scope="col">Pack</th>
<th class="num" scope="col">Qty</th>
<th class="uom" scope="col">UoM</th>
<th class="num wt" scope="col">Weight</th>
<th class="tick" scope="col">Picked</th>
<th class="tick" scope="col">Checked</th>
<th class="note" scope="col">Short / note</th>
</tr>
</thead>
{%- for zone in sorted_items | group_by("zone") %}
<tbody class="zone">
<tr class="zone-row">
<td colspan="11">
<span class="zone-name">{{ zone.grouper }}</span>
<span class="zone-meta">{{ zone.list | length }} {{ "line" if zone.list | length == 1 else "lines" }} · {{ zone.list | sum_by("qty") | int }} units · {{ zone.list | sum_by("weight_lb") | format_number(locale, 1) }} lb</span>
</td>
</tr>
{%- for item in zone.list %}
<tr>
<td class="idx">{{ loop.index }}</td>
<td class="bin mono">{{ item.bin }}</td>
<td class="sku mono">{{ item.sku }}</td>
<td>
{{ item.description }}
{%- if item.flag %} <span class="flag">{{ item.flag }}</span>{% endif %}
</td>
<td class="pack">{{ item.pack }}</td>
<td class="num qty">{{ item.qty }}</td>
<td class="uom">{{ item.uom }}</td>
<td class="num wt">{{ item.weight_lb | format_number(locale, 1) }}</td>
<td class="tick"><span class="box" role="img" aria-label="Checkbox"></span><span class="write"></span></td>
<td class="tick"><span class="box" role="img" aria-label="Checkbox"></span></td>
<td class="note"><span class="line"></span></td>
</tr>
{%- endfor %}
</tbody>
{%- endfor %}
</table>
<section class="closeout">
<div class="cartons">
<p class="section-title">Carton count</p>
<div class="carton-total">
<span class="count-box"></span>
<span class="count-label">cartons packed<br><small>estimate {{ pick_ticket.estimated_cartons }} · {{ pick_ticket.estimated_pallets }} {{ "pallet" if pick_ticket.estimated_pallets == 1 else "pallets" }}</small></span>
</div>
<p class="section-hint">Weight per carton (lb)</p>
<div class="carton-grid">
{%- for n in range(1, pick_ticket.estimated_cartons + 3) %}
<span class="carton"><span class="carton-no">{{ n }}</span></span>
{%- endfor %}
</div>
</div>
{{ signoff("Picker") }}
{{ signoff("Checker") }}
</section><title>Pick list {{ pick_ticket.number }} – order {{ order.number }}</title>
<style>
:root {
--ink: #1c1f23;
--muted: #5c636b;
--rule: #cfd4da;
--zebra: #f3f4f6;
--panel: #eef0f2;
--yellow: #ffd21f;
}
* { box-sizing: border-box; }
html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
body {
margin: 0;
color: var(--ink);
font-family: "DejaVu Sans", "Liberation Sans", Arial, sans-serif;
font-size: 8pt;
line-height: 1.35;
}
p, h1, dl, dd { margin: 0; }
.mono { font-family: "DejaVu Sans Mono", "Liberation Mono", monospace; }
/* Header */
.head { display: grid; grid-template-columns: 78mm 1fr 1.25fr; gap: 6mm; align-items: stretch; }
.title-block { padding: 3mm 0 0; border-top: 1.6mm solid var(--ink); }
.site { font-size: 7pt; color: var(--muted); }
.title-block h1 { margin: 1mm 0 2mm; font-size: 24pt; font-weight: 700; line-height: 1; letter-spacing: -0.02em; text-transform: uppercase; }
.ticket-code img, .ticket-code svg { display: block; width: 66mm; height: 12mm; }
.panel {
display: grid;
grid-template-columns: 1fr 1fr;
align-content: start;
gap: 2mm 4mm;
padding: 3mm 4mm;
border-top: 1.6mm solid var(--yellow);
background: var(--panel);
}
.panel .span { grid-column: span 2; }
.panel dt { font-size: 6pt; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.panel dd { font-size: 8.5pt; }
.panel dd.big { font-size: 12pt; font-weight: 700; line-height: 1.15; }
.rush {
display: inline-block;
padding: 0.2mm 2.4mm;
background: var(--ink);
color: var(--yellow);
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
}
/* Totals strip */
.totals {
display: flex;
align-items: stretch;
gap: 0;
margin: 4mm 0 3mm;
border: 0.35mm solid var(--ink);
}
.totals div { padding: 1.6mm 4mm; border-right: 0.25mm solid var(--rule); white-space: nowrap; }
.totals span { display: block; font-size: 6pt; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.totals strong { font-size: 11pt; }
.instructions { flex: 1; align-self: center; padding: 1mm 4mm; font-size: 7.4pt; line-height: 1.35; }
.instructions b { margin-right: 1.5mm; font-size: 6pt; letter-spacing: 0.08em; text-transform: uppercase; }
/* Pick table */
table.picks { width: 100%; border-collapse: collapse; }
table.picks thead { display: table-header-group; }
table.picks th {
padding: 1.8mm 1.6mm;
background: var(--ink);
color: #ffffff;
font-size: 6.4pt;
font-weight: 700;
letter-spacing: 0.06em;
text-align: left;
text-transform: uppercase;
}
table.picks td { padding: 1.7mm 1.6mm; border-bottom: 0.2mm solid var(--rule); vertical-align: middle; }
table.picks tr { break-inside: avoid; page-break-inside: avoid; }
/* Cells paint white inside their padding, so the tagged PDF keeps them in the table structure (PDF/UA)
without painting over the row edges; the zebra rows override it. */
.picks td { background: #ffffff content-box; }
table.picks tbody tr:nth-child(odd):not(.zone-row) td { background: var(--zebra); }
/* A zone's heading row stays with its first line: never alone at the bottom of a page. */
.zone-row { break-after: avoid; page-break-after: avoid; }
.zone-row td { padding: 2.6mm 1.6mm 1.4mm; border-bottom: 0.5mm solid var(--ink); background: #ffffff; }
.zone-name {
display: inline-block;
padding: 0.4mm 2.4mm;
background: var(--yellow);
font-size: 8.5pt;
font-weight: 700;
}
.zone-meta { margin-left: 3mm; font-size: 7pt; color: var(--muted); }
.idx { width: 9mm; color: var(--muted); }
th.bin, td.bin { width: 19mm; }
td.bin { font-size: 9pt; font-weight: 700; }
th.sku, td.sku { width: 21mm; }
td.sku { font-size: 7.4pt; }
th.pack, td.pack { width: 24mm; }
td.pack { color: var(--muted); }
.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
th.num { text-align: right; }
td.qty { width: 12mm; font-size: 11pt; font-weight: 700; }
th.uom, td.uom { width: 12mm; }
th.wt, td.wt { width: 17mm; }
th.tick, td.tick { width: 21mm; }
td.tick { white-space: nowrap; }
th.note, td.note { width: 34mm; }
.flag {
display: inline-block;
margin-left: 1mm;
padding: 0 1.4mm;
border: 0.25mm solid var(--ink);
font-size: 6pt;
font-weight: 700;
letter-spacing: 0.02em;
vertical-align: 0.2mm;
}
.box { display: inline-block; width: 4.4mm; height: 4.4mm; border: 0.35mm solid var(--ink); background: #ffffff; vertical-align: middle; }
.write { display: inline-block; width: 10mm; height: 4.4mm; margin-left: 1.5mm; border-bottom: 0.25mm solid var(--ink); vertical-align: middle; }
.line { display: block; height: 4.4mm; border-bottom: 0.25mm dotted var(--muted); }
/* Close-out: cartons and sign-off */
.closeout {
display: grid;
grid-template-columns: 1.1fr 1fr 1fr;
gap: 5mm;
margin-top: 6mm;
break-inside: avoid;
page-break-inside: avoid;
}
.section-title, .signoff-title { margin-bottom: 2mm; font-size: 7pt; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.cartons, .signoff { padding: 3mm 4mm 4mm; border: 0.35mm solid var(--ink); }
.carton-total { display: flex; align-items: center; gap: 3mm; }
.count-box { display: block; width: 18mm; height: 12mm; border: 0.5mm solid var(--ink); }
.count-label { font-size: 8.5pt; font-weight: 700; line-height: 1.25; }
.count-label small { font-size: 7pt; font-weight: 400; color: var(--muted); }
.section-hint { margin: 3mm 0 1.2mm; font-size: 6.4pt; color: var(--muted); }
.carton-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 1.2mm; }
.carton { position: relative; display: block; height: 7.5mm; border: 0.25mm solid var(--rule); }
.carton-no { position: absolute; top: 0.4mm; left: 0.8mm; font-size: 5.4pt; color: var(--muted); }
.fields { display: grid; grid-template-columns: 2fr 1fr 1fr; gap: 1.8mm; }
.field { position: relative; height: 9mm; border-bottom: 0.3mm solid var(--ink); }
.field.tall { height: 14mm; }
.field span { position: absolute; top: 0; left: 0; font-size: 6pt; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; color: var(--muted); }
</style>Render it with the API
After adding the template to your workspace, render it by ID and pass your data. Arrays are shortened here.
curl -X POST https://api-eu.dynamicdocumentapi.com/v1/renders \
-H "Authorization: Bearer $DYNAMIC_DOCUMENT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"input": {
"type": "template",
"template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C"
},
"data": {
"warehouse": {
"name": "Granite Loop Supply Co.",
"site": "Sparks Distribution Center",
"site_code": "SDC-2"
},
"pick_ticket": {
"number": "PK-2026-091733",
"wave": "W-0917-03",
"created_at": "2026-09-17T06:40:00-07:00",
"timezone": "America/Los_Angeles",
"priority": "Rush",
"dock_door": "D-07",
"ship_by": "2026-09-18",
"carrier": "Summit Freight Lines (LTL)",
"estimated_cartons": 12,
"estimated_pallets": 2
},
"order": {
"number": "SO-448120",
"customer_po": "JRG-77215",
"customer": "Juniper Row Grocers",
"ship_to": "Juniper Row Grocers #14\nReceiving dock, 2150 Alder Creek Pkwy\nBoise, ID 83709",
"instructions": "Build heavy cases on the bottom layer. Chilled lines go into insulated liners and are loaded last, at the trailer doors."
},
"items": [
{
"zone": "C · Chilled room",
"bin": "C-02-1",
"sku": "GLS-30112",
"description": "Greek-style yogurt, plain",
"pack": "6 × 500 g",
"uom": "case",
"qty": 12,
"case_weight_lb": 7.4,
"weight_lb": 88.8,
"flag": "Chilled 34–40 °F"
},
{
"zone": "A · Ambient racking",
"bin": "A-04-2C",
"sku": "GLS-10671",
"description": "Chickpeas in water, canned",
"pack": "12 × 400 g",
"uom": "case",
"qty": 10,
"case_weight_lb": 12.4,
"weight_lb": 124,
"flag": null
}
]
},
"output": {
"format": "pdf",
"filename": "packing-slip-wholesale-picklist.pdf"
}
}'const response = await fetch("https://api-eu.dynamicdocumentapi.com/v1/renders", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.DYNAMIC_DOCUMENT_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
"input": {
"type": "template",
"template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C"
},
"data": {
"warehouse": {
"name": "Granite Loop Supply Co.",
"site": "Sparks Distribution Center",
"site_code": "SDC-2"
},
"pick_ticket": {
"number": "PK-2026-091733",
"wave": "W-0917-03",
"created_at": "2026-09-17T06:40:00-07:00",
"timezone": "America/Los_Angeles",
"priority": "Rush",
"dock_door": "D-07",
"ship_by": "2026-09-18",
"carrier": "Summit Freight Lines (LTL)",
"estimated_cartons": 12,
"estimated_pallets": 2
},
"order": {
"number": "SO-448120",
"customer_po": "JRG-77215",
"customer": "Juniper Row Grocers",
"ship_to": "Juniper Row Grocers #14\nReceiving dock, 2150 Alder Creek Pkwy\nBoise, ID 83709",
"instructions": "Build heavy cases on the bottom layer. Chilled lines go into insulated liners and are loaded last, at the trailer doors."
},
"items": [
{
"zone": "C · Chilled room",
"bin": "C-02-1",
"sku": "GLS-30112",
"description": "Greek-style yogurt, plain",
"pack": "6 × 500 g",
"uom": "case",
"qty": 12,
"case_weight_lb": 7.4,
"weight_lb": 88.8,
"flag": "Chilled 34–40 °F"
},
{
"zone": "A · Ambient racking",
"bin": "A-04-2C",
"sku": "GLS-10671",
"description": "Chickpeas in water, canned",
"pack": "12 × 400 g",
"uom": "case",
"qty": 10,
"case_weight_lb": 12.4,
"weight_lb": 124,
"flag": null
}
]
},
"output": {
"format": "pdf",
"filename": "packing-slip-wholesale-picklist.pdf"
}
}),
});
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
const result = await response.json();
console.log(result);import os
import uuid
import requests
response = requests.post(
"https://api-eu.dynamicdocumentapi.com/v1/renders",
headers={
"Authorization": f"Bearer {os.environ['DYNAMIC_DOCUMENT_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"input": {
"type": "template",
"template_id": "tpl_01J9ZK3M7Q8V5W2X4Y6Z8A0B1C",
},
"data": {
"warehouse": {
"name": "Granite Loop Supply Co.",
"site": "Sparks Distribution Center",
"site_code": "SDC-2",
},
"pick_ticket": {
"number": "PK-2026-091733",
"wave": "W-0917-03",
"created_at": "2026-09-17T06:40:00-07:00",
"timezone": "America/Los_Angeles",
"priority": "Rush",
"dock_door": "D-07",
"ship_by": "2026-09-18",
"carrier": "Summit Freight Lines (LTL)",
"estimated_cartons": 12,
"estimated_pallets": 2,
},
"order": {
"number": "SO-448120",
"customer_po": "JRG-77215",
"customer": "Juniper Row Grocers",
"ship_to": "Juniper Row Grocers #14\nReceiving dock, 2150 Alder Creek Pkwy\nBoise, ID 83709",
"instructions": "Build heavy cases on the bottom layer. Chilled lines go into insulated liners and are loaded last, at the trailer doors.",
},
"items": [
{
"zone": "C · Chilled room",
"bin": "C-02-1",
"sku": "GLS-30112",
"description": "Greek-style yogurt, plain",
"pack": "6 × 500 g",
"uom": "case",
"qty": 12,
"case_weight_lb": 7.4,
"weight_lb": 88.8,
"flag": "Chilled 34–40 °F",
},
{
"zone": "A · Ambient racking",
"bin": "A-04-2C",
"sku": "GLS-10671",
"description": "Chickpeas in water, canned",
"pack": "12 × 400 g",
"uom": "case",
"qty": 10,
"case_weight_lb": 12.4,
"weight_lb": 124,
"flag": None,
},
],
},
"output": {
"format": "pdf",
"filename": "packing-slip-wholesale-picklist.pdf",
},
},
timeout=90,
)
response.raise_for_status()
print(response.json())