Skip to content

210 × 148 mm

Delivery notes

Proof of delivery form

An A5 landscape proof-of-delivery form for courier stops: route and stop number, consignee and delivery window, a parcel list with a Code 128 barcode per parcel, condition tick boxes, recipient name, signature and time boxes, and driver notes.

A5 landscapeLocale en-IEHTML + Jinja

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

Template language features

  • Loops
  • Conditionals
  • Macros
  • Filters
  • Number formatting
  • Date formatting
  • Barcode

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

Variables

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

PathTypeExample
carrierobject
carrier.namestring"Brannock Couriers"
carrier.depotstring"Galway depot"
carrier.support_emailstring"pod@brannock.example.com"
runobject
run.routestring"G-14"
run.stop_numbernumber7
run.stops_totalnumber22
run.vehiclestring"Van 08"
run.driverstring"Aoife Brennan-Kelleher"
run.window_startdate"2026-09-17T10:00:00+01:00"
run.window_enddate"2026-09-17T12:00:00+01:00"
run.timezonestring"Europe/Dublin"
shipperobject
shipper.namestring"Cairnfield Kitchen Supply Ltd"
shipper.referencestring"CKS-SO-30917"
consigneeobject
consignee.namestring"Lough Arrow Bakehouse"
consignee.contactstring"Niamh Costigan"
consignee.addressstring"Unit 4, Cloonfad Business Park ⏎ Dublin Road ⏎…"
delivery_instructionsstring"Use the rear loading door. Ring twice; if nobo…"
parcelsarray<object> · 4
parcels[].trackingstring"BRC0917G1400701"
parcels[].descriptionstring"Stainless mixing bowls, set of 5"
parcels[].weight_kgnumber6.4
parcels[].handlingstring"Fragile"
conditionsarray<string> · 4"All parcels received"

Sample data

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

data.json
{
  "carrier": {
    "name": "Brannock Couriers",
    "depot": "Galway depot",
    "support_email": "pod@brannock.example.com"
  },
  "run": {
    "route": "G-14",
    "stop_number": 7,
    "stops_total": 22,
    "vehicle": "Van 08",
    "driver": "Aoife Brennan-Kelleher",
    "window_start": "2026-09-17T10:00:00+01:00",
    "window_end": "2026-09-17T12:00:00+01:00",
    "timezone": "Europe/Dublin"
  },
  "shipper": {
    "name": "Cairnfield Kitchen Supply Ltd",
    "reference": "CKS-SO-30917"
  },
  "consignee": {
    "name": "Lough Arrow Bakehouse",
    "contact": "Niamh Costigan",
    "address": "Unit 4, Cloonfad Business Park\nDublin Road\nTuam, Co. Galway"
  },
  "delivery_instructions": "Use the rear loading door. Ring twice; if nobody answers, knock at the bakery window.",
  "parcels": [
    { "tracking": "BRC0917G1400701", "description": "Stainless mixing bowls, set of 5", "weight_kg": 6.4, "handling": null },
    { "tracking": "BRC0917G1400702", "description": "Proving baskets, 12 pieces", "weight_kg": 3.1, "handling": null },
    { "tracking": "BRC0917G1400703", "description": "Digital kitchen scales, 2 units", "weight_kg": 4.8, "handling": "Fragile" },
    { "tracking": "BRC0917G1400704", "description": "Baking trays, 600 × 400 mm, 10 pieces", "weight_kg": 11.2, "handling": "Heavy" }
  ],
  "conditions": [
    "All parcels received",
    "Packaging undamaged",
    "Damage or shortage, see notes",
    "Left in agreed safe place"
  ]
}

Source

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

