Skip to main content
This example demonstrates a complete, production-ready UBL 2.1 invoice with all major components including supplier and customer parties, delivery information, payment terms, tax calculations, and multiple invoice lines.

Full Invoice Example

import {
  Invoice,
  InvoiceLine,
  Item,
  Price,
  TaxTotal,
  TaxSubtotal,
  TaxCategory,
  TaxScheme,
  ClassifiedTaxCategory,
  LegalMonetaryTotal,
  AccountingSupplierParty,
  AccountingCustomerParty,
  Party,
  PartyTaxScheme,
  PartyLegalEntity,
  PartyName,
  PostalAddress,
  Country,
  Contact,
  SellersItemIdentification,
  Delivery,
  DeliveryLocation,
  Address,
  PaymentMeans,
  PaymentTerms,
} from 'ubl-builder';

const invoiceOptions = {
  enviroment: '1', // Production environment
  issuer: {
    prefix: 'INV',
    resolutionNumber: '321654987',
    startDate: '2024-01-01',
    endDate: '2025-12-31',
    startRange: '1000',
    endRange: '10000',
    technicalKey: 'tech-key-prod-123',
  },
  software: {
    id: 'soft-prod-123',
    pin: 'prod-pin-987654321',
    providerNit: '900123456-1',
  },
};

const invoice = new Invoice('INV-2026-001', invoiceOptions);

// Basic invoice properties
invoice.setDefaultProperties();
invoice.setID('INV-2026-001');
invoice.setUBLVersionID('UBL 2.1');
invoice.setIssueDate('2026-03-06');
invoice.setIssueTime('14:30:00-05:00');
invoice.setInvoiceTypeCode('01'); // Standard invoice
invoice.setDocumentCurrencyCode('USD');
invoice.setDueDate('2026-04-05'); // 30 days payment term
invoice.addNote('Payment due within 30 days of invoice date');
invoice.addNote('Bank transfer preferred', { languageID: 'en' });

// Invoice period
invoice.addInvoicePeriod({
  startDate: '2026-02-01',
  endDate: '2026-02-28',
});

// Create supplier party (seller)
const supplierTaxScheme = new PartyTaxScheme({
  registrationName: 'Acme Corporation Inc',
  companyID: '900123456',
  taxScheme: new TaxScheme({
    id: '01',
    name: 'VAT',
  }),
});

const supplierLegalEntity = new PartyLegalEntity({
  registrationName: 'Acme Corporation Inc',
  companyID: '900123456-1',
});

const supplierAddress = new PostalAddress({
  streetName: '123 Business Street',
  cityName: 'New York',
  postalZone: '10001',
  countrySubentity: 'NY',
  country: new Country({
    identificationCode: 'US',
    name: 'United States',
  }),
});

const supplierContact = new Contact({
  name: 'John Smith',
  telephone: '+1-555-0100',
  electronicMail: '[email protected]',
});

const supplierParty = new Party({
  partyNames: [new PartyName({ name: 'Acme Corporation' })],
  postalAddress: supplierAddress,
  partyTaxSchemes: [supplierTaxScheme],
  partyLegalEntities: [supplierLegalEntity],
  contact: supplierContact,
} as any);

const accountingSupplierParty = new AccountingSupplierParty({
  party: supplierParty,
});

invoice.setAccountingSupplierParty(accountingSupplierParty);

// Create customer party (buyer)
const customerTaxScheme = new PartyTaxScheme({
  registrationName: 'Global Tech Solutions LLC',
  companyID: '800987654',
  taxScheme: new TaxScheme({
    id: '01',
    name: 'VAT',
  }),
});

const customerLegalEntity = new PartyLegalEntity({
  registrationName: 'Global Tech Solutions LLC',
  companyID: '800987654-3',
});

const customerAddress = new PostalAddress({
  streetName: '456 Tech Avenue',
  cityName: 'San Francisco',
  postalZone: '94105',
  countrySubentity: 'CA',
  country: new Country({
    identificationCode: 'US',
    name: 'United States',
  }),
});

const customerContact = new Contact({
  name: 'Jane Doe',
  telephone: '+1-555-0200',
  electronicMail: '[email protected]',
});

const customerParty = new Party({
  partyNames: [new PartyName({ name: 'Global Tech Solutions' })],
  postalAddress: customerAddress,
  partyTaxSchemes: [customerTaxScheme],
  partyLegalEntities: [customerLegalEntity],
  contact: customerContact,
} as any);

const accountingCustomerParty = new AccountingCustomerParty({
  party: customerParty,
});

