Skip to content

210 × 297 mm

Packing slips

E-commerce packing slip

An A4 packing slip for online orders: an order-number barcode, ship-to and order details, items with SKU, variant, quantity and tick boxes, a note for items shipping in another parcel, an optional gift message and returns steps written in Markdown.

A4 portraitLocale en-GBHTML + Jinja

Opens Dynamic Document API with this template preloaded in a free workspace.

Template language features

  • Loops
  • Conditionals
  • Filters
  • Date formatting
  • Barcode
  • Markdown
  • Repeating table headers

Filters such as format_currency and qrcode are described in the template language reference.

Variables

Derived from the sample data: 7 top-level fields, 30 paths in total. Send the same shape as data.

PathTypeExample
storeobject
store.namestring"Hollowmere Goods"
store.taglinestring"Homeware for slow mornings"
store.websitestring"hollowmere.example.com"
store.emailstring"hello@hollowmere.example.com"
store.returns_addressstring"Hollowmere Returns ⏎ Unit 9, Larkspur Trading …"
orderobject
order.numberstring"HM-104729"
order.placed_ondate"2026-09-12"
order.packed_ondate"2026-09-14"
order.shipping_methodstring"Tracked 48, no signature"
order.parcel_numbernumber1
order.parcel_countnumber2
order.is_giftbooleantrue
customerobject
customer.namestring"Tomasz Wrenley"
customer.emailstring"t.wrenley@example.net"
ship_toobject
ship_to.namestring"Mira Castellane"
ship_to.addressstring"Flat 3, 41 Carrow Terrace ⏎ Dundee DD2 1LX ⏎ U…"
gift_messageobject
gift_message.textstring"Happy housewarming, Mira! A few things for slo…"
gift_message.fromstring"Tomasz"
itemsarray<object> · 8
items[].skustring"HMG-MUG-OAT-35"
items[].namestring"Stoneware mug"
items[].variantstring"Oat glaze · 350 ml"
items[].quantitynumber4
items[].parcelnumber1
returns_instructionsstring"**Changed your mind?** Unused items can come b…"

Sample data

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

data.json
{
  "store": {
    "name": "Hollowmere Goods",
    "tagline": "Homeware for slow mornings",
    "website": "hollowmere.example.com",
    "email": "hello@hollowmere.example.com",
    "returns_address": "Hollowmere Returns\nUnit 9, Larkspur Trading Estate\nThetfield TF9 3QA\nUnited Kingdom"
  },
  "order": {
    "number": "HM-104729",
    "placed_on": "2026-09-12",
    "packed_on": "2026-09-14",
    "shipping_method": "Tracked 48, no signature",
    "parcel_number": 1,
    "parcel_count": 2,
    "is_gift": true
  },
  "customer": {
    "name": "Tomasz Wrenley",
    "email": "t.wrenley@example.net"
  },
  "ship_to": {
    "name": "Mira Castellane",
    "address": "Flat 3, 41 Carrow Terrace\nDundee DD2 1LX\nUnited Kingdom"
  },
  "gift_message": {
    "text": "Happy housewarming, Mira! A few things for slow Sunday breakfasts in the new flat.\nSee you at the end of the month.",
    "from": "Tomasz"
  },
  "items": [
    { "sku": "HMG-MUG-OAT-35", "name": "Stoneware mug", "variant": "Oat glaze · 350 ml", "quantity": 4, "parcel": 1 },
    { "sku": "HMG-BWL-SAL-18", "name": "Serving bowl", "variant": "Salt glaze · 18 cm", "quantity": 1, "parcel": 1 },
    { "sku": "HMG-LIN-NAP-SGE", "name": "Linen napkins, set of four", "variant": "Sage", "quantity": 2, "parcel": 1 },
    { "sku": "HMG-BRD-OLV-40", "name": "Olive wood serving board", "variant": "40 × 18 cm", "quantity": 1, "parcel": 1 },
    { "sku": "HMG-CAN-FIG-200", "name": "Soy wax candle", "variant": "Fig leaf · 200 g", "quantity": 2, "parcel": 1 },
    { "sku": "HMG-TWL-HRB-NAT", "name": "Waffle tea towel", "variant": "Herringbone · natural", "quantity": 3, "parcel": 1 },
    { "sku": "HMG-JAR-HNY-250", "name": "Glass honey jar with dipper", "variant": "250 ml", "quantity": 1, "parcel": 1 },
    { "sku": "HMG-PLT-SPK-22", "name": "Speckled side plate", "variant": "Charcoal · 22 cm", "quantity": 4, "parcel": 2 }
  ],
  "returns_instructions": "**Changed your mind?** Unused items can come back within 30 days of delivery, in their original packaging.\n\n1. Go to **hollowmere.example.com/returns** and enter your order number and delivery postcode.\n2. Choose a drop-off point or book a collection. We email you a prepaid label.\n3. Pack the items securely, attach the label and keep your proof of postage.\n\nRefunds go back to the original payment method within five working days of the parcel reaching us. Gift recipients receive store credit instead."
}

