Generic JSON Invoice
Single-invoice nested-object body. Header fields at the root; supplier,
customer, bill-to, ship-to, and payment as sub-objects; lines,
taxes, charges, and discounts as arrays. This is the most
common JSON shape for AP integrations.
Config item ID
generic-json-invoice
Pick this in the admin portal when creating a customer file format from a global template, or select the same config item ID via the API.
Notable conventions
- JSONPath everywhere. Loops use
$-rooted paths ($.lines[*],$.supplier); fields use JSONPath relative to the loop's context. Bare identifiers (invoiceNumber) are auto-prefixed with$.soinvoiceNumberand$.invoiceNumbermean the same thing. - 1:1 scope loops for the sub-objects. Supplier lives at
$.supplier; customer at$.customer; bill-to and ship-to at$.billToand$.shipTo; payment at$.payment. Each scope loop's child fields reference that sub-object by name. - 1:many detail loops for
$.lines[*],$.taxes[*],$.charges[*],$.discounts[*]. - Native types round-trip. JSON numbers stay numbers; dates arrive as
ISO strings and parse with
dateFormat: YYYY-MM-DD.
Loops
invoice loop ← recordType: header, jsonpath: $
supplier loop ← recordType: none, scope: sender jsonpath: $.supplier
customer loop ← recordType: none, scope: receiver jsonpath: $.customer
billto loop ← recordType: none, scope: bill_to jsonpath: $.billTo
shipto loop ← recordType: none, scope: ship_to jsonpath: $.shipTo
payment loop ← recordType: none, scope: payment jsonpath: $.payment
line loop ← recordType: line jsonpath: $.lines[*]
taxes loop ← recordType: taxes jsonpath: $.taxes[*]
charges loop ← recordType: charges jsonpath: $.charges[*]
discounts loop ← recordType: discounts jsonpath: $.discounts[*]
Fields
Fields are grouped by loop. Field locators are JSONPaths relative to the
loop's context, so $.street on a field under the billto loop
resolves to $.billTo.street at the root.
Header (loop invoice)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.invoiceNumber | header.invoice_number | text | Sender-issued invoice number. |
$.invoiceDate | header.invoice_date | date | Date the invoice was issued. |
$.dueDate | header.due_date | date | Date the full amount is due. |
$.deliveryDate | header.delivery_date | date | Date the goods or services were delivered. |
$.currency | header.currency_code | text | ISO 4217 currency code. |
$.purchaseOrder | header.order_number_1 | text | Buyer purchase order number. |
$.contractNumber | header.contract_number | text | Master or framework contract reference. |
$.customer.taxId | header.customer_tax_id | text | Buyer VAT / tax registration number. |
$.totals.net | header.net_amount | number | Invoice-level net (pre-tax) total. |
$.totals.tax | header.tax_amount | number | Invoice-level total tax. |
$.totals.gross | header.gross_amount | number | Invoice-level total gross (net + tax). |
Supplier (loop supplier → sender scope)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.name | sender.supplier_name | text | Supplier / vendor legal name. |
$.taxId | sender.supplier_tax_id | text | Supplier VAT / tax registration number. |
$.contact | sender.supplier_contact | text | Supplier contact person or team. |
Customer (loop customer → receiver scope)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.name | receiver.customer_name | text | Buyer / customer legal name. |
$.contact | receiver.customer_contact | text | Buyer contact person or team. |
Bill-to address (loop billto → bill_to scope)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.name | bill_to.address_name | text | Bill-to party name or department. |
$.street | bill_to.street | text | Bill-to street address. |
$.city | bill_to.city | text | Bill-to city. |
$.postalCode | bill_to.postal_code | text | Bill-to postal / ZIP code. |
$.state | bill_to.state | text | Bill-to state or region. |
$.country | bill_to.country | text | Bill-to country (ISO 3166-1 alpha-2). |
Ship-to address (loop shipto → ship_to scope)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.name | ship_to.address_name | text | Ship-to party name or department. |
$.street | ship_to.street | text | Ship-to street address. |
$.city | ship_to.city | text | Ship-to city. |
$.postalCode | ship_to.postal_code | text | Ship-to postal / ZIP code. |
$.state | ship_to.state | text | Ship-to state or region. |
$.country | ship_to.country | text | Ship-to country (ISO 3166-1 alpha-2). |
Payment (loop payment → payment scope)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.reference | payment.reference_number | text | Payment reference the buyer should quote when remitting. |
$.method | payment.payment_method | text | Preferred payment method (ACH, wire, cheque, …). |
$.bankAccount | payment.bank_account | text | Supplier bank account (IBAN or local format). |
$.bankName | payment.bank_name | text | Supplier bank name. |
Line items (loop line → line records)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.productCode | line.product_code_1 | text | Supplier product / SKU code. |
$.productName | line.product_name | text | Product or service description. |
$.quantity | line.quantity | number | Line quantity. |
$.unitPrice | line.unit_price | number | Price per unit. |
$.uom | line.unit_of_measure | text | Unit of measure (EA, BX, KG, …). |
$.netAmount | line.net_amount | number | Line net (pre-tax) amount. |
$.taxRate | line.tax_rate | number | Line tax rate as a percentage. |
$.taxAmount | line.tax_amount | number | Line tax amount. |
$.grossAmount | line.gross_amount | number | Line gross amount (net + tax). |
Taxes (loop taxes → taxes records)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.name | taxes.tax_name | text | Tax category or jurisdiction name. |
$.rate | taxes.tax_rate | number | Tax rate as a percentage. |
$.baseAmount | taxes.tax_base_amount | number | Amount the tax rate is applied to. |
$.amount | taxes.tax_amount | number | Tax amount for this category. |
Charges (loop charges → charges records)
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.name | charges.charge_name | text | Charge description (freight, handling, insurance, …). |
$.amount | charges.charge_amount | text | Charge amount. |
Discounts (loop discounts → discounts records)
The deadline for taking the discount can be expressed as an absolute
date (discountDueDate) or as a term relative to a basis date
(dueDateBasis + dueDatePeriodValue + dueDatePeriodMeasure, e.g.
"10 DAY from invoice date"). Senders that emit both should populate
both; downstream processing prefers the absolute date when present.
| JSONPath (relative to loop) | Field | Type | Description |
|---|---|---|---|
$.description | discounts.discount_description | text | Human-readable description of the discount. |
$.rate | discounts.discount_rate | number | Discount rate as a percentage. |
$.amount | discounts.discount_amount | number | Discount amount. |
$.discountDueDate | discounts.discount_due_date | date | Absolute date on which the discount expires (YYYY-MM-DD). |
$.dueDateBasis | discounts.due_date_basis | date | Date the discount period is counted from (YYYY-MM-DD). |
$.dueDatePeriodValue | discounts.due_date_period_value | number | Number of periods from due_date_basis until the discount expires (integer). |
$.dueDatePeriodMeasure | discounts.due_date_period_measure | text | Unit for the period value. One of DAY, WEEK, MONTH, YEAR. |
Sample file
Download generic-json-invoice.json
{
"invoiceNumber": "INV-2025-0042",
"invoiceDate": "2026-07-15",
"dueDate": "2026-08-14",
"deliveryDate": "2026-07-12",
"currency": "USD",
"purchaseOrder": "PO-88190",
"contractNumber": "MSA-2024-11",
"totals": {
"net": 1250.00,
"tax": 112.50,
"gross": 1362.50
},
"supplier": {
"name": "Northwind Manufacturing LLC",
"taxId": "US-441290",
"contact": "accounts@northwind.example"
},
"customer": {
"name": "Contoso Retail Group",
"taxId": "US-849201",
"contact": "ap@contoso.example"
},
"billTo": {
"name": "Contoso Accounts Payable",
"street": "450 Market Street, Suite 200",
"city": "San Francisco",
"postalCode": "94105",
"state": "CA",
"country": "US"
},
"shipTo": {
"name": "Contoso Distribution Center",
"street": "901 Airport Way",
"city": "Reno",
"postalCode": "89502",
"state": "NV",
"country": "US"
},
"payment": {
"reference": "INV-2025-0042",
"method": "ACH",
"bankAccount": "US1234567890",
"bankName": "First National Bank"
},
"lines": [
{
"productCode": "SKU-4471",
"productName": "Stainless Bolt M6 x 20 (box of 100)",
"quantity": 5,
"unitPrice": 85.00,
"uom": "BX",
"netAmount": 425.00,
"taxRate": 9.00,
"taxAmount": 38.25,
"grossAmount": 463.25
},
{
"productCode": "SKU-4472",
"productName": "Stainless Nut M6 (box of 200)",
"quantity": 3,
"unitPrice": 55.00,
"uom": "BX",
"netAmount": 165.00,
"taxRate": 9.00,
"taxAmount": 14.85,
"grossAmount": 179.85
},
{
"productCode": "SKU-9013",
"productName": "Vibration Damper Kit",
"quantity": 2,
"unitPrice": 330.00,
"uom": "EA",
"netAmount": 660.00,
"taxRate": 9.00,
"taxAmount": 59.40,
"grossAmount": 719.40
}
],
"taxes": [
{ "name": "CA State", "rate": 6.00, "baseAmount": 1250.00, "amount": 75.00 },
{ "name": "County Levy", "rate": 3.00, "baseAmount": 1250.00, "amount": 37.50 }
],
"charges": [
{ "name": "Freight", "amount": 45.00 },
{ "name": "Handling & pallet", "amount": 15.00 }
],
"discounts": [
{
"description": "2/10 Net 30 early payment",
"rate": 2.00,
"amount": 25.00,
"discountDueDate": "2026-07-25",
"dueDateBasis": "2026-07-15",
"dueDatePeriodValue": 10,
"dueDatePeriodMeasure": "DAY"
}
]
}
Expected extraction
Running the sample through this seed extracts 1 invoice with fully
populated header, sender, receiver, bill-to, ship-to, and payment records,
plus 3 line items, 2 tax detail rows, 2 invoice-level charges,
and 1 cash discount. Numeric fields (quantities, prices, amounts) stay
as numbers; dates parse to YYYY-MM-DD.