invoice.setAccountingCustomerParty(accountingCustomerParty);

// Delivery information
const deliveryAddress = new Address({
  streetName: '456 Tech Avenue',
  cityName: 'San Francisco',
  postalZone: '94105',
  countrySubentity: 'CA',
  country: new Country({
    identificationCode: 'US',
    name: 'United States',
  }),
});

const deliveryLocation = new DeliveryLocation({
  address: deliveryAddress,
});

const delivery = new Delivery({
  actualDeliveryDate: '2026-02-28',
  deliveryLocation: deliveryLocation,
});

invoice.addDelivery(delivery);

// Payment means
const paymentMeans = new PaymentMeans({
  paymentMeansCode: '31', // Wire transfer
  paymentID: 'INV-2026-001',
});

invoice.addPaymentMeans(paymentMeans);

// Tax configuration
const taxScheme = new TaxScheme({
  id: '01',
  name: 'VAT',
});

const classifiedTaxCategory = new ClassifiedTaxCategory({
  id: 'S',
  percent: '10.00',
  taxScheme: taxScheme,
});

// Invoice Line 1: Professional Services
const item1 = new Item({
  name: 'Software Development Services',
  descriptions: ['Full-stack development for Q1 2026', 'Includes frontend and backend work'],
  sellersItemIdentification: new SellersItemIdentification({
    id: 'SERV-DEV-001',
  }),
  classifiedTaxCategory: classifiedTaxCategory,
} as any);

const price1 = new Price({
  priceAmount: '5000.00',
});

const invoiceLine1 = new InvoiceLine({
  id: '1',
  invoicedQuantity: '160',
  lineExtensionAmount: '8000.00',
  item: item1,
  price: price1,
} as any);

invoice.addInvoiceLine(invoiceLine1);

// Invoice Line 2: Hardware
const item2 = new Item({
  name: 'Enterprise Server',
  descriptions: ['Dell PowerEdge R750', '2x Intel Xeon processors, 128GB RAM'],
  sellersItemIdentification: new SellersItemIdentification({
    id: 'HW-SRV-750',
  }),
  classifiedTaxCategory: classifiedTaxCategory,
} as any);

const price2 = new Price({
  priceAmount: '12000.00',
});

const invoiceLine2 = new InvoiceLine({
  id: '2',
  invoicedQuantity: '1',
  lineExtensionAmount: '12000.00',
  item: item2,
  price: price2,
} as any);

invoice.addInvoiceLine(invoiceLine2);

// Invoice Line 3: Software Licenses
const item3 = new Item({
  name: 'Annual Software License',
  descriptions: ['Enterprise tier subscription', 'Includes 24/7 support'],
  sellersItemIdentification: new SellersItemIdentification({
    id: 'LIC-ENT-001',
  }),
  classifiedTaxCategory: classifiedTaxCategory,
} as any);

const price3 = new Price({
  priceAmount: '2400.00',
});

const invoiceLine3 = new InvoiceLine({
  id: '3',
  invoicedQuantity: '5',
  lineExtensionAmount: '12000.00',
  item: item3,
  price: price3,
} as any);

invoice.addInvoiceLine(invoiceLine3);

// Calculate totals
const lineExtensionAmount = 8000.00 + 12000.00 + 12000.00; // 32000.00
const taxRate = 0.10; // 10%
const taxAmount = (lineExtensionAmount * taxRate).toFixed(2); // 3200.00
const payableAmount = (lineExtensionAmount + parseFloat(taxAmount)).toFixed(2); // 35200.00

// Tax category for totals
const taxCategory = new TaxCategory({
  id: 'S',
  percent: '10.00',
  taxScheme: taxScheme,
});

// Tax subtotal
const taxSubtotal = new TaxSubtotal({
  taxableAmount: lineExtensionAmount.toFixed(2),
  taxAmount: taxAmount,
  taxCategory: taxCategory,
});

// Tax total
const taxTotal = new TaxTotal({
  taxAmount: taxAmount,
  taxSubtotals: [taxSubtotal],
});

invoice.addTaxTotal(taxTotal);

// Legal monetary total
const legalMonetaryTotal = new LegalMonetaryTotal({
  lineExtensionAmount: lineExtensionAmount.toFixed(2),
  taxExclusiveAmount: lineExtensionAmount.toFixed(2),
  taxInclusiveAmount: payableAmount,
  payableAmount: payableAmount,
});

invoice.setLegalMonetaryTotal(legalMonetaryTotal);

// Set line count
invoice.setLineCountNumeric('3');

