Skip to main content

Generic XML Invoice

A vendor-neutral XML invoice shape covering the fields most senders carry: header, party blocks, addresses, payment terms, line items, tax detail, invoice-level charges, and cash discounts. Use this seed as a starting point for any custom XML dialect whose structure roughly matches the shape below — clone it, adjust element names / XPaths, and go.

Config item ID

generic-xml-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

  • Split dates. Dates are split into YEAR, MONTH, and DAY sub-elements. The seed's date locators assemble the canonical YYYY-MM-DD string inline with XPath's concat() function.
  • Amounts. Amount elements carry their sign as part of the value: positive amounts are just the number (100.00), negative amounts have a leading minus (-25.00). No SIGN attribute; the locator is a plain number(./NET_AMOUNT).
  • Flat references. ORDER_REFERENCE and CONTRACT_REFERENCE are flat text elements on the header — no nested REFERENCE_NUMBER child.
  • Ship-to and bill-to. Both party blocks nest their own NAME and POSTAL_ADDRESS. Bill-to lives under BUYER_PARTY; ship-to lives under DELIVERY_PARTY. The buyer party's own NAME becomes the canonical customer name; the address's NAME becomes the bill-to (or ship-to) party name.
  • Taxes, charges, and discounts are separate top-level containers. Each has its own element (TAXES/TAX, CHARGES/CHARGE, DISCOUNTS/DISCOUNT) and its own loop.

Loops

invoice loop ← recordType: header, xpath: /INVOICE
seller loop ← recordType: none, scope: sender xpath: ./PARTIES/SELLER_PARTY
buyer loop ← recordType: none, scope: receiver xpath: ./PARTIES/BUYER_PARTY
billto loop ← recordType: none, scope: bill_to xpath: ./PARTIES/BUYER_PARTY/POSTAL_ADDRESS
shipto loop ← recordType: none, scope: ship_to xpath: ./PARTIES/DELIVERY_PARTY/POSTAL_ADDRESS
payment loop ← recordType: none, scope: payment xpath: ./PAYMENT_TERMS
line loop ← recordType: line xpath: ./DETAILS/ROW
taxes loop ← recordType: taxes xpath: ./TAXES/TAX
charges loop ← recordType: charges xpath: ./CHARGES/CHARGE
discounts loop ← recordType: discounts, xpath: ./DISCOUNTS/DISCOUNT

Fields

Fields are grouped by loop. XPaths are relative to the loop's context node, so ./STREET on a field under the billto loop resolves to BUYER_PARTY/POSTAL_ADDRESS/STREET. Date locators are summarized here — see the seed itself for the exact XPath expression.

Header (loop invoice)

XPath (relative to loop)FieldTypeDescription
./HEADER/INVOICE_NUMBERheader.invoice_numbertextSender-issued invoice number.
concat(./HEADER/INVOICE_DATE/DATE/YEAR, "-", MONTH, "-", DAY)header.invoice_datedateDate the invoice was issued.
concat(./HEADER/DUE_DATE/DATE/YEAR, "-", MONTH, "-", DAY)header.due_datedateDate the full amount is due.
concat(./HEADER/DELIVERY_DATE/DATE/YEAR, "-", MONTH, "-", DAY)header.delivery_datedateDate the goods or services were delivered.
./HEADER/CURRENCY_CODEheader.currency_codetextISO 4217 currency code.
./HEADER/ORDER_REFERENCEheader.order_number_1textBuyer purchase order number.
./HEADER/CONTRACT_REFERENCEheader.contract_numbertextMaster or framework contract reference.
./PARTIES/BUYER_PARTY/TAX_IDheader.customer_tax_idtextBuyer VAT / tax registration number.
number(./HEADER/NET_AMOUNT)header.net_amountnumberInvoice-level net (pre-tax) total.
number(./HEADER/VAT_TOTAL)header.tax_amountnumberInvoice-level total tax.
number(./HEADER/GROSS_AMOUNT)header.gross_amountnumberInvoice-level total gross (net + tax).

Supplier (loop sellersender scope)

