210 × 297 mm
Purchase orders
Standard purchase order
An A4 purchase order with buyer, supplier and delivery addresses, a required-by date calculated from the lead time, numbered order lines, subtotal, VAT and total derived from the lines, delivery instructions and an approval block that adds finance sign-off above a threshold.
Opens Dynamic Document API with this template preloaded in a free workspace.
Template language features
- Loops
- Conditionals
- Macros
- Filters
- Currency formatting
- Date formatting
- 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: 9 top-level fields, 44 paths in total. Send the same shape as data.
| Path | Type | Example |
|---|---|---|
| buyer | object | |
| buyer.name | string | "Stackyard Brewing Co. Ltd" |
| buyer.address | string | "The Maltings, 7 Stackyard Lane ⏎ Kendal LA9 4T…" |
| buyer.vat_id | string | "GB 318 2264 50" |
| buyer.invoice_email | string | "payables@stackyard.example.com" |
| buyer_contact | object | |
| buyer_contact.name | string | "Rhiannon Tuckett" |
| buyer_contact.role | string | "Procurement Lead" |
| buyer_contact.email | string | "rhiannon.tuckett@stackyard.example.com" |
| buyer_contact.phone | string | "+44 20 7946 0852" |
| supplier | object | |
| supplier.name | string | "Pellow & Grange Packaging Ltd" |
| supplier.account | string | "SUP-00412" |
| supplier.address | string | "Unit 14, Brindley Road Industrial Estate ⏎ War…" |
| supplier.email | string | "orders@pellowgrange.example.com" |
| deliver_to | object | |
| deliver_to.name | string | "Stackyard Brewing, Goods In" |
| deliver_to.address | string | "Bay 3, Kentmere Works, Quarry Row ⏎ Kendal LA9…" |
| deliver_to.hours | string | "Monday to Friday, 07:30–14:30" |
| deliver_to.contact | string | "Warehouse team, +44 20 7946 0853" |
| order | object | |
| order.number | string | "PO-SB-2026-0388" |
| order.date | date | "2026-09-15" |
| order.lead_time_days | number | 21 |
| order.supplier_quote | string | "Q-PG-11873" |
| order.payment_terms | string | "30 days from the end of the invoice month" |
| order.cost_centre | string | "OPS-PACK" |
| order.currency | string | "GBP" |
| order.vat_rate | number | 0.2 |
| lines | array<object> · 8 | |
| lines[].code | string | "PG-CAN-440-MB" |
| lines[].description | string | "Aluminium cans, 440 ml, matt black, unprinted" |
| lines[].unit | string | "pallet of 8,280" |
| lines[].quantity | number | 6 |
| lines[].unit_price | number | 812.4 |
| lines[].amount | number | 4874.4 |
| delivery_instructions | array<string> · 4 | "Book a delivery slot with the warehouse team a…" |
| conditions | string | "Quote the PO number on every delivery note and…" |
| approvals | array<object> · 3 | |
| approvals[].step | string | "Requested by" |
| approvals[].name | string | "Rhiannon Tuckett" |
| approvals[].role | string | "Procurement Lead" |
| approvals[].date | date | "2026-09-14" |
| approvals[].required_above | number | 5000 |
Sample data
Fictional records used for previews. Replace them with your own data when you call the API.
{
"buyer": {
"name": "Stackyard Brewing Co. Ltd",
"address": "The Maltings, 7 Stackyard Lane\nKendal LA9 4TR\nUnited Kingdom",
"vat_id": "GB 318 2264 50",
"invoice_email": "payables@stackyard.example.com"
},
"buyer_contact": {
"name": "Rhiannon Tuckett",
"role": "Procurement Lead",
"email": "rhiannon.tuckett@stackyard.example.com",
"phone": "+44 20 7946 0852"
},
"supplier": {
"name": "Pellow & Grange Packaging Ltd",
"account": "SUP-00412",
"address": "Unit 14, Brindley Road Industrial Estate\nWarrington WA2 8QZ\nUnited Kingdom",
"email": "orders@pellowgrange.example.com"
},
"deliver_to": {
"name": "Stackyard Brewing, Goods In",
"address": "Bay 3, Kentmere Works, Quarry Row\nKendal LA9 6QQ\nUnited Kingdom",
"hours": "Monday to Friday, 07:30–14:30",
"contact": "Warehouse team, +44 20 7946 0853"
},
"order": {
"number": "PO-SB-2026-0388",
"date": "2026-09-15",
"lead_time_days": 21,
"supplier_quote": "Q-PG-11873",
"payment_terms": "30 days from the end of the invoice month",
"cost_centre": "OPS-PACK",
"currency": "GBP",
"vat_rate": 0.2
},
"lines": [
{ "code": "PG-CAN-440-MB", "description": "Aluminium cans, 440 ml, matt black, unprinted", "unit": "pallet of 8,280", "quantity": 6, "unit_price": 812.4, "amount": 4874.4 },
{ "code": "PG-END-202-SL", "description": "Can ends, 202 diameter, silver", "unit": "box of 6,000", "quantity": 8, "unit_price": 96.0, "amount": 768.0 },
{ "code": "PG-CRT-4PK-PR", "description": "Four-pack paperboard carriers, printed two colours", "unit": "1,000 pieces", "quantity": 12, "unit_price": 64.5, "amount": 774.0 },
{ "code": "PG-SHP-24-KFT", "description": "Shipping cartons for 24 × 440 ml cans, kraft", "unit": "bundle of 250", "quantity": 10, "unit_price": 87.25, "amount": 872.5 },
{ "code": "PG-KEG-CLR-30", "description": "Keg collars, printed, for 30 l kegs", "unit": "pack of 500", "quantity": 4, "unit_price": 38.9, "amount": 155.6 },
{ "code": "PG-WRP-23-CL", "description": "Pallet stretch film, 23 µm, clear", "unit": "roll", "quantity": 24, "unit_price": 14.8, "amount": 355.2 },
{ "code": "PG-LBL-TE-60", "description": "Tamper-evident labels, 60 mm", "unit": "roll of 1,000", "quantity": 15, "unit_price": 11.6, "amount": 174.0 },
{ "code": "PG-ART-PROOF", "description": "Artwork proofing and print plate set-up for carriers", "unit": "job", "quantity": 1, "unit_price": 240.0, "amount": 240.0 }
],
"delivery_instructions": [
"Book a delivery slot with the warehouse team at least 48 hours in advance.",
"Deliver on standard 1,200 × 1,000 mm pallets, stretch-wrapped, no higher than 1.8 m.",
"Label each pallet with this PO number and the line numbers it contains.",
"Cans and ends must arrive sealed in food-grade packaging, with batch certificates."
],
"conditions": "Quote the PO number on every delivery note and invoice. Part deliveries only by prior agreement. All goods are inspected on arrival and may be returned if they do not match this order.",
"approvals": [
{ "step": "Requested by", "name": "Rhiannon Tuckett", "role": "Procurement Lead", "date": "2026-09-14", "required_above": null },
{ "step": "Budget holder", "name": "Callum Everingham", "role": "Head of Operations", "date": "2026-09-15", "required_above": null },
{ "step": "Finance approval", "name": "Priti Sandhu-Morrow", "role": "Finance Controller", "date": "2026-09-15", "required_above": 5000.0 }
]
}Source
The body markup with Jinja, the stylesheet placed in <head> and the header and footer settings.
{#- Standard purchase order. Subtotal, VAT and total come from the order lines; the required-by date from the lead time. -#}
{%- set locale = "en-GB" -%}
{%- set currency = order.currency -%}
{%- set subtotal = lines | sum_by("amount") -%}
{%- set vat = (subtotal * order.vat_rate) | round(2) -%}
{%- set total = subtotal + vat -%}
{%- set required_by = order.date | date_add(days=order.lead_time_days) -%}
{%- macro address_card(label, name, address, extra=none) -%}
<div class="card">
<p class="label">{{ label }}</p>
<p class="card-name">{{ name }}</p>
<p>{{ address | nl2br }}</p>
{%- if extra %}
<p class="card-extra">{{ extra }}</p>
{%- endif %}
</div>
{%- endmacro %}
<header class="masthead">
<div>
<p class="buyer-name">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 20V9l8-5 8 5v11" fill="none" stroke="#1d5b45" stroke-width="2.2" stroke-linejoin="round"/><path d="M8.5 20v-6h7v6M8.5 17h7" fill="none" stroke="#1d5b45" stroke-width="2.2"/></svg>
{{ buyer.name }}
</p>
<h1>Purchase order</h1>
</div>
<div class="po-box">
<span class="po-label">PO number</span>
<span class="po-number">{{ order.number }}</span>
<span class="po-date">Issued {{ order.date | format_date("long", locale) }}</span>
</div>
</header>
<section class="cards">
{{ address_card("Buyer", buyer.name, buyer.address, "VAT " ~ buyer.vat_id) }}
{{ address_card("Supplier", supplier.name, supplier.address, "Account " ~ supplier.account ~ " · " ~ supplier.email) }}
{{ address_card("Deliver to", deliver_to.name, deliver_to.address, deliver_to.hours) }}
</section>
<section class="meta">
<div><span>Required by</span><strong>{{ required_by | format_date("long", locale) }}</strong></div>
<div><span>Lead time</span><strong>{{ order.lead_time_days }} days</strong></div>
<div><span>Supplier quote</span><strong>{{ order.supplier_quote }}</strong></div>
<div><span>Cost centre</span><strong>{{ order.cost_centre }}</strong></div>
<div class="wide"><span>Payment terms</span><strong>{{ order.payment_terms }}</strong></div>
<div class="wide"><span>Buyer contact</span><strong>{{ buyer_contact.name }}, {{ buyer_contact.role }}</strong><em>{{ buyer_contact.email }} · {{ buyer_contact.phone }}</em></div>
</section>
<table class="lines">
<thead>
<tr>
<th class="ln" scope="col">Line</th>
<th class="code" scope="col">Item code</th>
<th scope="col">Description</th>
<th class="num" scope="col">Qty</th>
<th scope="col">Unit</th>
<th class="num" scope="col">Unit price</th>
<th class="num" scope="col">Amount</th>
</tr>
</thead>
<tbody>
{%- for line in lines %}
<tr>
<td class="ln">{{ "%02d" | format(loop.index) }}</td>
<td class="code">{{ line.code }}</td>
<td>{{ line.description }}</td>
<td class="num">{{ line.quantity }}</td>
<td class="unit">{{ line.unit }}</td>
<td class="num">{{ line.unit_price | format_currency(currency, locale) }}</td>
<td class="num">{{ line.amount | format_currency(currency, locale) }}</td>
</tr>
{%- endfor %}
</tbody>
</table>
<section class="totals-row">
<p class="conditions">{{ conditions }}</p>
<table class="totals">
<tr><th scope="row">Subtotal ({{ lines | length }} lines)</th><td class="num">{{ subtotal | format_currency(currency, locale) }}</td></tr>
<tr><th scope="row">VAT at {{ order.vat_rate | format_percent(locale) }}</th><td class="num">{{ vat | format_currency(currency, locale) }}</td></tr>
<tr class="grand"><th scope="row">Order total</th><td class="num">{{ total | format_currency(currency, locale) }}</td></tr>
</table>
</section>
<section class="lower">
<div class="instructions">
<h2>Delivery instructions</h2>
<ol>
{%- for step in delivery_instructions %}
<li>{{ step }}</li>
{%- endfor %}
</ol>
<p class="contact">On-site contact: {{ deliver_to.contact }}</p>
<p class="contact">Send invoices to {{ buyer.invoice_email }}, quoting {{ order.number }}.</p>
</div>
<div class="approvals">
<h2>Approval</h2>
{%- for approval in approvals %}
{%- if not approval.required_above or total > approval.required_above %}
<div class="approver">
<div class="who">
<span class="step">{{ approval.step }}</span>
<strong>{{ approval.name }}</strong>
<span class="role">{{ approval.role }}</span>
{%- if approval.required_above %}
<span class="rule">Needed for orders above {{ approval.required_above | format_currency(currency, locale) }}</span>
{%- endif %}
</div>
<div class="sig"><span>Signature</span></div>
<div class="when"><span>Date</span>{{ approval.date | format_date("%d/%m/%Y", locale) }}</div>
</div>
{%- endif %}
{%- endfor %}
</div>
</section><title>Purchase order {{ order.number }} – {{ supplier.name }}</title>
<style>
:root {
--ink: #17231e;
--muted: #5e6b65;
--rule: #dbe3df;
--forest: #1d5b45;
--mint: #eaf3ee;
}
* { box-sizing: border-box; }
html { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
body {
margin: 0;
color: var(--ink);
font-family: "Inter", "Liberation Sans", Arial, sans-serif;
font-size: 8.6pt;
line-height: 1.42;
}
p, h1, h2 { margin: 0; }
.num { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.label {
margin-bottom: 1.2mm;
font-size: 6.6pt;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--forest);
}
/* Masthead */
.masthead { display: flex; justify-content: space-between; align-items: flex-end; padding-bottom: 5mm; border-bottom: 0.8mm solid var(--forest); }
.buyer-name { display: flex; align-items: center; gap: 2mm; font-size: 9pt; font-weight: 600; color: var(--forest); }
.buyer-name svg { width: 5mm; height: 5mm; }
.masthead h1 { margin-top: 1.5mm; font-size: 28pt; font-weight: 800; line-height: 1; letter-spacing: -0.03em; }
.po-box { display: flex; flex-direction: column; align-items: flex-end; padding: 3mm 4.5mm; border-radius: 2mm; background: var(--forest); color: #ffffff; }
.po-label { font-size: 6.6pt; font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: #bfe0d1; }
.po-number { font-size: 14pt; font-weight: 700; letter-spacing: 0.01em; }
.po-date { font-size: 7.6pt; color: #d6ebe1; }
/* Address cards */
.cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4mm; margin: 5mm 0 4mm; }
.card { padding: 3.2mm 3.8mm; border: 0.3mm solid var(--rule); border-top: 1mm solid var(--forest); border-radius: 0 0 1.5mm 1.5mm; }
.card-name { font-weight: 700; }
.card-extra { margin-top: 1.4mm; font-size: 7.6pt; color: var(--muted); overflow-wrap: anywhere; }
/* Order facts */
.meta {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 0;
margin-bottom: 5mm;
border-radius: 1.5mm;
background: var(--mint);
}
.meta div { padding: 2.2mm 3.5mm; border-right: 0.25mm solid #d3e4da; border-bottom: 0.25mm solid #d3e4da; }
.meta div.wide { grid-column: span 2; }
.meta span { display: block; font-size: 6.4pt; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.meta strong { display: block; font-weight: 600; }
.meta em { display: block; font-size: 7.6pt; font-style: normal; color: var(--muted); }
/* Lines */
table.lines { width: 100%; border-collapse: collapse; }
table.lines thead { display: table-header-group; }
table.lines th {
padding: 2mm;
background: var(--forest);
color: #ffffff;
font-size: 6.8pt;
font-weight: 600;
letter-spacing: 0.06em;
text-align: left;
text-transform: uppercase;
}
table.lines th.num { text-align: right; }
table.lines td { padding: 2.2mm 2mm; border-bottom: 0.2mm solid var(--rule); vertical-align: top; }
table.lines tr { break-inside: avoid; page-break-inside: avoid; }
table.lines tbody tr:nth-child(even) td { background: #f7faf8; }
.ln { width: 10mm; color: var(--muted); font-variant-numeric: tabular-nums; }
.code { width: 30mm; font-family: "DejaVu Sans Mono", "Liberation Mono", monospace; font-size: 7.2pt; }
.unit { width: 24mm; color: var(--muted); }
.totals-row { display: grid; grid-template-columns: 1fr 74mm; gap: 10mm; margin-top: 4mm; break-inside: avoid; page-break-inside: avoid; }
.conditions { align-self: start; padding-top: 1.5mm; font-size: 7.6pt; color: var(--muted); }
.totals { width: 100%; border-collapse: collapse; }
.totals td, .totals th { padding: 1.4mm 2mm; }
.totals th { font-weight: inherit; text-align: inherit; }
.totals .grand td, .totals .grand th { padding: 2.6mm 2mm; border-top: 0.5mm solid var(--forest); font-size: 11.5pt; font-weight: 700; color: var(--forest); }
/* Instructions and approvals */
.lower { display: grid; grid-template-columns: 1fr 1.05fr; gap: 9mm; margin-top: 7mm; break-inside: avoid; page-break-inside: avoid; }
.lower h2 { margin-bottom: 2mm; font-size: 10pt; font-weight: 700; color: var(--forest); }
.instructions ol { margin: 0 0 2.5mm; padding-left: 4.5mm; }
.instructions li { margin-bottom: 1mm; padding-left: 1mm; }
.instructions li::marker { font-weight: 700; color: var(--forest); }
.contact { font-size: 7.8pt; color: var(--muted); }
.approver { display: grid; grid-template-columns: 1.2fr 1fr 22mm; gap: 3mm; align-items: end; padding: 2.2mm 0; border-bottom: 0.25mm solid var(--rule); }
.who .step { display: block; font-size: 6.4pt; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); }
.who strong { display: block; font-weight: 600; }
.who .role { display: block; font-size: 7.4pt; color: var(--muted); }
.who .rule { display: inline-block; margin-top: 0.8mm; padding: 0 1.6mm; border-radius: 1mm; background: #fbf4e3; color: #8a6414; font-size: 6.6pt; }
.sig, .when { position: relative; height: 9mm; padding-top: 4.5mm; border-bottom: 0.3mm solid var(--ink); font-variant-numeric: tabular-nums; }
.sig span, .when span { position: absolute; top: 0; left: 0; font-size: 6pt; 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": {
"buyer": {
"name": "Stackyard Brewing Co. Ltd",
"address": "The Maltings, 7 Stackyard Lane\nKendal LA9 4TR\nUnited Kingdom",
"vat_id": "GB 318 2264 50",
"invoice_email": "payables@stackyard.example.com"
},
"buyer_contact": {
"name": "Rhiannon Tuckett",
"role": "Procurement Lead",
"email": "rhiannon.tuckett@stackyard.example.com",
"phone": "+44 20 7946 0852"
},
"supplier": {
"name": "Pellow & Grange Packaging Ltd",
"account": "SUP-00412",
"address": "Unit 14, Brindley Road Industrial Estate\nWarrington WA2 8QZ\nUnited Kingdom",
"email": "orders@pellowgrange.example.com"
},
"deliver_to": {
"name": "Stackyard Brewing, Goods In",
"address": "Bay 3, Kentmere Works, Quarry Row\nKendal LA9 6QQ\nUnited Kingdom",
"hours": "Monday to Friday, 07:30–14:30",
"contact": "Warehouse team, +44 20 7946 0853"
},
"order": {
"number": "PO-SB-2026-0388",
"date": "2026-09-15",
"lead_time_days": 21,
"supplier_quote": "Q-PG-11873",
"payment_terms": "30 days from the end of the invoice month",
"cost_centre": "OPS-PACK",
"currency": "GBP",
"vat_rate": 0.2
},
"lines": [
{
"code": "PG-CAN-440-MB",
"description": "Aluminium cans, 440 ml, matt black, unprinted",
"unit": "pallet of 8,280",
"quantity": 6,
"unit_price": 812.4,
"amount": 4874.4
},
{
"code": "PG-END-202-SL",
"description": "Can ends, 202 diameter, silver",
"unit": "box of 6,000",
"quantity": 8,
"unit_price": 96,
"amount": 768
}
],
"delivery_instructions": [
"Book a delivery slot with the warehouse team at least 48 hours in advance.",
"Deliver on standard 1,200 × 1,000 mm pallets, stretch-wrapped, no higher than 1.8 m."
],
"conditions": "Quote the PO number on every delivery note and invoice. Part deliveries only by prior agreement. All goods are inspected on arrival and may be returned if they do not match this order.",
"approvals": [
{
"step": "Requested by",
"name": "Rhiannon Tuckett",
"role": "Procurement Lead",
"date": "2026-09-14",
"required_above": null
},
{
"step": "Budget holder",
"name": "Callum Everingham",
"role": "Head of Operations",
"date": "2026-09-15",
"required_above": null
}
]
},
"output": {
"format": "pdf",
"filename": "purchase-order-standard.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": {
"buyer": {
"name": "Stackyard Brewing Co. Ltd",
"address": "The Maltings, 7 Stackyard Lane\nKendal LA9 4TR\nUnited Kingdom",
"vat_id": "GB 318 2264 50",
"invoice_email": "payables@stackyard.example.com"
},
"buyer_contact": {
"name": "Rhiannon Tuckett",
"role": "Procurement Lead",
"email": "rhiannon.tuckett@stackyard.example.com",
"phone": "+44 20 7946 0852"
},
"supplier": {
"name": "Pellow & Grange Packaging Ltd",
"account": "SUP-00412",
"address": "Unit 14, Brindley Road Industrial Estate\nWarrington WA2 8QZ\nUnited Kingdom",
"email": "orders@pellowgrange.example.com"
},
"deliver_to": {
"name": "Stackyard Brewing, Goods In",
"address": "Bay 3, Kentmere Works, Quarry Row\nKendal LA9 6QQ\nUnited Kingdom",
"hours": "Monday to Friday, 07:30–14:30",
"contact": "Warehouse team, +44 20 7946 0853"
},
"order": {
"number": "PO-SB-2026-0388",
"date": "2026-09-15",
"lead_time_days": 21,
"supplier_quote": "Q-PG-11873",
"payment_terms": "30 days from the end of the invoice month",
"cost_centre": "OPS-PACK",
"currency": "GBP",
"vat_rate": 0.2
},
"lines": [
{
"code": "PG-CAN-440-MB",
"description": "Aluminium cans, 440 ml, matt black, unprinted",
"unit": "pallet of 8,280",
"quantity": 6,
"unit_price": 812.4,
"amount": 4874.4
},
{
"code": "PG-END-202-SL",
"description": "Can ends, 202 diameter, silver",
"unit": "box of 6,000",
"quantity": 8,
"unit_price": 96,
"amount": 768
}
],
"delivery_instructions": [
"Book a delivery slot with the warehouse team at least 48 hours in advance.",
"Deliver on standard 1,200 × 1,000 mm pallets, stretch-wrapped, no higher than 1.8 m."
],
"conditions": "Quote the PO number on every delivery note and invoice. Part deliveries only by prior agreement. All goods are inspected on arrival and may be returned if they do not match this order.",
"approvals": [
{
"step": "Requested by",
"name": "Rhiannon Tuckett",
"role": "Procurement Lead",
"date": "2026-09-14",
"required_above": null
},
{
"step": "Budget holder",
"name": "Callum Everingham",
"role": "Head of Operations",
"date": "2026-09-15",
"required_above": null
}
]
},
"output": {
"format": "pdf",
"filename": "purchase-order-standard.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": {
"buyer": {
"name": "Stackyard Brewing Co. Ltd",
"address": "The Maltings, 7 Stackyard Lane\nKendal LA9 4TR\nUnited Kingdom",
"vat_id": "GB 318 2264 50",
"invoice_email": "payables@stackyard.example.com",
},
"buyer_contact": {
"name": "Rhiannon Tuckett",
"role": "Procurement Lead",
"email": "rhiannon.tuckett@stackyard.example.com",
"phone": "+44 20 7946 0852",
},
"supplier": {
"name": "Pellow & Grange Packaging Ltd",
"account": "SUP-00412",
"address": "Unit 14, Brindley Road Industrial Estate\nWarrington WA2 8QZ\nUnited Kingdom",
"email": "orders@pellowgrange.example.com",
},
"deliver_to": {
"name": "Stackyard Brewing, Goods In",
"address": "Bay 3, Kentmere Works, Quarry Row\nKendal LA9 6QQ\nUnited Kingdom",
"hours": "Monday to Friday, 07:30–14:30",
"contact": "Warehouse team, +44 20 7946 0853",
},
"order": {
"number": "PO-SB-2026-0388",
"date": "2026-09-15",
"lead_time_days": 21,
"supplier_quote": "Q-PG-11873",
"payment_terms": "30 days from the end of the invoice month",
"cost_centre": "OPS-PACK",
"currency": "GBP",
"vat_rate": 0.2,
},
"lines": [
{
"code": "PG-CAN-440-MB",
"description": "Aluminium cans, 440 ml, matt black, unprinted",
"unit": "pallet of 8,280",
"quantity": 6,
"unit_price": 812.4,
"amount": 4874.4,
},
{
"code": "PG-END-202-SL",
"description": "Can ends, 202 diameter, silver",
"unit": "box of 6,000",
"quantity": 8,
"unit_price": 96,
"amount": 768,
},
],
"delivery_instructions": ["Book a delivery slot with the warehouse team at least 48 hours in advance.", "Deliver on standard 1,200 × 1,000 mm pallets, stretch-wrapped, no higher than 1.8 m."],
"conditions": "Quote the PO number on every delivery note and invoice. Part deliveries only by prior agreement. All goods are inspected on arrival and may be returned if they do not match this order.",
"approvals": [
{
"step": "Requested by",
"name": "Rhiannon Tuckett",
"role": "Procurement Lead",
"date": "2026-09-14",
"required_above": None,
},
{
"step": "Budget holder",
"name": "Callum Everingham",
"role": "Head of Operations",
"date": "2026-09-15",
"required_above": None,
},
],
},
"output": {
"format": "pdf",
"filename": "purchase-order-standard.pdf",
},
},
timeout=90,
)
response.raise_for_status()
print(response.json())