Skip to content

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.

A4 landscapeLocale en-USHTML + JinjaHeader & footer

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.

PathTypeExample
warehouseobject
warehouse.namestring"Granite Loop Supply Co."
warehouse.sitestring"Sparks Distribution Center"
warehouse.site_codestring"SDC-2"
pick_ticketobject
pick_ticket.numberstring"PK-2026-091733"
pick_ticket.wavestring"W-0917-03"
pick_ticket.created_atdate"2026-09-17T06:40:00-07:00"
pick_ticket.timezonestring"America/Los_Angeles"
pick_ticket.prioritystring"Rush"
pick_ticket.dock_doorstring"D-07"
pick_ticket.ship_bydate"2026-09-18"
pick_ticket.carrierstring"Summit Freight Lines (LTL)"
pick_ticket.estimated_cartonsnumber12
pick_ticket.estimated_palletsnumber2
orderobject
order.numberstring"SO-448120"
order.customer_postring"JRG-77215"
order.customerstring"Juniper Row Grocers"
order.ship_tostring"Juniper Row Grocers #14 ⏎ Receiving dock, 2150…"
order.instructionsstring"Build heavy cases on the bottom layer. Chilled…"
itemsarray<object> · 18
items[].zonestring"C · Chilled room"
items[].binstring"C-02-1"
items[].skustring"GLS-30112"
items[].descriptionstring"Greek-style yogurt, plain"
items[].packstring"6 × 500 g"
items[].uomstring"case"
items[].qtynumber12
items[].case_weight_lbnumber7.4
items[].weight_lbnumber88.8
items[].flagstring"Chilled 34–40 °F"

Sample data

Fictional records used for previews. Replace them with your own data when you call the API.

data.json
{
  "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>

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"
  }
}'