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

# SaaS Invoice

> A professional B2B SaaS invoice template with a dynamic line-items table.

<Frame>
  <img src="https://mintcdn.com/pdf-dyno/pat72jpBFeHUuLAU/images/templates/invoice.png?fit=max&auto=format&n=pat72jpBFeHUuLAU&q=85&s=b439bab2a06344b1c7674e22f756dbf0" alt="SaaS Invoice Preview" width="569" height="737" data-path="images/templates/invoice.png" />
</Frame>

Copy the JSON payload and the Typst code below to generate this SaaS invoice. You can easily adjust the logo and branding color directly in the code.

<CodeGroup>
  ```typst template.typ theme={null}

  // CHANGE BRAND COLOR HERE (e.g., your company's hex code)
  #let brand-color = rgb("#334155")

  #set page(paper: "us-letter", margin: 2cm)
  #set text(font: "Helvetica", size: 11pt, fill: rgb("#111827"))

  // Header: Logo & Document Info
  #grid(
    columns: (1fr, 1fr),
    align(left)[
      // INSERT LOGO HERE (You can also use image("url"))
      #text(size: 24pt, weight: "bold", fill: brand-color)[PDFDyno] \
      #text(size: 10pt, fill: luma(100))[hello\@pdfdyno.com]
    ],
    align(right)[
      #text(size: 24pt, weight: "bold")[INVOICE] \
      #v(5pt)
      *Invoice \#*: #data.invoice_id \
      *Date*: #data.date
    ]
  )

  #v(2cm)

  // Customer Address & Info
  #grid(
    columns: (1fr, 1fr),
    [
      #text(weight: "bold")[Bill To:] \
      #data.customer.name \
      #data.customer.company \
      #data.customer.address
    ],
    []
  )

  #v(1.5cm)

  // Line Items Table
  #table(
    columns: (1fr, auto, auto),
    inset: 12pt,
    stroke: (x, y) => if y == 0 { (bottom: 2pt + black) } else { (bottom: 1pt + rgb("#e5e7eb")) },
    align: (left, right, right),
    
    [*Description*], [*Qty*], [*Amount*],
    
    ..data.items.map(item => (
      item.description,
      item.qty,
      item.amount
    )).flatten()
  )

  #v(1cm)

  // Summary Section
  #align(right)[
    #grid(
      columns: (auto, auto),
      gutter: 15pt,
      align: right,
      [Subtotal:], [#data.summary.subtotal],
      [Tax (19%):], [#data.summary.tax],
      [*Total Due:*], [#block(fill: rgb("#f3f4f6"), inset: 8pt, radius: 4pt)[
        *#text(size: 14pt)[#data.summary.total]*
      ]]
    )
  ]

  #v(1fr)

  // Footer
  #align(center)[
    #text(size: 9pt, fill: luma(100))[Thank you for your business. Payment is due within 14 days.]
  ]
  ```

  ```json data.json theme={null}
  {
    "invoice_id": "INV-2026-042",
    "date": "2026-08-05",
    "customer": {
      "name": "Jane Doe",
      "company": "Acme Corp",
      "address": "123 Startup Ave, San Francisco, CA"
    },
    "items": [
      {
        "description": "Serverless API Hosting (Pro Plan)",
        "qty": "1",
        "amount": "$49.00"
      },
      {
        "description": "Overage: 20,000 PDF Generations",
        "qty": "1",
        "amount": "$100.00"
      }
    ],
    "summary": {
      "subtotal": "$149.00",
      "tax": "$28.31",
      "total": "$177.31"
    }
  }
  ```

  ```bash cURL (Try It) theme={null}
  # 1. Save the Typst code from the tab above as 'template.typ'
  # 2. Save the JSON data from the tab above as 'data.json'

  # 3. Combine them and call the API (requires jq)
  jq -n \
    --arg t "$(cat template.typ)" \
    --argjson d "$(<data.json)" \
    '{ "data": $d, "template": $t }' > request.json

  curl -X POST https://api.pdfdyno.com/v1/pdf/generate \
    -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d @request.json \
    --output invoice.pdf
  ```
</CodeGroup>
