Complete Example with Tax
import {
Invoice,
InvoiceLine,
Item,
Price,
TaxTotal,
TaxSubtotal,
TaxCategory,
TaxScheme,
ClassifiedTaxCategory,
LegalMonetaryTotal,
SellersItemIdentification,
} from 'ubl-builder';
const invoiceOptions = {
enviroment: '2',
issuer: {
prefix: 'INV',
resolutionNumber: '321654987',
startDate: '2024-01-01',
endDate: '2025-12-31',
startRange: '1000',
endRange: '5000',
technicalKey: 'tech-key-123',
},
software: {
id: 'soft-123',
pin: '123456789',
providerNit: '900123456-1',
},
};
const invoice = new Invoice('INV-002', invoiceOptions);
// Set basic fields
invoice.setDefaultProperties();
invoice.setID('INV-002');
invoice.setUBLVersionID('UBL 2.1');
invoice.setIssueDate('2026-03-06');
invoice.setIssueTime('10:30:00-05:00');
invoice.setInvoiceTypeCode('01');
invoice.setDocumentCurrencyCode('USD');
// Create tax category and scheme for line items
const taxScheme = new TaxScheme({
id: '01',
name: 'VAT',
});
const classifiedTaxCategory = new ClassifiedTaxCategory({
id: 'S',
percent: '19.00',
taxScheme: taxScheme,
});
// Create invoice line 1 - Product with tax
const item1 = new Item({
name: 'Laptop Computer',
sellersItemIdentification: new SellersItemIdentification({
id: 'PROD-001',
}),
classifiedTaxCategory: classifiedTaxCategory,
});
const price1 = new Price({
priceAmount: '1000.00',
});
const invoiceLine1 = new InvoiceLine({
id: '1',
invoicedQuantity: '2',
lineExtensionAmount: '2000.00',
item: item1,
price: price1,
});
invoice.addInvoiceLine(invoiceLine1);
// Create invoice line 2 - Service with tax
const item2 = new Item({
name: 'Technical Support',
sellersItemIdentification: new SellersItemIdentification({
id: 'SERV-001',
}),
classifiedTaxCategory: classifiedTaxCategory,
});
const price2 = new Price({
priceAmount: '500.00',
});
const invoiceLine2 = new InvoiceLine({
id: '2',
invoicedQuantity: '1',
lineExtensionAmount: '500.00',
item: item2,
price: price2,
});
invoice.addInvoiceLine(invoiceLine2);
// Calculate tax amounts
const subtotalAmount = 2500.00; // 2000 + 500
const taxRate = 0.19; // 19%
const taxAmount = (subtotalAmount * taxRate).toFixed(2); // 475.00
const totalAmount = (subtotalAmount + parseFloat(taxAmount)).toFixed(2); // 2975.00
// Create tax category for tax total
const taxCategory = new TaxCategory({
id: 'S',
percent: '19.00',
taxScheme: taxScheme,
});
// Create tax subtotal
const taxSubtotal = new TaxSubtotal({
taxableAmount: subtotalAmount.toFixed(2),
taxAmount: taxAmount,
taxCategory: taxCategory,
});
// Create tax total
const taxTotal = new TaxTotal({
taxAmount: taxAmount,
taxSubtotals: [taxSubtotal],
});
invoice.addTaxTotal(taxTotal);
// Set monetary totals
const legalMonetaryTotal = new LegalMonetaryTotal({
lineExtensionAmount: subtotalAmount.toFixed(2),
taxExclusiveAmount: subtotalAmount.toFixed(2),
taxInclusiveAmount: totalAmount,
payableAmount: totalAmount,
});
invoice.setLegalMonetaryTotal(legalMonetaryTotal);
// Set line count
invoice.setLineCountNumeric('2');
// Generate XML
const xml = invoice.getXml(true);
console.log(xml);
Generated XML Output (Excerpt)
The code generates a complete UBL 2.1 invoice with tax calculations:<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:UBLVersionID>UBL 2.1</cbc:UBLVersionID>
<cbc:ID>INV-002</cbc:ID>
<cbc:IssueDate>2026-03-06</cbc:IssueDate>
<cbc:IssueTime>10:30:00-05:00</cbc:IssueTime>
<cbc:InvoiceTypeCode>01</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>USD</cbc:DocumentCurrencyCode>
<cbc:LineCountNumeric>2</cbc:LineCountNumeric>
<!-- Tax Total -->
<cac:TaxTotal>
<cbc:TaxAmount currencyID="USD">475.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="USD">2500.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="USD">475.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>01</cbc:ID>
<cbc:Name>VAT</cbc:Name>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<!-- Legal Monetary Total -->
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="USD">2500.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="USD">2500.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="USD">2975.00</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="USD">2975.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<!-- Invoice Lines -->
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="EA">2</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="USD">2000.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Name>Laptop Computer</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>PROD-001</cbc:ID>
</cac:SellersItemIdentification>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>19.00</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>01</cbc:ID>
<cbc:Name>VAT</cbc:Name>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="USD">1000.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
Tax Structure Explained
Tax Scheme
Defines the type of tax being applied:const taxScheme = new TaxScheme({
id: '01', // Tax scheme identifier (e.g., '01' for VAT)
name: 'VAT', // Human-readable tax name
});
Tax Category
Specifies the tax rate and category:const taxCategory = new TaxCategory({
id: 'S', // Standard rate
percent: '19.00', // Tax percentage
taxScheme: taxScheme, // Reference to tax scheme
});
Tax Subtotal
Calculates tax for a specific category:const taxSubtotal = new TaxSubtotal({
taxableAmount: '2500.00', // Amount before tax
taxAmount: '475.00', // Calculated tax amount
taxCategory: taxCategory, // Tax category applied
});
Tax Total
Aggregates all tax subtotals:const taxTotal = new TaxTotal({
taxAmount: '475.00', // Total tax amount
taxSubtotals: [taxSubtotal], // Array of tax subtotals
});
Common Tax Scheme IDs:
01- VAT (Value Added Tax)02- GST (Goods and Services Tax)03- ICA (Industry and Commerce Tax)04- INC (National Consumption Tax)
Always ensure your tax calculations are accurate:
- Calculate the subtotal (sum of all line extension amounts)
- Apply the tax rate to get the tax amount
- Add tax to subtotal to get the total payable amount
Multiple Tax Rates
You can apply different tax rates to different items:// Standard rate 19%
const standardTaxCategory = new ClassifiedTaxCategory({
id: 'S',
percent: '19.00',
taxScheme: new TaxScheme({ id: '01', name: 'VAT' }),
});
// Reduced rate 5%
const reducedTaxCategory = new ClassifiedTaxCategory({
id: 'AA',
percent: '5.00',
taxScheme: new TaxScheme({ id: '01', name: 'VAT' }),
});
// Zero rate
const zeroRatedTaxCategory = new ClassifiedTaxCategory({
id: 'Z',
percent: '0.00',
taxScheme: new TaxScheme({ id: '01', name: 'VAT' }),
});
TaxSubtotal objects for each rate and add them all to the TaxTotal.
Next Steps
- See a complete invoice with parties and delivery in Complete Invoice
- Learn about all invoice fields in the API Reference
- Go back to basics with Basic Invoice