// Generate XML
const xml = invoice.getXml(true);
console.log(xml);

// Save to file
import * as fs from 'fs';
fs.writeFileSync('invoice-INV-2026-001.xml', xml);
console.log('Invoice saved to invoice-INV-2026-001.xml');

Invoice Structure Overview

A complete UBL 2.1 invoice includes the following major components:

Key Components Explained

Party Information

Both supplier and customer parties require:
const party = new Party({
  partyNames: [new PartyName({ name: 'Company Name' })],
  postalAddress: postalAddress,
  partyTaxSchemes: [taxScheme],
  partyLegalEntities: [legalEntity],
  contact: contact,
});

Delivery Details

Specify where and when goods/services were delivered:
const delivery = new Delivery({
  actualDeliveryDate: '2026-02-28',
  deliveryLocation: new DeliveryLocation({
    address: deliveryAddress,
  }),
});

Payment Means

Indicate how payment should be made:
const paymentMeans = new PaymentMeans({
  paymentMeansCode: '31', // Wire transfer
  paymentID: 'INV-2026-001',
});
Common Payment Means Codes:
  • 30 - Credit transfer
  • 31 - Debit transfer
  • 48 - Bank card
  • 49 - Direct debit
  • 54 - Credit card

Invoice Lines

Each line represents an item or service:
const invoiceLine = new InvoiceLine({
  id: '1',                           // Line number
  invoicedQuantity: '2',             // Quantity
  lineExtensionAmount: '2000.00',    // Total for this line
  item: item,                        // Item details
  price: price,                      // Unit price
});
Invoice Line Amount Calculation:lineExtensionAmount = invoicedQuantity × price.priceAmountAlways ensure this calculation is correct, as validation may fail if amounts don’t match.

Generated XML Structure

The complete invoice generates a UBL 2.1 XML document with this structure:
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" ...>
  <!-- Header Information -->
  <cbc:UBLVersionID>UBL 2.1</cbc:UBLVersionID>
  <cbc:ID>INV-2026-001</cbc:ID>
  <cbc:IssueDate>2026-03-06</cbc:IssueDate>
  <cbc:IssueTime>14:30:00-05:00</cbc:IssueTime>
  <cbc:DueDate>2026-04-05</cbc:DueDate>
  <cbc:InvoiceTypeCode>01</cbc:InvoiceTypeCode>
  <cbc:DocumentCurrencyCode>USD</cbc:DocumentCurrencyCode>
  
  <!-- Invoice Period -->
  <cac:InvoicePeriod>
    <cbc:StartDate>2026-02-01</cbc:StartDate>
    <cbc:EndDate>2026-02-28</cbc:EndDate>
  </cac:InvoicePeriod>
  
  <!-- Supplier Party -->
  <cac:AccountingSupplierParty>
    <cac:Party>...</cac:Party>
  </cac:AccountingSupplierParty>
  
  <!-- Customer Party -->
  <cac:AccountingCustomerParty>
    <cac:Party>...</cac:Party>
  </cac:AccountingCustomerParty>
  
  <!-- Delivery -->
  <cac:Delivery>...</cac:Delivery>
  
  <!-- Payment Means -->
  <cac:PaymentMeans>...</cac:PaymentMeans>
  
  <!-- Tax Total -->
  <cac:TaxTotal>...</cac:TaxTotal>
  
  <!-- Legal Monetary Total -->
  <cac:LegalMonetaryTotal>...</cac:LegalMonetaryTotal>
  
  <!-- Invoice Lines -->
  <cac:InvoiceLine>...</cac:InvoiceLine>
  <cac:InvoiceLine>...</cac:InvoiceLine>
  <cac:InvoiceLine>...</cac:InvoiceLine>
</Invoice>

Financial Summary

For this example invoice:
DescriptionAmount
Line 1: Software Development (160 hrs × $5,000)$8,000.00
Line 2: Enterprise Server (1 × $12,000)$12,000.00
Line 3: Software Licenses (5 × $2,400)$12,000.00
Subtotal$32,000.00
Tax (10%)$3,200.00
Total Payable$35,200.00
Best Practices for Production Invoices:
  1. Always validate party tax IDs and legal entity information
  2. Include complete contact information for both parties
  3. Specify delivery dates and locations for goods
  4. Add clear payment terms and due dates
  5. Use consistent currency codes throughout
  6. Include detailed item descriptions
  7. Ensure all amounts are calculated correctly
  8. Add meaningful notes for payment instructions

Next Steps

Build docs developers (and LLMs) love