{#- Proof of delivery form (A5 landscape): stop details and parcel barcodes on the left, recipient sign-off on the right. -#}
{%- set locale = "en-IE" -%}
{%- set tz = run.timezone | default("Europe/Dublin") -%}
{%- set total_weight = parcels | sum_by("weight_kg") -%}

{%- macro digit_boxes(count) -%}
{%- for _ in range(count) %}<span class="digit"></span>{% endfor -%}
{%- endmacro %}

<article class="pod">
  <header class="bar">
    <div class="brand">
      <svg class="logo" viewBox="0 0 32 32" aria-hidden="true">
        <rect width="32" height="32" rx="7" fill="#a61e4d"/>
        <path d="M7 12l9-5 9 5v9l-9 5-9-5z" fill="none" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"/>
        <path d="M7 12l9 5 9-5M16 17v9" fill="none" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"/>
      </svg>
      <div>
        <p class="brand-name">{{ carrier.name }}</p>
        <p class="brand-meta">{{ carrier.depot }}</p>
      </div>
    </div>
    <h1>Proof of delivery</h1>
    <div class="stop">
      <span class="stop-label">Route {{ run.route }} · Stop</span>
      <span class="stop-number">{{ run.stop_number }}<small>/{{ run.stops_total }}</small></span>
    </div>
  </header>

  <div class="columns">
    <section class="left">
      <div class="details">
        <div class="consignee">
          <p class="label">Deliver to</p>
          <p class="strong">{{ consignee.name }}</p>
          <p>{{ consignee.address | nl2br }}</p>
          <p class="muted">Contact: {{ consignee.contact }}</p>
        </div>
        <dl class="facts">
          <dt>Date</dt><dd>{{ run.window_start | format_date("%a %d %b %Y", locale, tz) }}</dd>
          <dt>Window</dt><dd>{{ run.window_start | format_date("%H:%M", locale, tz) }}–{{ run.window_end | format_date("%H:%M", locale, tz) }}</dd>
          <dt>Shipper</dt><dd>{{ shipper.name }}</dd>
          <dt>Reference</dt><dd>{{ shipper.reference }}</dd>
          <dt>Driver</dt><dd>{{ run.driver }} · {{ run.vehicle }}</dd>
        </dl>
      </div>

      <div class="parcels">
        <p class="label">Parcels <span class="count">{{ parcels | length }} parcels · {{ total_weight | format_number(locale, 1) }} kg</span></p>
        <ol>
          {%- for parcel in parcels %}
          <li>
            <span class="seq">{{ loop.index }}/{{ loop.length }}</span>
            <span class="code">{{ parcel.tracking | barcode("code128", alt="Barcode " ~ parcel.tracking) }}</span>
            <span class="parcel-text">
              <span class="tracking">{{ parcel.tracking }}</span>
              <span>{{ parcel.description }}</span>
              <span class="weight">{{ parcel.weight_kg | format_number(locale, 1) }} kg{% if parcel.handling %} <b class="handling">{{ parcel.handling }}</b>{% endif %}</span>
            </span>
          </li>
          {%- endfor %}
        </ol>
      </div>
    </section>

    <section class="right">
      <div class="conditions">
        <p class="label">Condition on arrival</p>
        <ul>
          {%- for condition in conditions %}
          <li><span class="box"></span>{{ condition }}</li>
          {%- endfor %}
        </ul>
      </div>

      <div class="recipient">
        <p class="label">Recipient</p>
        <div class="field"><span>Name in capitals</span></div>
        <div class="field signature"><span>Signature</span></div>
        <div class="when">
          <div class="time"><span class="t-label">Time</span>{{ digit_boxes(2) }}<b>:</b>{{ digit_boxes(2) }}</div>
          <div class="field short"><span>Parcels received</span></div>
        </div>
      </div>

      <div class="notes">
        <p class="label">Driver notes</p>
        <p class="instructions">{{ delivery_instructions }}</p>
        <span class="rule"></span>
        <span class="rule"></span>
      </div>
    </section>
  </div>

  <footer class="foot">Keep this copy with the delivery paperwork. Queries: {{ carrier.support_email }}, quoting route {{ run.route }}, stop {{ run.stop_number }}.</footer>
</article>

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": {
    "carrier": {
      "name": "Brannock Couriers",
      "depot": "Galway depot",
      "support_email": "pod@brannock.example.com"
    },
    "run": {
      "route": "G-14",
      "stop_number": 7,
      "stops_total": 22,
      "vehicle": "Van 08",
      "driver": "Aoife Brennan-Kelleher",
      "window_start": "2026-09-17T10:00:00+01:00",
      "window_end": "2026-09-17T12:00:00+01:00",
      "timezone": "Europe/Dublin"
    },
    "shipper": {
      "name": "Cairnfield Kitchen Supply Ltd",
      "reference": "CKS-SO-30917"
    },
    "consignee": {
      "name": "Lough Arrow Bakehouse",
      "contact": "Niamh Costigan",
      "address": "Unit 4, Cloonfad Business Park\nDublin Road\nTuam, Co. Galway"
    },
    "delivery_instructions": "Use the rear loading door. Ring twice; if nobody answers, knock at the bakery window.",
    "parcels": [
      {
        "tracking": "BRC0917G1400701",
        "description": "Stainless mixing bowls, set of 5",
        "weight_kg": 6.4,
        "handling": null
      },
      {
        "tracking": "BRC0917G1400702",
        "description": "Proving baskets, 12 pieces",
        "weight_kg": 3.1,
        "handling": null
      }
    ],
    "conditions": [
      "All parcels received",
      "Packaging undamaged"
    ]
  },
  "output": {
    "format": "pdf",
    "filename": "delivery-note-proof-of-delivery.pdf"
  }
}'