Invoice Schema
Every field in the invoice request JSON: which are required, which are optional, and the validation rule for each.
Money is expressed as decimal strings in the request ("1234.56"), never floats — this avoids float-rounding errors on the wire. Values are parsed into integer minor units internally.
The full machine-readable schema is published at GET /v1/schema/invoice.v1.
Fields
| Field | Required | Rule |
|---|---|---|
docType | no (default invoice) | invoice or receipt |
invoiceNumber | yes | Non-empty string. Caller-supplied — sequential numbering is the caller's legal duty. |
issueDate | yes | ISO 8601 date, e.g. 2026-07-08. |
dueDate | no | ISO 8601 date. |
currency | yes | ISO 4217 code (^[A-Z]{3}$). Determines decimal places — see VAT & Currency. |
locale | no (default en-IE) | BCP 47 tag. Controls number and date formatting. |
seller.name | yes | Non-empty string. |
seller.address | yes | Array of strings, at least one line. |
seller.vatId | yes for a VAT invoice | Required whenever any line has non-zero VAT or reverse_charge. |
seller.email | no | String. |
buyer.name | yes | Non-empty string. |
buyer.address | yes | Array of strings, at least one line. |
buyer.vatId | yes when any line is reverse_charge | Reverse charge requires the customer's VAT ID on the invoice. |
buyer.email | no | String. |
lineItems | yes, ≥1 | Array of line-item objects, minimum 1 item, maximum 200. |
lineItems[].description | yes | Non-empty string. |
lineItems[].quantity | yes | Decimal string, e.g. "10". Must be greater than 0. |
lineItems[].unitPrice | yes | Decimal string, e.g. "100.00". Must be 0 or greater. |
lineItems[].taxCategory | yes | standard, reduced, zero, exempt, or reverse_charge. |
lineItems[].taxRate | yes | Decimal percentage string. Must be "0" for zero, exempt, and reverse_charge — otherwise INVOICE_ERR_VAT_INCONSISTENT. |
taxMode | no (default summary) | summary (VAT grouped by rate) or per_line (VAT shown per line). |
rounding | no (default per_rate) | per_rate (round VAT once per rate group) or per_line (round VAT per line). |
notes | no | Free-text string, printed on the document. |
logo | no | Base64 data URI (data:image/png;base64,...) or a URL. Remote URL fetch is off by default — only data URIs render unless the server operator enables it. |
payment.iban | no | String. |
payment.bic | no | String. |
payment.reference | no | String. |
Tax category is explicit input — the API never infers jurisdiction from country codes. The caller declares the category for each line; the API guarantees correct math and required legal notes for whatever category is declared, and rejects inconsistent combinations.
Full example
json
{
"docType": "invoice",
"invoiceNumber": "2026-0042",
"issueDate": "2026-07-08",
"dueDate": "2026-08-07",
"currency": "EUR",
"locale": "de-DE",
"seller": {
"name": "Nordvik Consulting OÜ",
"address": ["Line 1", "12345 City", "Estonia"],
"vatId": "EE102938475",
"email": "billing@example.com"
},
"buyer": {
"name": "Acme GmbH",
"address": ["Str. 1", "10115 Berlin", "Germany"],
"vatId": "DE987654321"
},
"lineItems": [
{
"description": "Consulting, July",
"quantity": "10",
"unitPrice": "100.00",
"taxCategory": "standard",
"taxRate": "19"
},
{
"description": "E-book (reduced rate)",
"quantity": "1",
"unitPrice": "40.00",
"taxCategory": "reduced",
"taxRate": "7"
}
],
"taxMode": "summary",
"rounding": "per_rate",
"notes": "Payment within 30 days.",
"logo": "data:image/png;base64,iVBOR...",
"payment": { "iban": "EE00...", "bic": "XXXX", "reference": "2026-0042" }
}Next steps
- VAT & Currency — tax categories, rounding modes, supported currencies in full
- Error Codes — validation failures for this schema
- Response Formats — what comes back