# Reference invoice — one template, every API call

A complete, runnable example of the xgenerate API: an English invoice template
with everything that is hard to get right the first time — image slots, a
repeating line-items table with a **nested** details table per line, computed
line amounts and totals, a payment QR code, a Swiss QR-bill, a letterhead, a
conditional block and an optional watermark. Every file here is what the API really consumed or
produced; drift tests keep them that way.

Base URL: `https://api.xgenerate.io/v2`. The contract itself is at
`/contract` (Swagger UI at `/contract/ui`); this bundle is served at
`/contract/examples/reference-invoice/`.

## Files

| File | What |
|---|---|
| `Invoice-Form-A-CH-EN.docx` | the template (DIN 5008 Form A geometry, English labels) |
| `fields.extracted.json` | exact response of `POST /documents/fields` for it — the empty contract |
| `request.fields.json` | the filled `DocumentFields` envelope: scalars (among them the `invoice.paid` flag that decides the conditional block), three lines each with nested details rows, logo and signature images, EPC payment code, Swiss QR-bill, letterhead |
| `sidecar.bindings.yaml` | the computed bindings (`amount` per line, subtotal, VAT, total) for the multipart `sidecar` part |
| `evaluate.request.json` | the same bindings as a `POST /bindings/evaluate` body, for the JSON transport |
| `watermark.json` | optional `watermark` part (`SAMPLE`) |
| `assets/` | the images, also inlined as `data:` URIs in `request.fields.json` |
| `expected/Invoice-Form-A-CH-EN.pdf`, `expected/page-*.png` | output of step 3 below |
| `run.sh` | the six calls as `curl` commands |

## Run it

In an empty directory, download all inputs and run the six calls:

```bash
example_url=https://api.xgenerate.io/v2/contract/examples/reference-invoice
for file in run.sh Invoice-Form-A-CH-EN.docx request.fields.json \
  sidecar.bindings.yaml evaluate.request.json watermark.json; do
  curl -fsS -O "$example_url/$file" || exit 1
done
XGENERATE_CLIENT_ID=... XGENERATE_CLIENT_SECRET=... bash run.sh
```

1. **`POST /documents/fields`** (multipart, the template as `file`) returns `fields.extracted.json`: every merge field with `value: null` — `invoice.paid`, the flag the conditional block reads, among them — the `invoice.lines` region with one seed row that itself carries the nested `details` region, and the five slots — `images` `company` and `signature`, `qrcodes` `epc`, `qrbills` `payment`, `letterheads` `first`. Slot names are bare on the wire; the template's alt-texts carry the kind prefixes (`logo:`, `qr:`, `qrbill:`, `letterhead:`).
2. **`POST /bindings/evaluate`** with `evaluate.request.json` returns the line amounts (`row.quantity * row.unitPrice`), the subtotal (`sum(invoice.lines[].amount)`), VAT and total — plain decimals with two places. Use this when you call the JSON transport, which has no sidecar part.
3. **`POST /documents/generate`** (multipart) with `file`, `fields` = `request.fields.json`, `sidecar` = `sidecar.bindings.yaml` and `format=PDF` returns the PDF. The computed values are folded in during the call; the Swiss QR-bill is composited onto an appended last page; the response carries a `Content-Disposition` filename and, when anything was skipped, `X-Xgenerate-Warnings`. The request sends `invoice.paid` `"true"`, so the conditional block prints `Payment received - thank you.` under the notes on page 2; send `"false"` and the block is removed. Neither value adds a warning.
4. **`POST /documents/generate`** (JSON) with the template base64-encoded in `content` and the envelope carrying the values from step 2 returns the same document base64-encoded, with `warnings` in the body.
5. `format=DOCX` returns the editable document. The QR-bill slip is PDF-only, so this response carries one `QR_BILL` warning and no slip.
6. The `watermark` part stamps `SAMPLE` diagonally on every page.

## What the template contains, and how to author one in Word

The template was built by a script, but Word works just as well: every element is
standard Word, nothing proprietary.

