DEV Community

TemplateMaster
TemplateMaster

Posted on

Generate Invoices as PDFs via API in C# (Step by Step)

Yet in many C# applications, generating a clean and reliable invoice PDF still feels harder than it should be.

Between PDF libraries, HTML-to-PDF tools, layout bugs, and infrastructure issues, what looks like a simple feature often turns into a maintenance nightmare.

In this article, I’ll show you how to generate invoice PDFs in C# using an API-first approach, with:

  • HTML templates
  • dynamic JSON data
  • no PDF logic in your backend

Why invoice PDF generation is still painful in .NET

If you’ve worked on invoice generation before, this probably sounds familiar:

  • Layout breaks when data grows
  • PDF libraries tightly coupled to business logic
  • Headless browsers crashing in production
  • Every layout change requires a redeploy
  • Only developers can edit templates

Invoices evolve constantly: branding, legal mentions, taxes, languages.
Embedding all of that directly inside your backend does not scale.

That’s why treating document generation as a separate service makes a huge difference.

The API-first approach

Instead of generating PDFs inside your C# application, we’ll:
(using a document generation API like TemplateMaster)

  • Create an HTML invoice template
  • Store and version it in TemplateMaster
  • Send invoice data as JSON
  • Let the API generate the PDF
  • Receive a ready-to-use file

Your backend focuses on business logic.
The document layer becomes external, reusable, and maintainable.

Step 1 – Create an invoice HTML template

Here’s a simplified invoice template example:

<h1>Invoice #{{invoiceNumber}}</h1>

<p>
  <strong>Customer</strong><br />
  {{customer.name}}<br />
  {{customer.address}}
</p>

<table width="100%" border="1" cellspacing="0" cellpadding="8">
  <thead>
    <tr>
      <th>Description</th>
      <th>Qty</th>
      <th>Unit price</th>
      <th>Total</th>
    </tr>
  </thead>
  <tbody>
    {{#each items}}
    <tr>
      <td>{{description}}</td>
      <td>{{quantity}}</td>
      <td>{{price}} €</td>
      <td>{{total}} €</td>
    </tr>
    {{/each}}
  </tbody>
</table>

<p>
  <strong>Total amount:</strong> {{totalAmount}} €
</p>
Enter fullscreen mode Exit fullscreen mode

This template:

  • is readable
  • supports loops
  • can be edited by non-developers
  • doesn’t require any C# change when updated

Step 2 – Upload the template to TemplateMaster

Once uploaded to TemplateMaster:

  • the template is versioned
  • editable via a visual editor
  • reusable across environments

Each template has a unique identifier, for example:

813a5147-a68c-4c37-b194-124100368efa
Enter fullscreen mode Exit fullscreen mode

This identifier will be used by your backend when generating PDFs.

Step 3 – Prepare invoice data in C#

Now let’s build the invoice payload in C#:

var invoiceData ={
    "templateCode": "813a5147-a68c-4c37-b194-124100368efa",
    "version": 0,
    "data": {
        "name": "John Doe",
        "address": "1234 Main St, Anytown, AN 12345",
        "items": [
            {
                "description": "Product 1",
                "quantity": 2,
                "price": 30.00
            },
            {
                "description": "Product 2",
                "quantity": 1,
                "price": 15.50
            }
        ],
        "total": 75.50,
        "date": "2023-07-30",
        "metadata": {
            "title": "Service Agreement",
            "author": "TemplateMaster",
            "subject": "Commercial agreement between TemplateMaster and ABC Company",
            "keywords": ["contract", "services", "TemplateMaster", "ABC Company"],
            "creator": "TemplateMaster API",
            "producer": "TemplateMaster PDF Engine",
            "createdAt": "2025-10-14T10:30:00Z",
            "modifiedAt": "2025-10-14T10:31:00Z"
        },
        "indexes":[
            { "DocumentType": "Facture" },
            { "InvoiceNumber":  "F2025-00123" },
            { "CreatedBy": "TemplateMaster" }
        ]
    }
};
Enter fullscreen mode Exit fullscreen mode

This object matches the variables used in the HTML template.

No formatting logic.
No PDF concerns.
Just data.

Step 4 – Call the PDF generation API

Now we send the template ID and data to TemplateMaster.

using var client = new HttpClient();

var request = new
{
    templateId = "invoice-default",
    data = invoiceData
};

var response = await client.PostAsJsonAsync(
    "https://api.templatemaster.io/pdf/generate",
    request
);

var pdfBytes = await response.Content.ReadAsByteArrayAsync();
File.WriteAllBytes("invoice.pdf", pdfBytes);

Enter fullscreen mode Exit fullscreen mode

That’s all it takes.

No PDF engine.
No headless browser.
No rendering logic in your backend.

Step 5 – Use the PDF anywhere

Once generated, the PDF can be:

  • emailed to customers
  • stored for accounting
  • archived for compliance
  • exposed via an API

When the invoice layout changes?

  • Update the template
  • No backend redeploy
  • No code change

Why this approach scales better
Approach Problems
PDF libraries Tight coupling, hard to evolve
HTML-to-PDF in backend Infra heavy, unstable
API-based generation Clean, scalable, maintainable

This pattern works especially well when:

  • invoices evolve frequently
  • multiple teams collaborate
  • you run a SaaS or multi-tenant system

Final thoughts

Invoice PDF generation shouldn’t slow your team down.

By externalizing document generation behind an API, you:

  • reduce complexity
  • move faster
  • keep your backend clean

If you’re building a serious C# application, this is a pattern worth adopting early.

Try it locally

If you want to experiment with this approach, I’m using

TemplateMaster to manage templates and generate PDFs via API.

You can try it without changing your C# setup or PDF stack.

Top comments (0)