XPath (relative to loop)FieldTypeDescription
./NAMEsender.supplier_nametextSupplier / vendor legal name.
./TAX_IDsender.supplier_tax_idtextSupplier VAT / tax registration number.

Customer (loop buyerreceiver scope)

XPath (relative to loop)FieldTypeDescription
./NAMEreceiver.customer_nametextBuyer / customer legal name.

Bill-to address (loop billtobill_to scope)

XPath (relative to loop)FieldTypeDescription
./NAMEbill_to.address_nametextBill-to party name or department.
./STREETbill_to.streettextBill-to street address.
./CITYbill_to.citytextBill-to city.
./POSTAL_CODEbill_to.postal_codetextBill-to postal / ZIP code.
./STATEbill_to.statetextBill-to state or region.
./COUNTRYbill_to.countrytextBill-to country (ISO 3166-1 alpha-2).

Ship-to address (loop shiptoship_to scope)

XPath (relative to loop)FieldTypeDescription
./NAMEship_to.address_nametextShip-to party name or department.
./STREETship_to.streettextShip-to street address.
./CITYship_to.citytextShip-to city.
./POSTAL_CODEship_to.postal_codetextShip-to postal / ZIP code.
./STATEship_to.statetextShip-to state or region.
./COUNTRYship_to.countrytextShip-to country (ISO 3166-1 alpha-2).

Payment (loop paymentpayment scope)

XPath (relative to loop)FieldTypeDescription
./PAYMENT_REFERENCEpayment.reference_numbertextPayment reference the buyer should quote when remitting.
./PAYMENT_METHODpayment.payment_methodtextPreferred payment method (ACH, wire, cheque, …).
./BANK/ACCOUNT_NUMBERpayment.bank_accounttextSupplier bank account (IBAN or local format).
./BANK/BANK_NAMEpayment.bank_nametextSupplier bank name.

Line items (loop lineline records)

XPath (relative to loop)FieldTypeDescription
./PRODUCT_CODEline.product_code_1textSupplier product / SKU code.
./DESCRIPTIONline.product_nametextProduct or service description.
./QUANTITYline.quantitynumberLine quantity.
./QUANTITY/@UNITline.unit_of_measuretextUnit of measure (EA, BX, KG, …).
./UNIT_PRICEline.unit_pricenumberPrice per unit.
number(./NET_AMOUNT)line.net_amountnumberLine net (pre-tax) amount.
./VAT_RATEline.tax_ratenumberLine tax rate as a percentage.
number(./VAT_AMOUNT)line.tax_amountnumberLine tax amount.
number(./GROSS_AMOUNT)line.gross_amountnumberLine gross amount (net + tax).

Taxes (loop taxestaxes records)

One record per TAXES/TAX element.

XPath (relative to loop)FieldTypeDescription
./TAX_NAMEtaxes.tax_nametextTax category or jurisdiction name.
./TAX_RATEtaxes.tax_ratenumberTax rate as a percentage.
number(./BASE_AMOUNT)taxes.tax_base_amountnumberAmount the tax rate is applied to.
number(./TAX_AMOUNT)taxes.tax_amountnumberTax amount for this category.

Charges (loop chargescharges records)

Invoice-level charges (freight, handling, insurance, …). One record per CHARGES/CHARGE element.

XPath (relative to loop)FieldTypeDescription
./DESCRIPTIONcharges.charge_nametextCharge description (freight, handling, insurance, …).
number(./AMOUNT)charges.charge_amountnumberCharge amount.

Discounts (loop discountsdiscounts records)

Cash discounts (early-payment, promotional, …). One record per DISCOUNTS/DISCOUNT element. Discount amounts are stored as the value they carry — negative amounts appear as -25.00.

The deadline for taking the discount can be expressed two ways: as an absolute date (DISCOUNT_DUE_DATE) or as a term relative to a basis date (DUE_DATE_BASIS + DUE_DATE_PERIOD_VALUE + DUE_DATE_PERIOD_MEASURE, e.g. "10 DAY from invoice date"). Senders that emit both should populate both; downstream processing prefers the absolute date when present.

