> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blinkpdf.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Generate Invoices and Financial Reports as PDFs Fast

> Create pixel-perfect invoices and financial reports from Markdown templates. Fill variables, call /v1/render, and receive a professional PDF in ~100ms.

Invoices, statements, and financial reports share a simple structure — a header, a table of line items, a summary, and some footer metadata. Markdown handles all of that cleanly, which makes Blink PDF an ideal engine for document generation at any scale. You define a template once, fill in the variables at runtime, and receive a print-ready PDF in about 100ms with no layout code to maintain.

## The Markdown Template Approach

Rather than wrestling with HTML/CSS layouts or heavyweight PDF libraries, you write your document once in Markdown and parameterize the dynamic parts. Your application merges the data at runtime and sends the resulting string to `/v1/render`. The workflow looks like this:

```text theme={null}
Template + Data → Rendered Markdown string → POST /v1/render → PDF binary
```

Tables, bold text, horizontal rules, and headings all render cleanly into professionally typeset PDF pages.

## Invoice Markdown Template

Below is a complete invoice template. The placeholders in `{curly braces}` are replaced by your application before the string is sent to the API.

```markdown theme={null}
# Invoice

**{company_name}**
{company_address}
{company_email}

---

**Bill To:**
{client_name}
{client_address}

| Field        | Detail             |
|--------------|--------------------|
| Invoice No.  | {invoice_number}   |
| Issue Date   | {issue_date}       |
| Due Date     | {due_date}         |
| Status       | {status}           |

---

## Line Items

| Description              | Qty | Unit Price | Amount      |
|--------------------------|-----|------------|-------------|
{line_items_rows}

---

## Summary

| | |
|---|---|
| Subtotal | {subtotal} |
| Tax ({tax_rate}%) | {tax_amount} |
| **Total Due** | **{total}** |

---

**Payment Instructions**

Please transfer to the bank account below by {due_date}:

- Account Name: {account_name}
- Account Number: {account_number}
- Routing / Sort Code: {routing_code}
- Reference: {invoice_number}

*Thank you for your business.*
```

<Note>
  The `metadata.title` field you pass in the request body sets the PDF document title (visible in browser tab bars and PDF readers). Use the invoice number or report name for easy identification — for example `"Invoice #1042 — Acme Corp"`.
</Note>

## Code Example

This Python example fills the template, calls `/v1/render`, and saves the PDF to disk. You can adapt it to pull data from a database, a CRM, or a spreadsheet.

