How to Generate a Dynamic PDF E-commerce Invoice with PDF.co

5 Minutes Read

This tutorial explains how to generate an e-commerce invoice from an HTML template and dynamic JSON data using the PDF.co Web API.

The HTML template controls the invoice’s design, while the JSON data supplies values such as the order number, customer address, products, prices, and totals. You can reuse the same template to generate a different invoice for every order.

What You Will Need

Before starting, make sure you have:

  • A PDF.co account
  • An HTML invoice template saved in PDF.co
  • Sample order data in JSON format
  • Access to the PDF.co API Tester

The workflow consists of three parts:

  1. Create and save an HTML invoice template.
  2. send the template ID and order data to the PDF.co API.
  3. Open or download the generated PDF.

Step 1: Create an HTML Invoice Template

Sign in to your PDF.co account and open the HTML to PDF Templates section.

Create a new template and give it a descriptive name, such as:

E-commerce Invoice

HTML templates support Mustache and Handlebars placeholders. A placeholder such as {{order_id}} is replaced by the matching value from the template data.

The {{#each items}} block can be used to create one table row for each purchased product.

Here is a simplified invoice template:

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <style>
    body {
      margin: 0;
      color: #222;
      font-family: Arial, sans-serif;
      font-size: 12px;
    }

    .invoice {
      max-width: 760px;
      margin: 0 auto;
    }

    .header {
      display: flex;
      justify-content: space-between;
      margin-bottom: 30px;
    }

    .header h1 {
      margin: 0 0 8px;
      color: #2457a7;
      font-size: 30px;
    }

    .company,
    .invoice-details {
      line-height: 1.5;
    }

    .invoice-details {
      text-align: right;
    }

    .addresses {
      display: flex;
      gap: 40px;
      margin-bottom: 30px;
    }

    .address {
      flex: 1;
      white-space: pre-line;
    }

    .address h2 {
      margin: 0 0 8px;
      color: #555;
      font-size: 14px;
      text-transform: uppercase;
    }

    table {
      width: 100%;
      border-collapse: collapse;
    }

    th {
      padding: 10px;
      color: #fff;
      background: #2457a7;
      text-align: left;
    }

    td {
      padding: 10px;
      border-bottom: 1px solid #ddd;
    }

    .number {
      text-align: right;
    }

    .totals {
      width: 320px;
      margin: 24px 0 0 auto;
    }

    .totals td {
      border: 0;
      padding: 5px 10px;
    }

    .grand-total {
      font-size: 15px;
      font-weight: bold;
    }

    .notes {
      margin-top: 35px;
      padding: 15px;
      background: #f3f5f8;
      white-space: pre-line;
    }
  </style>
</head>
<body>
  <div class="invoice">
    <div class="header">
      <div class="company">
        <h1>INVOICE</h1>
        <strong>{{company_name}}</strong><br>
        <span style="white-space: pre-line">{{company_address}}</span>
      </div>

      <div class="invoice-details">
        <strong>Order:</strong> {{order_id}}<br>
        <strong>Order date:</strong> {{order_date}}<br>
        <strong>Customer ID:</strong> {{customer_id}}<br>
        <strong>Shipped date:</strong> {{shipped_date}}<br>
        <strong>Shipped via:</strong> {{shipped_via}}
      </div>
    </div>

    <div class="addresses">
      <div class="address">
        <h2>Bill To</h2>
        <strong>{{bill_to_name}}</strong><br>
        {{bill_to_address}}
      </div>

      <div class="address">
        <h2>Ship To</h2>
        <strong>{{ship_to_name}}</strong><br>
        {{ship_to_address}}
      </div>
    </div>

    <table>
      <thead>
        <tr>
          <th>Product</th>
          <th class="number">Quantity</th>
          <th class="number">Unit Price</th>
          <th class="number">Amount</th>
        </tr>
      </thead>

      <tbody>
        {{#each items}}
        <tr>
          <td>{{name}}</td>
          <td class="number">{{quantity}}</td>
          <td class="number">{{price}}</td>
          <td class="number">{{line_total}}</td>
        </tr>
        {{/each}}
      </tbody>
    </table>

    <table class="totals">
      <tr>
        <td>Subtotal</td>
        <td class="number">{{subtotal}}</td>
      </tr>
      <tr>
        <td>Shipping</td>
        <td class="number">{{freight}}</td>
      </tr>
      <tr>
        <td>Tax</td>
        <td class="number">{{tax}}</td>
      </tr>
      <tr class="grand-total">
        <td>Total</td>
        <td class="number">{{total}}</td>
      </tr>
    </table>

    {{#if notes}}
    <div class="notes">
      <strong>Notes</strong><br>
      {{notes}}
    </div>
    {{/if}}
  </div>
</body>
</html>

Save the template.

Step 2: Copy the Template ID

After saving the template, locate its numeric template ID. The ID may appear in the template list, template details, or template-editing URL.

Copy this value. You will use it as the request’s templateId.

The template ID must belong to the PDF.co account used to authenticate the request.

Step 3: Prepare the Invoice Data

Create a JSON object whose property names match the placeholders in the HTML template.

For example:

{
  "company_name": "Northwind Market",
  "company_address": "1234 Market Street\nSan Francisco, CA 94102\nUSA",
  "order_id": "1122455",
  "order_date": "September 2, 2026",
  "customer_id": "C-8001",
  "shipped_date": "September 3, 2026",
  "shipped_via": "UPS",
  "bill_to_name": "John Doe",
  "bill_to_address": "435 South La Fayette Park Place\nLos Angeles, CA 90057\nUSA",
  "ship_to_name": "Jane Doe",
  "ship_to_address": "18144 El Camino Real\nSunnyvale, CA 94087\nUSA",
  "items": [
    {
      "name": "Wireless Keyboard",
      "quantity": 2,
      "price": "$50.00",
      "line_total": "$100.00"
    },
    {
      "name": "USB-C Dock",
      "quantity": 1,
      "price": "$150.00",
      "line_total": "$150.00"
    },
    {
      "name": "Laptop Stand",
      "quantity": 2,
      "price": "$35.00",
      "line_total": "$70.00"
    }
  ],
  "subtotal": "$320.00",
  "freight": "$19.95",
  "tax": "$26.40",
  "total": "$366.35",
  "notes": "Thank you for your purchase."
}

Calculate monetary totals in the e-commerce platform or application creating the request. The PDF template should generally display finalized values rather than perform authoritative financial calculations.

Step 4: Open the PDF.co API Tester

Open the PDF.co API Tester while signed in to your PDF.co account.

Select the following endpoint:

POST /v1/pdf/convert/from/html

This endpoint supports both raw HTML and saved HTML templates. When using a saved template, supply templateId and templateData.

The current endpoint and its parameters are documented in the PDF from HTML Template API reference.

Step 5: Configure the Request

Enter the following request values:

  • Template ID: Your saved HTML template ID
  • Template Data: The invoice data serialized as a JSON string
  • Name: ecommerce-invoice-1122455.pdf
  • Paper Size: Letter
  • Orientation: Portrait
  • Margins: 20px
  • Print Background: true
  • Media Type: print
  • Async: false

A complete JSON request body has this structure:

{
  "templateId": 123,
  "name": "ecommerce-invoice-1122455.pdf",
  "paperSize": "Letter",
  "orientation": "Portrait",
  "margins": "20px",
  "printBackground": true,
  "mediaType": "print",
  "async": false,
  "templateData": "{\"company_name\":\"Northwind Market\",\"company_address\":\"1234 Market Street\\nSan Francisco, CA 94102\\nUSA\",\"order_id\":\"1122455\",\"order_date\":\"September 2, 2026\",\"customer_id\":\"C-8001\",\"shipped_date\":\"September 3, 2026\",\"shipped_via\":\"UPS\",\"bill_to_name\":\"John Doe\",\"bill_to_address\":\"435 South La Fayette Park Place\\nLos Angeles, CA 90057\\nUSA\",\"ship_to_name\":\"Jane Doe\",\"ship_to_address\":\"18144 El Camino Real\\nSunnyvale, CA 94087\\nUSA\",\"items\":[{\"name\":\"Wireless Keyboard\",\"quantity\":2,\"price\":\"$50.00\",\"line_total\":\"$100.00\"},{\"name\":\"USB-C Dock\",\"quantity\":1,\"price\":\"$150.00\",\"line_total\":\"$150.00\"},{\"name\":\"Laptop Stand\",\"quantity\":2,\"price\":\"$35.00\",\"line_total\":\"$70.00\"}],\"subtotal\":\"$320.00\",\"freight\":\"$19.95\",\"tax\":\"$26.40\",\"total\":\"$366.35\",\"notes\":\"Thank you for your purchase.\"}"
}

Replace 123 with the actual template ID.

The templateData parameter is a string containing JSON. When assembling the request programmatically, serialize the invoice object with the standard JSON function provided by your programming language. In JavaScript, for example, use:

const requestBody = {
  templateId: 123,
  name: "ecommerce-invoice-1122455.pdf",
  paperSize: "Letter",
  orientation: "Portrait",
  margins: "20px",
  printBackground: true,
  mediaType: "print",
  async: false,
  templateData: JSON.stringify(invoiceData)
};

This avoids manually escaping every quotation mark.

Step 6: Run the Request

Run the request in the API Tester.

A successful synchronous response resembles:

{
  "url": "https://pdf-temp-files.s3.amazonaws.com/.../ecommerce-invoice-1122455.pdf",
  "pageCount": 1,
  "error": false,
  "status": 200,
  "name": "ecommerce-invoice-1122455.pdf",
  "remainingCredits": 1000
}

Confirm that:

  • error is false.
  • status is 200.
  • url contains the temporary location of the generated PDF.
  • pageCount contains the number of generated pages.

Step 7: Review the Generated Invoice

Open the returned URL and inspect the invoice.

Verify that:

  • The order and customer information is correct.
  • Billing and shipping addresses retain their line breaks.
  • Every product appears in the table.
  • Quantities, prices, and totals are correct.
  • Long product lists continue onto additional pages properly.
  • Colors and other background styling appear in the PDF.
  • No content is cut off by the page margins.

If the layout needs adjustment, edit the HTML template, save it, and run the same request again.

Step 8: Integrate the Request into an E-commerce Workflow

After validating the template in the API Tester, call the same endpoint from your application or automation workflow.

A production workflow might:

  1. Receive a paid-order event from an e-commerce platform.
  2. Validate the order and customer data.
  3. Calculate the subtotal, discounts, shipping, tax, and total.
  4. Serialize the order data into templateData.
  5. Send it to PDF.co with the template ID.
  6. Download the generated PDF from the returned URL.
  7. Save the invoice in permanent storage.
  8. Email the invoice to the customer.

PDF.co output URLs are temporary. Download or transfer the generated invoice to permanent storage before the output link expires.

Troubleshooting

A Placeholder Appears Unchanged

Confirm that its name exactly matches a property in the JSON data. Placeholder names and JSON property names are case-sensitive.

For example:

{{order_id}}

requires:

{
  "order_id": "1122455"
}

The Items Table Is Empty

Confirm that items is an array and that the template places its table row inside:

{{#each items}}
...
{{/each}}

The API Reports Invalid Template Data

The templateData parameter must be a string. Serialize the invoice-data object before placing it in the request body.

Background Colors Are Missing

Set printBackground to true.

The Header or Footer Overlaps the Invoice

Increase the corresponding top or bottom margin. Headers and footers require enough page space to render without covering the main content.

The Output Link No Longer Works

Generated output links are temporary. Run the request again or save the PDF to permanent storage immediately after it is generated.

The Wrong Template Is Used

Check that the templateId belongs to the authenticated PDF.co account and identifies the intended HTML template.

Conclusion

You have created a reusable HTML invoice template and populated it with dynamic e-commerce order data through the PDF.co Web API. The same template can now generate invoices for different customers and orders by changing only the templateData value.

This approach separates invoice design from order data, making the workflow easier to maintain and integrate with e-commerce platforms, web applications, and automation services.

Related Tutorials

See Related Tutorials