<!-- SKILL-VERSION: library/invoice-v1 3a76850@2026-10-04T07:41:12+10:00 -->
> **Skill version:** `3a76850@2026-10-04T07:41:12+10:00` (`library/invoice-v1`).
> If you have a cached copy of this skill with a different version token,
> discard it and use this copy. Re-fetch this URL at the start of each
> session to detect updates.

# makesPDF — Invoice skill `invoice-v1`

> Version: `invoice-v1`. **Immutable** — this file never changes after
> release. Fixes land in `invoice-v2`, served alongside this file. If a
> newer version exists, it is noted at the top of this file; this URL
> keeps serving regardless.

> **Note to AI agents:** this document is served over HTTP at
> `https://makespdf.com/skills/library/invoice-v1.md` (or
> `http://localhost:8788/skills/library/invoice-v1.md` in dev). It is
> **not a local file.** Re-fetch it with a web fetch / HTTP tool — do
> **not** call your filesystem `Read` tool with `/skills/...`. Paths
> that begin with `/api/v1/` or `/skills/` below are URL paths relative
> to the makespdf origin, not filesystem paths.

Read [`/skills/pdf-template-author.md`](https://makespdf.com/skills/pdf-template-author.md)
first for the builder DSL, style properties, and the preview/render loop.
This file is the invoice-specific companion: which fields to use, which
library template to start from, and a worked fetch, fill, render example.

## Canonical fields (field registry)

Source: `docs/field-registry.md` and
`apps/web/src/utils/field-registry.ts` (`documentTypes` containing
`"invoice"`). Use these canonical ids when naming data keys so templates,
field mapping, and future tooling agree on what a field means. The
`Aliases` column lists common incoming names the registry already
recognises — prefer the canonical id for new data.

### Document identity

| Canonical id       | Label            | Type / format | Common aliases                              |
| ------------------ | ---------------- | ------------- | ------------------------------------------- |
| `invoice-number`   | Invoice Number   | string        | invoicenumber, invoiceno, invoiceid, number |
| `document-date`    | Date             | date          | date, invoicedate, issuedate                |
| `due-date`         | Due Date         | date          | duedate, paymentdue, deadline               |
| `payment-terms`    | Payment Terms    | string        | paymentterms, terms, netterms               |
| `reference-number` | Reference Number | string        | ref, ponumber, contractnumber               |
| `currency`         | Currency         | code          | currencycode, cur                           |
| `status`           | Status           | string        | status, invoicestatus                       |

### Seller (your company)

| Canonical id          | Label               | Type / format | Common aliases                        |
| --------------------- | ------------------- | ------------- | ------------------------------------- |
| `seller-name`         | Company Name        | string        | companyname, vendorname, suppliername |
| `seller-address`      | Company Address     | string        | companyaddress, vendoraddress         |
| `seller-phone`        | Phone               | phone         | phone, mobile, tel                    |
| `seller-email`        | Email               | email         | email, companyemail                   |
| `seller-website`      | Website             | url           | website, url                          |
| `seller-tax-id`       | Tax ID              | tax-id        | gstin, vat, ein, abn, taxnumber       |
| `seller-registration` | Registration Number | string        | regnumber, companyreg                 |
| `seller-logo`         | Logo                | url           | logo, companylogo                     |

### Buyer (your customer)

| Canonical id           | Label           | Type / format | Common aliases                      |
| ---------------------- | --------------- | ------------- | ----------------------------------- |
| `buyer-name`           | Client Name     | string        | customername, billtoname, client    |
| `buyer-address`        | Client Address  | string        | customeraddress, billingaddress     |
| `buyer-contact`        | Contact Name    | string        | contactname, attn, attention        |
| `buyer-email`          | Client Email    | email         | customeremail, billingemail         |
| `buyer-phone`          | Client Phone    | phone         | customerphone, contactphone         |
| `buyer-tax-id`         | Client Tax ID   | tax-id        | buyergstin, clientvatnumber         |
| `buyer-account-number` | Account Number  | string        | accountnumber, customerid, clientid |
| `ship-to-address`      | Ship To Address | string        | shipto, shippingaddress             |

### Line items

| Canonical id       | Label       | Type / format | Common aliases                   |
| ------------------ | ----------- | ------------- | -------------------------------- |
| `item-description` | Description | string        | description, itemname, product   |
| `item-quantity`    | Quantity    | integer       | qty, quantity, count             |
| `item-unit-price`  | Unit Price  | currency      | unitprice, price, rate           |
| `item-unit`        | Unit        | code          | uom, unitofmeasure               |
| `item-discount`    | Discount    | currency      | discount, rebate                 |
| `item-tax-rate`    | Tax Rate    | percentage    | taxrate, vatrate, gstrate        |
| `item-line-total`  | Line Total  | currency      | linetotal, amount, total         |
| `item-sku`         | SKU         | code          | sku, itemcode, partnumber, hsncd |
| `item-hours`       | Hours       | number        | hours, billablehours             |

### Totals

| Canonical id     | Label       | Type / format | Common aliases               |
| ---------------- | ----------- | ------------- | ---------------------------- |
| `subtotal`       | Subtotal    | currency      | subtotal, netamount          |
| `discount-total` | Discount    | currency      | discounttotal, totaldiscount |
| `tax-rate`       | Tax Rate    | percentage    | taxrate, vatrate             |
| `tax-amount`     | Tax Amount  | currency      | tax, vat, gst, salestax      |
| `shipping-cost`  | Shipping    | currency      | shipping, freight            |
| `total`          | Total       | currency      | grandtotal, totaldue         |
| `amount-due`     | Amount Due  | currency      | balancedue, outstanding      |
| `amount-paid`    | Amount Paid | currency      | paid, totalpaid              |

### Payment detail and notes

| Canonical id           | Label                | Type / format | Common aliases                 |
| ---------------------- | -------------------- | ------------- | ------------------------------ |
| `payment-method`       | Payment Method       | string        | paymentmethod, payvia          |
| `bank-name`            | Bank Name            | string        | bankname, bank                 |
| `bank-account`         | Account Number       | string        | bankaccount, acctno            |
| `iban`                 | IBAN                 | string        | iban                           |
| `swift-bic`            | SWIFT / BIC          | string        | swift, bic, routingnumber, bsb |
| `notes`                | Notes                | string        | notes, memo, remarks           |
| `terms-and-conditions` | Terms & Conditions   | string        | terms, tandcs                  |
| `payment-instructions` | Payment Instructions | string        | howtopay, bankdetails          |

## Library template

Start from **`invoice-classic`** (formal bordered B2B invoice: header
bar, remit-to + meta grid, bill-to block, itemised table, aligned
totals, payment-instructions panel with scan-to-pay QR, notes). Other
invoice variations exist (`invoice-modern`, `invoice-compact`,
`invoice-with-logo`) — list them with
`GET /api/v1/templates?owner=library&category=invoice`.

## Worked example: fetch, fill, render

All calls need `Authorization: Bearer $MAKESPDF_API_KEY`.

**1. Fetch the template's DSL and sample data.**

```sh
curl -s -H "Authorization: Bearer $MAKESPDF_API_KEY" \
  "https://makespdf.com/api/v1/templates/invoice-classic"
# -> { templateId, name, dsl, sampleData, ... }
```

**2. Fill.** Start from the returned `sampleData`, keep its keys, replace
the values with the real invoice. Map incoming field names to the
canonical ids above first (e.g. `gstin` -> seller Tax ID,
`qty` -> Quantity). Send ISO dates (`"2026-09-01"`) and raw numbers for
money — format with `{{ total | currency }}` in the DSL or pre-format as
the sample does. Minimal override shape:

```json
{
  "invoiceNumber": "INV-2026-0417",
  "date": "2026-09-01",
  "dueDate": "2026-10-01",
  "paymentTerms": "Net 30",
  "currency": "USD",
  "vendor": { "name": "TechStar Solutions, Inc." },
  "customer": { "name": "Riverside Manufacturing Holdings, LLC" },
  "items": [{ "description": "Enterprise License", "qty": 1, "total": 12000 }],
  "total": 12979.16,
  "balanceDue": 7979.16
}
```

**3. Render.** Production path is the stored template (billed, 1 credit
per 10 pages):

```sh
curl -s -X POST https://makespdf.com/api/v1/render \
  -H "Authorization: Bearer $MAKESPDF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"templateId": "invoice-classic", "data": {...}}' -o invoice.pdf
```

Iterating on a customised fork? Draft it free with
`POST /api/v1/preview { dsl, data }`, pre-flight with
`POST /api/v1/preview/validate`, then save via
`POST /api/v1/templates { dsl, name }` and render your copy.

## Traps

- Numeric table columns must stay `auto`/`1fr` — never fixed `%` widths
  on Qty / Unit Price / Amount. See the main skill, Grid + Colspan.
- `ship-to-address` belongs on the invoice only when goods ship
  somewhere other than the bill-to address.
- Partial payments: show `amount-paid` and `amount-due`/`balanceDue`
  together; do not overwrite `total`.