- **Scalar fields** are `MERGEFIELD` codes: press Ctrl+F9, type `MERGEFIELD invoice.number`, press F9. Names may contain dots; they are the `fields[].name` values. Values are inserted verbatim — send `1'234.50` or `2026-10-08` exactly as it should print. A `null` or empty value leaves the field empty, and a paragraph that held nothing else disappears.
- **A repeating table** is a mail-merge region: a table row whose first cell starts with `MERGEFIELD TableStart:invoice.lines` and whose last cell ends with `MERGEFIELD TableEnd:invoice.lines`, with the row's own merge fields (`position`, `description`, `quantity`, …) in between. The row repeats once per entry in `lists[].value`.
- **A nested table** is a region inside that row: here a small table in the description cell with `TableStart:details` … `TableEnd:details` in its data row. Its rows come from the parent row's `lists[]` entry named `details`. Nested regions are data only — computed bindings reach top-level regions, not nested rows.
- **Image slots** are rectangles (Insert → Shapes) whose alternative text (right-click → *View Alt Text*) is `logo:company` or `logo:signature`. The image is scaled to fit inside the rectangle, keeping its aspect ratio; `value` is a `data:image/png;base64,…` or `data:image/jpeg;base64,…` URI. An unbound slot is removed with a warning.
- **A QR code** is a rectangle with alt-text `qr:epc`; `value` is the raw string to encode. This example encodes an EPC QR code (the SEPA credit-transfer "Girocode" a banking app scans). Any string works — a URL, a vCard, an order reference.
- **The Swiss QR-bill** is a rectangle with alt-text `qrbill:payment` on the SIX payment-part band (bottom 105 mm of the page). It only advertises the slot: the slip is composited onto the PDF after rendering, at the SIX coordinates, so the rectangle is removed. `value` is the JSON payload (creditor, QR-IBAN + `QRR` reference or IBAN + `SCOR`/`NON`, amount, currency, debtor, language `EN`/`DE`/`FR`/`IT`/`RM`, `placement`). This example uses `NEW_PAGE_AT_END`; `LAST_PAGE` draws the slip on the last page and overprints whatever is in the band, so use it only when the template keeps that band clear.
- **The letterhead** is a page-sized PNG painted behind every page; it needs no placeholder, but a small rectangle with alt-text `letterhead:first` makes `/documents/fields` advertise the slot. It is removed at generation. The request sends both `first` and `primary` to paint the artwork edge to edge on every page; extraction advertises only `first`, whose one-image path fits the artwork inside the page margins.
- **Computed values**: the template prints `«invoice.subtotal»`, `«invoice.vatRate» %` and `Total «invoice.currency» «invoice.total»`. The sidecar computes the numbers; the template adds the currency and the `%` sign. Inputs read by expressions must be plain decimals (`2.5`, `1200.00`, `0`), never `1'200.00` or `8.1 %`.
- **A conditional block** is a pair of merge fields around the content: `MERGEFIELD IfStart:invoice.paid` in its own paragraph before the line `Payment received - thank you.` and `MERGEFIELD IfEnd:invoice.paid` in its own paragraph after it. The content stays when the condition is true and is removed when it is false; the markers never print, and a marker paragraph left empty disappears. The condition is an expression in the sidecar's dialect, and the simplest one is a bare flag field whose value is `"true"` or `"false"` — set by the caller, as here, or computed by a sidecar binding such as `invoice.paid: { compute: "invoice.balance == 0 ? 'true' : 'false'" }`. The same pair in the first and last cell of a table row removes the row; around a whole table, the table. A condition the engine cannot decide — an unknown field, a value that is not `true`/`false`, a marker without its partner — keeps the content, removes the markers and adds one `MAIL_MERGE` warning; it never fails the call. `/documents/fields` lists the fields a condition reads, never the markers.

## Fonts

The template declares Arial. The production runtime renders it with Liberation Sans, a
metric-compatible open font: identical advance widths, so the line breaks and page flow are
those of the expected output, with slightly different glyph shapes. The service does not report
this substitution. A template that declares a font the runtime does not have gets a
`FONT_SUBSTITUTION` warning instead, and its pagination may differ from Word.

## Values worth copying

- Invoice in EUR from a Swiss company to a French customer: VAT 0 % with a reverse-charge note, an EPC code for a SEPA transfer and a Swiss QR-bill (QR-bills may be in CHF or EUR).
- `invoice.reference` and the QR-bill's `reference.value` carry the same 27-digit QR reference.
- `invoice.paid` is the flag pattern for conditional content: the bare field name is the condition, `"true"`/`"false"` its value on the wire.
- All company names, addresses and account numbers are fictitious.
