People and payroll / A4
Expense report HTML template
An itemised claim for reimbursement: expenses with receipts and business purposes, mileage calculated separately, and a policy note explaining the rules being applied.
When this document is the right one
An employee spends their own money on the business. The document is approved by a manager and then paid by finance, and those two readers check different things.
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.
- A business purpose on every line, not just a category. A category is what it was, a purpose is why it is claimable.
- A receipt reference per line, with missing receipts flagged in the document rather than left for the approver to notice.
- Net and tax as separate columns, because tax is only reclaimable where a valid receipt exists and the claim has to show which lines qualify.
- Mileage in its own table with distance and rate, since it is calculated rather than receipted and follows different rules.
- The policy rules being applied, on the document, so an approver does not have to remember them.
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>Expense claim EXP-2026-0219</title>
<style>
@page { size: A4; margin: 15mm; }
* { box-sizing: border-box; }
body { margin: 0; font: 9pt/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: 16pt; }
.claim-meta { text-align: right; font-size: 9pt; }
.claimant { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5mm;
margin: 5mm 0; }
.claimant .k { font-size: 7.5pt; text-transform: uppercase; letter-spacing: 0.06em;
color: #666; }
table { width: 100%; border-collapse: collapse; margin-top: 4mm; }
thead { display: table-header-group; }
th { text-align: left; font-size: 7.5pt; text-transform: uppercase; letter-spacing: 0.05em;
color: #666; border-bottom: 1.5px solid #111; padding-bottom: 2mm; }
td { padding: 2.2mm 2mm 2.2mm 0; border-bottom: 1px solid #eee; vertical-align: top; }
tr { break-inside: avoid; }
.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* A claim line with no receipt reference is the line that gets rejected, so
the absence is made visible rather than left to a reviewer to notice. */
.no-receipt { color: #b3261e; font-weight: 700; }
tfoot td { border-top: 1.5px solid #111; border-bottom: 0; font-weight: 700;
padding-top: 3mm; font-size: 11pt; }
.mileage { margin-top: 7mm; border: 1px solid #ddd; padding: 4mm; break-inside: avoid; }
.mileage h2 { margin: 0 0 2mm; font-size: 8.5pt; text-transform: uppercase;
letter-spacing: 0.07em; color: #666; }
.mileage table { margin: 0; }
.mileage td, .mileage th { border-bottom: 1px solid #eee; }
.policy { margin-top: 7mm; font-size: 8pt; color: #555; background: #f6f6f6;
padding: 4mm; break-inside: avoid; }
.policy ul { margin: 2mm 0 0; padding-left: 4.5mm; }
.approval { margin-top: 8mm; display: grid; grid-template-columns: 1fr 1fr 1fr;
gap: 8mm; break-inside: avoid; }
.approval div { border-top: 1px solid #111; padding-top: 1.5mm; margin-top: 14mm;
font-size: 8pt; color: #666; }
</style>
</head>
<body>
<header>
<div>
<h1>Expense claim</h1>
<div style="margin-top:1.5mm">Kilnworks Studio Ltd</div>
</div>
<div class="claim-meta">
<strong>EXP-2026-0219</strong><br>
Submitted 18 May 2026<br>
Period 04 to 15 May 2026
</div>
</header>
<section class="claimant">
<div><div class="k">Claimant</div>E. Prentice</div>
<div><div class="k">Payroll number</div>KW-0101</div>
<div><div class="k">Cost centre</div>SALES-UK</div>
<div><div class="k">Reimburse to</div>Account ending 8842</div>
</section>
<table>
<thead>
<tr>
<th>Date</th><th>Category</th><th>Description and business purpose</th>
<th>Receipt</th><th class="num">Net</th><th class="num">VAT</th><th class="num">Gross</th>
</tr>
</thead>
<tbody>
<tr>
<td>06 May</td><td>Rail</td>
<td>Bristol to Bath return, Ravenshill site visit</td>
<td>R-4471</td><td class="num">18.83</td><td class="num">0.00</td><td class="num">18.83</td>
</tr>
<tr>
<td>06 May</td><td>Meals</td>
<td>Lunch with D. Quinn, Ravenshill Hotel Group, 2 covers</td>
<td>R-4472</td><td class="num">36.25</td><td class="num">7.25</td><td class="num">43.50</td>
</tr>
<tr>
<td>11 May</td><td>Materials</td>
<td>Glaze oxides, urgent replacement for trial batch</td>
<td>R-4473</td><td class="num">84.00</td><td class="num">16.80</td><td class="num">100.80</td>
</tr>
<tr>
<td>14 May</td><td>Parking</td>
<td>Bath city centre, 3 hours</td>
<td class="no-receipt">Missing</td><td class="num">7.50</td><td class="num">0.00</td><td class="num">7.50</td>
</tr>
</tbody>
<tfoot>
<tr><td colspan="4">Subtotal, receipted expenses</td>
<td class="num">146.58</td><td class="num">24.05</td><td class="num">170.63</td></tr>
</tfoot>
</table>
<section class="mileage">
<h2>Mileage</h2>
<table>
<tr><th>Date</th><th>From and to</th><th>Purpose</th>
<th class="num">Miles</th><th class="num">Rate</th><th class="num">Amount</th></tr>
<tr><td>12 May</td><td>Studio to Wells and return</td><td>Delivery, second batch samples</td>
<td class="num">44</td><td class="num">0.45</td><td class="num">19.80</td></tr>
<tr><td>15 May</td><td>Studio to Bristol depot</td><td>Collect clay order</td>
<td class="num">18</td><td class="num">0.45</td><td class="num">8.10</td></tr>
<tr><td colspan="5" class="num"><strong>Mileage total</strong></td>
<td class="num"><strong>27.90</strong></td></tr>
</table>
</section>
<div style="margin-top:5mm;text-align:right;font-size:13pt;font-weight:700">
Total claimed: GBP 198.53
</div>
<section class="policy">
<strong>Policy notes</strong>
<ul>
<li>A line without a receipt reference is paid at the approver's discretion and only up to GBP 10. The parking line above falls under this rule.</li>
<li>VAT is reclaimable only where a valid VAT receipt is attached, so the rail fare is claimed gross.</li>
<li>Client entertainment must name every attendee and their organisation. A count alone is not enough.</li>
<li>Mileage is paid at the approved rate for the first 10,000 business miles in a tax year.</li>
</ul>
</section>
<div class="approval">
<div>Claimant signature and date</div>
<div>Approved by and date</div>
<div>Finance, paid on</div>
</div>
</body>
</html>The layout decision worth understanding
A missing receipt is styled in red and named rather than left blank. This is the one place in the template where the design deliberately makes the claimant uncomfortable, and it is worth it: a flagged line gets a conversation, a blank cell gets approved by accident.
The mistake people make adapting it
Reclaiming tax on a line with no valid tax receipt. It is the most common finding in an expenses audit, and it happens because the claim form has a tax column that is easier to fill in than to leave empty.
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 expense-report.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 expense claim 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.
Payslip HTML template with CSS
A statement of pay for one period: gross made of its parts, deductions made of theirs, the net that was actually paid, and the year to date.
Weekly timesheet PDF template
Hours by project and by day across a week, totalled both ways, with an approval signature.
Employment offer letter template
A letter offering a role, stating the principal terms in a scannable block, the conditions the offer depends on, and an acceptance section to sign and return.
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.
Packing slip HTML template
The document that goes in the box: what was ordered, what was actually shipped, and no prices at all.
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.