Source

The body markup with Jinja, the stylesheet placed in <head>.

{#- Online-store packing slip. Lists the whole order and marks items that travel in another parcel. -#}
{%- set locale = "en-GB" -%}
{%- set this_parcel = order.parcel_number -%}
{%- set parcel_items = items | selectattr("parcel", "eq", this_parcel) | list -%}
{%- set units_here = parcel_items | sum_by("quantity") | int -%}
{%- set units_total = items | sum_by("quantity") | int -%}

<header class="masthead">
  <div class="brand">
    <svg class="logo" viewBox="0 0 40 40" aria-hidden="true">
      <circle cx="20" cy="20" r="19" fill="#b0532c"/>
      <path d="M20 31.5V11" stroke="#f4ede3" stroke-width="1.8" stroke-linecap="round"/>
      <path d="M20 17.5c-4.2-.6-6.6-3.4-6.8-7.2 4.2.2 6.6 3 6.8 7.2zM20 22.5c4.2-.6 6.6-3.4 6.8-7.2-4.2.2-6.6 3-6.8 7.2zM20 27.5c-4.2-.6-6.6-3.4-6.8-7.2 4.2.2 6.6 3 6.8 7.2z" fill="#f4ede3"/>
    </svg>
    <div>
      <div class="brand-name">{{ store.name }}</div>
      <div class="brand-tagline">{{ store.tagline }}</div>
    </div>
  </div>
  <div class="doc">
    <h1>Packing slip</h1>
    <div class="barcode">{{ order.number | barcode("code128", alt="Barcode " ~ order.number) }}</div>
    <div class="doc-number">Order {{ order.number }}</div>
  </div>
</header>

<section class="info">
  <div>
    <p class="label">Ship to</p>
    <p class="name">{{ ship_to.name }}</p>
    <p>{{ ship_to.address | nl2br }}</p>
  </div>
  <div>
    <p class="label">Order</p>
    <dl>
      <dt>Placed</dt><dd>{{ order.placed_on | format_date("long", locale) }}</dd>
      <dt>Packed</dt><dd>{{ order.packed_on | format_date("long", locale) }}</dd>
      <dt>Delivery</dt><dd>{{ order.shipping_method }}</dd>
      <dt>Parcel</dt><dd><strong>{{ this_parcel }} of {{ order.parcel_count }}</strong></dd>
    </dl>
  </div>
  <div>
    <p class="label">Ordered by</p>
    <p class="name">{{ customer.name }}</p>
    <p>{{ customer.email }}</p>
    {%- if order.is_gift %}
    <p class="gift-flag">
      <svg viewBox="0 0 16 16" aria-hidden="true"><path d="M2 6.5h12v2.5H2zM3 9h10v5.5H3z" fill="#b0532c"/><path d="M7.2 6.5h1.6v8H7.2z" fill="#f4ede3"/><path d="M8 6.5C6.6 3.6 3.9 3.8 4.3 5.5 4.6 6.6 8 6.5 8 6.5zm0 0c1.4-2.9 4.1-2.7 3.7-1C11.4 6.6 8 6.5 8 6.5z" fill="none" stroke="#b0532c" stroke-width="1.1"/></svg>
      Gift order · no prices enclosed
    </p>
    {%- endif %}
  </div>
</section>

{%- if order.is_gift and gift_message.text %}
<section class="gift">
  <p class="label">A message for {{ ship_to.name }}</p>
  <p class="gift-text">{{ gift_message.text | nl2br }}</p>
  <p class="gift-from">From {{ gift_message.from }}</p>
</section>
{%- endif %}

<table class="items">
  <thead>
    <tr>
      <th class="check" scope="col">Packed</th>
      <th scope="col">Item</th>
      <th scope="col">Variant</th>
      <th scope="col">SKU</th>
      <th class="qty" scope="col">Qty</th>
    </tr>
  </thead>
  <tbody>
    {%- for item in items %}
    {%- set elsewhere = item.parcel != this_parcel %}
    <tr{% if elsewhere %} class="elsewhere"{% endif %}>
      <td class="check"><span class="box" role="img" aria-label="Tick box"></span></td>
      <td>
        <span class="item-name">{{ item.name }}</span>
        {%- if elsewhere %}
        <span class="badge">Ships separately in parcel {{ item.parcel }} of {{ order.parcel_count }}</span>
        {%- endif %}
      </td>
      <td class="variant">{{ item.variant }}</td>
      <td class="sku">{{ item.sku }}</td>
      <td class="qty">{{ item.quantity }}</td>
    </tr>
    {%- endfor %}
  </tbody>
</table>

<p class="count">
  <strong>{{ units_here }} {{ "item" if units_here == 1 else "items" }} in this parcel</strong>
  · {{ units_total }} in the whole order
</p>

<section class="lower">
  <div class="returns">
    <h2>Returns</h2>
    {{ returns_instructions | markdown }}
  </div>
  <aside>
    <div class="initials">
      <div><span class="label">Packed by</span><span class="write"></span></div>
      <div><span class="label">Checked by</span><span class="write"></span></div>
    </div>
    <p class="label">Return address</p>
    <p class="address">{{ store.returns_address | nl2br }}</p>
  </aside>
</section>

<footer class="thanks">
  Thank you for shopping with {{ store.name }} · {{ store.website }} · {{ store.email }}
</footer>

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": {
    "store": {
      "name": "Hollowmere Goods",
      "tagline": "Homeware for slow mornings",
      "website": "hollowmere.example.com",
      "email": "hello@hollowmere.example.com",
      "returns_address": "Hollowmere Returns\nUnit 9, Larkspur Trading Estate\nThetfield TF9 3QA\nUnited Kingdom"
    },
    "order": {
      "number": "HM-104729",
      "placed_on": "2026-09-12",
      "packed_on": "2026-09-14",
      "shipping_method": "Tracked 48, no signature",
      "parcel_number": 1,
      "parcel_count": 2,
      "is_gift": true
    },
    "customer": {
      "name": "Tomasz Wrenley",
      "email": "t.wrenley@example.net"
    },
    "ship_to": {
      "name": "Mira Castellane",
      "address": "Flat 3, 41 Carrow Terrace\nDundee DD2 1LX\nUnited Kingdom"
    },
    "gift_message": {
      "text": "Happy housewarming, Mira! A few things for slow Sunday breakfasts in the new flat.\nSee you at the end of the month.",
      "from": "Tomasz"
    },
    "items": [
      {
        "sku": "HMG-MUG-OAT-35",
        "name": "Stoneware mug",
        "variant": "Oat glaze · 350 ml",
        "quantity": 4,
        "parcel": 1
      },
      {
        "sku": "HMG-BWL-SAL-18",
        "name": "Serving bowl",
        "variant": "Salt glaze · 18 cm",
        "quantity": 1,
        "parcel": 1
      }
    ],
    "returns_instructions": "**Changed your mind?** Unused items can come back within 30 days of delivery, in their original packaging.\n\n1. Go to **hollowmere.example.com/returns** and enter your order number and delivery postcode.\n2. Choose a drop-off point or book a collection. We email you a prepaid label.\n3. Pack the items securely, attach the label and keep your proof of postage.\n\nRefunds go back to the original payment method within five working days of the parcel reaching us. Gift recipients receive store credit instead."
  },
  "output": {
    "format": "pdf",
    "filename": "packing-slip-ecommerce.pdf"
  }
}'