XPath (relative to loop)FieldTypeDescription
./DESCRIPTIONdiscounts.discount_descriptiontextHuman-readable description of the discount.
./PERCENTAGEdiscounts.discount_ratenumberDiscount rate as a percentage.
number(./AMOUNT)discounts.discount_amountnumberDiscount amount.
./DISCOUNT_DUE_DATEdiscounts.discount_due_datedateAbsolute date on which the discount expires. Canonical YYYY-MM-DD.
./DUE_DATE_BASISdiscounts.due_date_basisdateDate the discount period is counted from (typically the invoice or delivery date). Canonical YYYY-MM-DD.
number(./DUE_DATE_PERIOD_VALUE)discounts.due_date_period_valuenumberNumber of periods from due_date_basis until the discount expires (integer).
./DUE_DATE_PERIOD_MEASUREdiscounts.due_date_period_measuretextUnit for the period value. One of DAY, WEEK, MONTH, YEAR. Map sender-side values (e.g. CII WEE/ANN, EDIFACT D/W) to this set.

Sample file

Download generic-xml-invoice.xml

<?xml version="1.0" encoding="UTF-8"?>
<INVOICE TYPE="Invoice" LANGUAGE_CODE="en">
<HEADER>
<INVOICE_NUMBER>INV-2025-0042</INVOICE_NUMBER>
<INVOICE_TYPE_CODE>380</INVOICE_TYPE_CODE>
<INVOICE_DATE>
<DATE>
<YEAR>2026</YEAR>
<MONTH>07</MONTH>
<DAY>15</DAY>
</DATE>
</INVOICE_DATE>
<DUE_DATE>
<DATE>
<YEAR>2026</YEAR>
<MONTH>08</MONTH>
<DAY>14</DAY>
</DATE>
</DUE_DATE>
<DELIVERY_DATE>
<DATE>
<YEAR>2026</YEAR>
<MONTH>07</MONTH>
<DAY>12</DAY>
</DATE>
</DELIVERY_DATE>
<CURRENCY_CODE>USD</CURRENCY_CODE>
<ORDER_REFERENCE>PO-88190</ORDER_REFERENCE>
<CONTRACT_REFERENCE>MSA-2024-11</CONTRACT_REFERENCE>
<NET_AMOUNT>1250.00</NET_AMOUNT>
<VAT_TOTAL>112.50</VAT_TOTAL>
<GROSS_AMOUNT>1362.50</GROSS_AMOUNT>
</HEADER>

<PARTIES>
<SELLER_PARTY>
<NAME>Northwind Manufacturing LLC</NAME>
<TAX_ID>US-441290</TAX_ID>
<POSTAL_ADDRESS>
<STREET>1500 Foundry Road</STREET>
<CITY>Reno</CITY>
<POSTAL_CODE>89501</POSTAL_CODE>
<STATE>NV</STATE>
<COUNTRY>US</COUNTRY>
</POSTAL_ADDRESS>
</SELLER_PARTY>
<BUYER_PARTY>
<NAME>Contoso Retail Group</NAME>
<TAX_ID>US-849201</TAX_ID>
<POSTAL_ADDRESS>
<NAME>Contoso Accounts Payable</NAME>
<STREET>450 Market Street, Suite 200</STREET>
<CITY>San Francisco</CITY>
<POSTAL_CODE>94105</POSTAL_CODE>
<STATE>CA</STATE>
<COUNTRY>US</COUNTRY>
</POSTAL_ADDRESS>
</BUYER_PARTY>
<DELIVERY_PARTY>
<NAME>Contoso Retail Group</NAME>
<POSTAL_ADDRESS>
<NAME>Contoso Distribution Center</NAME>
<STREET>901 Airport Way</STREET>
<CITY>Reno</CITY>
<POSTAL_CODE>89502</POSTAL_CODE>
<STATE>NV</STATE>
<COUNTRY>US</COUNTRY>
</POSTAL_ADDRESS>
</DELIVERY_PARTY>
</PARTIES>

