Fulfilment / A4
Returns form HTML template
The form that goes in the box for the customer to send back: numbered steps, a table to fill in, coded reasons and a choice of outcome.
When this document is the right one
A parcel is despatched with a returns policy attached. The form is printed before anyone knows whether it will be used, so it has to be filled in by hand rather than pre-populated.
Why each part is there
The fields are visible in the markup. What is not visible is why they are present, which is the part that gets removed first when someone adapts a template for their own use.
- Three numbered steps at the top, because the most common failure is a parcel arriving with no form in it.
- Reason codes as a printed key rather than a free-text box, since a free-text reason cannot be counted and counting is the whole point of collecting them.
- An unopened column, because the refund rule for consumables depends on it and asking after the parcel arrives costs a week.
- An explicit choice of refund, exchange or credit, so the outcome is not inferred.
- A tear-off line at the foot carrying the return reference, which is what the customer will quote when they chase it.
The template
A complete file. Doctype, stylesheet, body: paste it into a renderer unchanged and it produces a finished A4 page. Replace the sample data and the styling holds.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Returns form, order ORD-99031</title>
<style>
@page { size: A4; margin: 15mm; }
* { box-sizing: border-box; }
body { margin: 0; font: 9.5pt/1.4 Arial, sans-serif; color: #111; }
header { display: flex; justify-content: space-between; align-items: flex-start;
border-bottom: 2px solid #111; padding-bottom: 5mm; }
h1 { margin: 0; font-size: 17pt; }
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5mm; margin: 6mm 0;
break-inside: avoid; }
.steps div { border: 1px solid #ccc; padding: 4mm; }
.steps .n { width: 7mm; height: 7mm; border-radius: 50%; background: #111; color: #fff;
display: flex; align-items: center; justify-content: center;
font-weight: 700; font-size: 9pt; margin-bottom: 2mm;
print-color-adjust: exact; -webkit-print-color-adjust: exact; }
table { width: 100%; border-collapse: collapse; margin-top: 3mm; }
thead { display: table-header-group; }
th, td { border: 1px solid #bbb; padding: 2.5mm; }
th { background: #f2f2f2; text-align: left; font-size: 8pt;
text-transform: uppercase; letter-spacing: 0.05em; }
tr { break-inside: avoid; }
.num { text-align: right; font-variant-numeric: tabular-nums; }
.writein { height: 9mm; }
/* Reason codes as a printed key rather than a free-text box. A free-text
reason cannot be counted, and the whole point of collecting reasons is
to find out which product keeps coming back. */
.codes { margin-top: 5mm; border: 1px solid #bbb; padding: 4mm; font-size: 8.5pt;
break-inside: avoid; }
.codes ul { margin: 2mm 0 0; padding: 0; list-style: none;
display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5mm 5mm; }
.codes strong { display: inline-block; width: 8mm; }
.outcome { display: flex; gap: 8mm; margin-top: 5mm; font-size: 9.5pt; }
.outcome label { display: flex; align-items: center; gap: 2mm; }
.box { display: inline-block; width: 4mm; height: 4mm; border: 1.5px solid #111; }
.terms { margin-top: 6mm; border-top: 1px solid #ddd; padding-top: 4mm;
font-size: 8pt; color: #555; break-inside: avoid; }
.cut { margin-top: 8mm; border-top: 1px dashed #999; padding-top: 3mm;
font-size: 8pt; color: #777; text-align: center; }
</style>
</head>
<body>
<header>
<div>
<h1>Returns form</h1>
<div style="margin-top:1.5mm">Fennel & Rye · order ORD-99031 · delivered 21 May 2026</div>
</div>
<div style="text-align:right;font-size:9pt">
Return by<br><strong>20 June 2026</strong><br>30 days from delivery
</div>
</header>
<section class="steps">
<div><div class="n">1</div>Fill in the table below. Put a reason code against every item you are sending back.</div>
<div><div class="n">2</div>Put this form in the parcel. A parcel with no form takes about a week longer to process.</div>
<div><div class="n">3</div>Attach the label from fennelandrye.example/returns and drop the parcel at any collection point.</div>
</section>
<table>
<thead>
<tr><th>Item</th><th>SKU</th><th class="num">Qty sent back</th>
<th class="num">Reason code</th><th>Unopened?</th></tr>
</thead>
<tbody>
<tr><td>Cold brew concentrate, 1L</td><td>FR-CB-1000</td>
<td class="writein"></td><td></td><td></td></tr>
<tr><td>House blend beans, 500g</td><td>FR-HB-500</td>
<td class="writein"></td><td></td><td></td></tr>
<tr><td>Ceramic pour-over, matte white</td><td>FR-PO-01</td>
<td class="writein"></td><td></td><td></td></tr>
</tbody>
</table>
<section class="codes">
<strong>Reason codes</strong>
<ul>
<li><strong>01</strong> Changed my mind</li>
<li><strong>02</strong> Arrived damaged</li>
<li><strong>03</strong> Wrong item sent</li>
<li><strong>04</strong> Not as described</li>
<li><strong>05</strong> Arrived too late</li>
<li><strong>06</strong> Faulty in use</li>
</ul>
</section>
<div class="outcome">
<label><span class="box"></span> Refund to the original payment method</label>
<label><span class="box"></span> Exchange, tell us what for below</label>
<label><span class="box"></span> Store credit</label>
</div>
<p class="terms">
Unopened items in resaleable condition are refunded in full. Opened consumables can
only be refunded where the reason code is 02, 03, 04 or 06. Refunds are processed
within five working days of the parcel reaching us and reach your account a few days
after that, which is your bank's timing rather than ours. Original postage is
refunded only where the return is our error.
</p>
<div class="cut">Keep the bottom of this form. It has your return reference on it: RMA-99031.</div>
</body>
</html>The layout decision worth understanding
The step markers are filled circles with print-color-adjust: exact. They are the one decorative element on the page and they carry the reading order, so losing them to a print stylesheet that drops backgrounds would turn three steps into three paragraphs.
The mistake people make adapting it
Leaving the reason as a free-text field. It feels friendlier and it produces a column of prose nobody can aggregate, so the question that returns data exists to answer, which product keeps coming back and why, stays unanswered.
Rendering it
The page box is declared in the template's own CSS as A4, so the size travels with the markup rather than living in the code that calls the renderer. A4 is also one of the six named formats the API accepts, so it can be passed in the request options instead if that suits your setup better.
curl -X POST https://api.pdfpipe.xyz/v1/pdf \
-H "Authorization: Bearer $PDFPIPE_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<!doctype html>...",
"options": { "format": "A4" }
}' \
--output return-form.pdfFrequently asked
Can I use this template commercially?
Yes. Copy it, change it, ship it. It is sample markup written to be taken, and the sample data in it is invented, so replace the names and the numbers before anyone sees it.
Why is the page size in the CSS rather than in the API call?
Because a returns form is a A4 document, and that is a property of the document rather than of the code that renders it. Declaring it in the page box means the size cannot be lost between the template and the call, which is the usual way a document ends up on the wrong paper.
Will it look the same in every renderer?
The layout will, because it uses ordinary CSS. The page break behaviour will not: break-inside and break-after are implemented differently by browser engines and by dedicated print engines, and some of the paged media specification is not implemented in browser renders at all. That difference is documented per property in the paged CSS reference.
Other templates
Documents from the same part of a business, and one from each of the other groups.
Packing slip HTML template
The document that goes in the box: what was ordered, what was actually shipped, and no prices at all.
4x6 shipping label HTML template
A 4 by 6 inch thermal label with a service band, a large delivery address, a routing code and a barcode with real quiet zones.
Goods received note HTML template
The buyer's record of what actually arrived: ordered against delivered against accepted, with every discrepancy explained and signed for.
21-per-sheet address label HTML template
Twenty-one addresses in a fixed 3 by 7 grid on A4, with absolute row heights so the print cannot drift out of the die cuts.
HTML invoice template with CSS
The standard commercial invoice: a demand for payment with line items, a tax figure, and terms that say when the money is due.
Payment receipt HTML template
Proof that a payment was made: the amount, the payment reference, the method, and what it was for.
Quotation HTML template with CSS
A priced proposal with a validity date, a scope, optional items kept out of the headline total, and somewhere to sign.
Every template
The full set, grouped by what part of a business produces the document.
A4 page size for PDF generation
A4 is the default page for business documents everywhere except North America, and the default this API uses when no format is given.
Paste the template into the playground and get the PDF back. No signup, no key.