<CodeGroup>
  ```python Python theme={null}
  import requests
  from datetime import date, timedelta

  BLINK_API_KEY = "bp_xxxxxxxxxxxxxxxxxxxx"

  def render_invoice(invoice_data: dict) -> bytes:
      """Render an invoice to PDF and return the raw bytes."""

      # Build line item rows for the Markdown table
      line_rows = "\n".join(
          f"| {item['description']} | {item['qty']} "
          f"| ${item['unit_price']:.2f} | ${item['qty'] * item['unit_price']:.2f} |"
          for item in invoice_data["line_items"]
      )

      subtotal = sum(
          item["qty"] * item["unit_price"] for item in invoice_data["line_items"]
      )
      tax_rate = invoice_data.get("tax_rate", 0)
      tax_amount = subtotal * tax_rate / 100
      total = subtotal + tax_amount

      markdown = f"""# Invoice

  **{invoice_data['company_name']}**
  {invoice_data['company_address']}
  {invoice_data['company_email']}

  ---

  **Bill To:**
  {invoice_data['client_name']}
  {invoice_data['client_address']}

  | Field        | Detail                      |
  |--------------|-----------------------------|
  | Invoice No.  | {invoice_data['invoice_number']} |
  | Issue Date   | {invoice_data['issue_date']} |
  | Due Date     | {invoice_data['due_date']}  |
  | Status       | Unpaid                      |

  ---

  ## Line Items

  | Description | Qty | Unit Price | Amount |
  |-------------|-----|------------|--------|
  {line_rows}

  ---

  ## Summary

  | | |
  |---|---|
  | Subtotal | ${subtotal:.2f} |
  | Tax ({tax_rate}%) | ${tax_amount:.2f} |
  | **Total Due** | **${total:.2f}** |

  ---

  *Thank you for your business.*
  """

      response = requests.post(
          "https://api.blinkpdf.io/v1/render",
          headers={
              "x-api-key": BLINK_API_KEY,
              "Accept": "application/pdf",
              "Content-Type": "application/json",
          },
          json={
              "markdown": markdown,
              "metadata": {
                  "title": f"Invoice {invoice_data['invoice_number']} — {invoice_data['client_name']}"
              },
          },
      )
      response.raise_for_status()
      return response.content


  # Example usage
  invoice = {
      "company_name": "Acme Design Studio",
      "company_address": "123 Main Street, San Francisco, CA 94105",
      "company_email": "billing@acmedesign.io",
      "client_name": "Globex Corporation",
      "client_address": "742 Evergreen Terrace, Springfield, IL 62701",
      "invoice_number": "INV-1042",
      "issue_date": str(date.today()),
      "due_date": str(date.today() + timedelta(days=30)),
      "tax_rate": 8.5,
      "line_items": [
          {"description": "Brand Strategy Workshop", "qty": 1, "unit_price": 2500.00},
          {"description": "Logo Design (3 concepts)", "qty": 1, "unit_price": 1800.00},
          {"description": "Revision Rounds", "qty": 3, "unit_price": 250.00},
      ],
  }

  pdf_bytes = render_invoice(invoice)

  filename = f"invoice_{invoice['invoice_number'].lower()}.pdf"
  with open(filename, "wb") as f:
      f.write(pdf_bytes)

  print(f"Invoice saved as {filename}")
  ```

  ```javascript Node.js theme={null}
  import { writeFileSync } from "fs";

  const BLINK_API_KEY = "bp_xxxxxxxxxxxxxxxxxxxx";

  function buildLineRows(lineItems) {
    return lineItems
      .map(
        ({ description, qty, unitPrice }) =>
          `| ${description} | ${qty} | $${unitPrice.toFixed(2)} | $${(qty * unitPrice).toFixed(2)} |`
      )
      .join("\n");
  }

  async function renderInvoice(invoiceData) {
    const subtotal = invoiceData.lineItems.reduce(
      (sum, item) => sum + item.qty * item.unitPrice,
      0
    );
    const taxRate = invoiceData.taxRate ?? 0;
    const taxAmount = subtotal * (taxRate / 100);
    const total = subtotal + taxAmount;

    const markdown = `# Invoice

  **${invoiceData.companyName}**
  ${invoiceData.companyAddress}
  ${invoiceData.companyEmail}

  ---

  **Bill To:**
  ${invoiceData.clientName}
  ${invoiceData.clientAddress}

  | Field       | Detail                   |
  |-------------|--------------------------|
  | Invoice No. | ${invoiceData.invoiceNumber} |
  | Issue Date  | ${invoiceData.issueDate}  |
  | Due Date    | ${invoiceData.dueDate}    |
  | Status      | Unpaid                   |

  ---

  ## Line Items

  | Description | Qty | Unit Price | Amount |
  |-------------|-----|------------|--------|
  ${buildLineRows(invoiceData.lineItems)}

  ---

  ## Summary

  | | |
  |---|---|
  | Subtotal | $${subtotal.toFixed(2)} |
  | Tax (${taxRate}%) | $${taxAmount.toFixed(2)} |
  | **Total Due** | **$${total.toFixed(2)}** |

  ---

  *Thank you for your business.*
  `;

    const response = await fetch("https://api.blinkpdf.io/v1/render", {
      method: "POST",
      headers: {
        "x-api-key": BLINK_API_KEY,
        Accept: "application/pdf",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        markdown,
        metadata: {
          title: `Invoice ${invoiceData.invoiceNumber} — ${invoiceData.clientName}`,
        },
      }),
    });

    if (!response.ok) {
      throw new Error(`Render failed: ${response.status} ${response.statusText}`);
    }

    return Buffer.from(await response.arrayBuffer());
  }

  // Example usage
  const invoice = {
    companyName: "Acme Design Studio",
    companyAddress: "123 Main Street, San Francisco, CA 94105",
    companyEmail: "billing@acmedesign.io",
    clientName: "Globex Corporation",
    clientAddress: "742 Evergreen Terrace, Springfield, IL 62701",
    invoiceNumber: "INV-1042",
    issueDate: new Date().toISOString().split("T")[0],
    dueDate: new Date(Date.now() + 30 * 86400000).toISOString().split("T")[0],
    taxRate: 8.5,
    lineItems: [
      { description: "Brand Strategy Workshop", qty: 1, unitPrice: 2500.0 },
      { description: "Logo Design (3 concepts)", qty: 1, unitPrice: 1800.0 },
      { description: "Revision Rounds", qty: 3, unitPrice: 250.0 },
    ],
  };

  const pdfBytes = await renderInvoice(invoice);
  const filename = `invoice_${invoice.invoiceNumber.toLowerCase()}.pdf`;
  writeFileSync(filename, pdfBytes);
  console.log(`Invoice saved as ${filename}`);
  ```
</CodeGroup>

## Financial Reports

The same template pattern works for any structured financial document. Common report types and their natural Markdown structures:

| Report Type        | Key Markdown Elements                  |
| ------------------ | -------------------------------------- |
| Monthly P\&L       | H2 sections per category, totals table |
| Budget vs. Actuals | Two-column comparison table            |
| Expense Summary    | Line items table grouped by category   |
| Client Statement   | Chronological transactions table       |
| Annual Report      | Multi-section with H1/H2/H3 hierarchy  |

<Tip>
  For multi-page reports, use horizontal rules (`---`) to visually separate major sections. Blink PDF automatically handles page breaks, so you don't need to manage pagination manually.
</Tip>

## Consistent Branding Across Documents

To maintain a uniform look across all your invoices and reports:

* **Apply a [theme](/configuration/themes)** — set `"theme": "invoice"` for invoices and receipts, or `"report-clean"` / `"report-executive"` for financial reports, so every document shares one design without repeating styling rules.
* **Keep header structure identical** across templates — company name, address, and logo alt text in the same position every time.
* **Use the same section hierarchy** — H1 for the document title, H2 for major sections, H3 for subsections. Blink PDF applies consistent typographic styles to each level.
* **Standardize table column widths** by keeping column headers concise. Markdown tables auto-size based on content, so shorter headers produce tidier columns.
* **Set `metadata.title` programmatically** using a consistent naming convention (e.g., `"INV-{number} — {client}"`) so PDFs are identifiable in any file system or document management tool.

<Info>
  Need to generate dozens of invoices at once — for example, at month-end billing? See the [Batch Processing guide](/guides/batch-processing) to learn how to fire concurrent render requests within your plan's rate limits.
</Info>