<PAYMENT_TERMS>
<PAYMENT_REFERENCE>INV-2025-0042</PAYMENT_REFERENCE>
<PAYMENT_METHOD>ACH</PAYMENT_METHOD>
<BANK>
<ACCOUNT_NUMBER>US1234567890</ACCOUNT_NUMBER>
<BANK_NAME>First National Bank</BANK_NAME>
</BANK>
</PAYMENT_TERMS>

<TAXES>
<TAX>
<TAX_NAME>CA State</TAX_NAME>
<TAX_RATE>6.00</TAX_RATE>
<BASE_AMOUNT>1250.00</BASE_AMOUNT>
<TAX_AMOUNT>75.00</TAX_AMOUNT>
</TAX>
<TAX>
<TAX_NAME>County Levy</TAX_NAME>
<TAX_RATE>3.00</TAX_RATE>
<BASE_AMOUNT>1250.00</BASE_AMOUNT>
<TAX_AMOUNT>37.50</TAX_AMOUNT>
</TAX>
</TAXES>

<CHARGES>
<CHARGE>
<DESCRIPTION>Freight</DESCRIPTION>
<AMOUNT>45.00</AMOUNT>
</CHARGE>
<CHARGE>
<DESCRIPTION>Handling &amp; pallet</DESCRIPTION>
<AMOUNT>15.00</AMOUNT>
</CHARGE>
</CHARGES>

<DISCOUNTS>
<DISCOUNT>
<DESCRIPTION>2/10 Net 30 early payment</DESCRIPTION>
<PERCENTAGE>2.00</PERCENTAGE>
<AMOUNT>-25.00</AMOUNT>
<DISCOUNT_DUE_DATE>2026-07-25</DISCOUNT_DUE_DATE>
<DUE_DATE_BASIS>2026-07-15</DUE_DATE_BASIS>
<DUE_DATE_PERIOD_VALUE>10</DUE_DATE_PERIOD_VALUE>
<DUE_DATE_PERIOD_MEASURE>DAY</DUE_DATE_PERIOD_MEASURE>
</DISCOUNT>
</DISCOUNTS>

<DETAILS>
<ROW>
<LINE_ID>1</LINE_ID>
<PRODUCT_CODE>SKU-4471</PRODUCT_CODE>
<DESCRIPTION>Stainless Bolt M6 x 20 (box of 100)</DESCRIPTION>
<QUANTITY UNIT="BX">5</QUANTITY>
<UNIT_PRICE>85.00</UNIT_PRICE>
<NET_AMOUNT>425.00</NET_AMOUNT>
<VAT_RATE>9.00</VAT_RATE>
<VAT_AMOUNT>38.25</VAT_AMOUNT>
<GROSS_AMOUNT>463.25</GROSS_AMOUNT>
</ROW>
<ROW>
<LINE_ID>2</LINE_ID>
<PRODUCT_CODE>SKU-4472</PRODUCT_CODE>
<DESCRIPTION>Stainless Nut M6 (box of 200)</DESCRIPTION>
<QUANTITY UNIT="BX">3</QUANTITY>
<UNIT_PRICE>55.00</UNIT_PRICE>
<NET_AMOUNT>165.00</NET_AMOUNT>
<VAT_RATE>9.00</VAT_RATE>
<VAT_AMOUNT>14.85</VAT_AMOUNT>
<GROSS_AMOUNT>179.85</GROSS_AMOUNT>
</ROW>
<ROW>
<LINE_ID>3</LINE_ID>
<PRODUCT_CODE>SKU-9013</PRODUCT_CODE>
<DESCRIPTION>Vibration Damper Kit</DESCRIPTION>
<QUANTITY UNIT="EA">2</QUANTITY>
<UNIT_PRICE>330.00</UNIT_PRICE>
<NET_AMOUNT>660.00</NET_AMOUNT>
<VAT_RATE>9.00</VAT_RATE>
<VAT_AMOUNT>59.40</VAT_AMOUNT>
<GROSS_AMOUNT>719.40</GROSS_AMOUNT>
</ROW>
</DETAILS>
</INVOICE>

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. Split dates round-trip as YYYY-MM-DD; amounts extract exactly as they appear in the source (negative amounts keep their leading minus sign).