This guide covers creating UBL credit notes for refunds, corrections, and adjustments.
Credit notes use the CreditNote class instead of Invoice, and CreditNoteLine instead of InvoiceLine. The structure is very similar, with a few key differences:
| Invoice | Credit Note |
|---|---|
Invoice class |
CreditNote class |
InvoiceLine |
CreditNoteLine |
setInvoiceLines() |
setCreditNoteLines() |
generator->invoice() |
generator->creditNote() |
<?php
use NumNum\UBL\CreditNote;
use NumNum\UBL\CreditNoteLine;
use NumNum\UBL\Generator;
use NumNum\UBL\Party;
use NumNum\UBL\Address;
use NumNum\UBL\Country;
use NumNum\UBL\AccountingParty;
use NumNum\UBL\Item;
use NumNum\UBL\Price;
use NumNum\UBL\UnitCode;
use NumNum\UBL\TaxTotal;
use NumNum\UBL\TaxSubTotal;
use NumNum\UBL\TaxCategory;
use NumNum\UBL\TaxScheme;
use NumNum\UBL\LegalMonetaryTotal;
use NumNum\UBL\InvoiceTypeCode;
// 1. Create address
$country = (new Country())
->setIdentificationCode('BE');
$address = (new Address())
->setStreetName('Korenmarkt')
->setBuildingNumber(1)
->setCityName('Gent')
->setPostalZone('9000')
->setCountry($country);
// 2. Create parties
$supplierCompany = (new Party())
->setName('Supplier Company Name')
->setPostalAddress($address);
$clientCompany = (new Party())
->setName('Customer Company')
->setPostalAddress($address);
$accountingSupplierParty = (new AccountingParty())
->setParty($supplierCompany);
$accountingCustomerParty = (new AccountingParty())
->setParty($clientCompany);
// 3. Create product
$productItem = (new Item())
->setName('Product Name')
->setDescription('Product Description')
->setSellersItemIdentification('SKU-12345')
->setBuyersItemIdentification('BUYER-REF');
// 4. Create price
$price = (new Price())
->setBaseQuantity(1)
->setUnitCode(UnitCode::UNIT)
->setPriceAmount(100);
// 5. Create line tax total
$lineTaxTotal = (new TaxTotal())
->setTaxAmount(21);
// 6. Create credit note line
$creditNoteLine = (new CreditNoteLine())
->setId(1)
->setItem($productItem)
->setPrice($price)
->setTaxTotal($lineTaxTotal)
->setInvoicedQuantity(1);
// 7. Create tax totals
$taxScheme = (new TaxScheme())
->setId('VAT');
$taxCategory = (new TaxCategory())
->setId('S')
->setPercent(21)
->setTaxScheme($taxScheme);
$taxSubTotal = (new TaxSubTotal())
->setTaxableAmount(100)
->setTaxAmount(21)
->setTaxCategory($taxCategory);
$taxTotal = (new TaxTotal())
->setTaxAmount(21)
->addTaxSubTotal($taxSubTotal);
// 8. Create monetary totals
$legalMonetaryTotal = (new LegalMonetaryTotal())
->setLineExtensionAmount(100)
->setTaxExclusiveAmount(100)
->setTaxInclusiveAmount(121)
->setPayableAmount(121);
// 9. Create credit note
$creditNote = (new CreditNote())
->setId('CN-2024-001')
->setIssueDate(new \DateTime())
->setInvoiceTypeCode(InvoiceTypeCode::CREDIT_NOTE)
->setAccountingSupplierParty($accountingSupplierParty)
->setAccountingCustomerParty($accountingCustomerParty)
->setCreditNoteLines([$creditNoteLine])
->setTaxTotal($taxTotal)
->setLegalMonetaryTotal($legalMonetaryTotal);
// 10. Generate XML
$generator = new Generator();
$xml = $generator->creditNote($creditNote);
file_put_contents('credit-note.xml', $xml);When creating a credit note that references an original invoice, use BillingReference:
use NumNum\UBL\BillingReference;
use NumNum\UBL\InvoiceDocumentReference;
$invoiceReference = (new InvoiceDocumentReference())
->setId('INV-2024-001')
->setIssueDate(new \DateTime('2024-01-15'));
$billingReference = (new BillingReference())
->setInvoiceDocumentReference($invoiceReference);
$creditNote = (new CreditNote())
->setId('CN-2024-001')
->setBillingReference($billingReference)
// ... rest of credit note setupuse NumNum\UBL\InvoiceTypeCode;
// Standard credit note
$creditNote->setInvoiceTypeCode(InvoiceTypeCode::CREDIT_NOTE);For partial refunds, simply include only the items being credited:
// Original invoice had 10 units at €100 each
// Credit note for 3 returned units
$creditNoteLine = (new CreditNoteLine())
->setId(1)
->setItem($productItem)
->setPrice($price) // €100 per unit
->setInvoicedQuantity(3); // Only 3 units
$legalMonetaryTotal = (new LegalMonetaryTotal())
->setLineExtensionAmount(300) // 3 × €100
->setTaxExclusiveAmount(300)
->setTaxInclusiveAmount(363) // 300 + 21% VAT
->setPayableAmount(363);$creditNoteLines = [];
// Line 1: Returned product
$creditNoteLines[] = (new CreditNoteLine())
->setId(1)
->setItem((new Item())->setName('Returned Product'))
->setPrice((new Price())->setPriceAmount(50)->setBaseQuantity(1)->setUnitCode(UnitCode::UNIT))
->setInvoicedQuantity(2);
// Line 2: Service adjustment
$creditNoteLines[] = (new CreditNoteLine())
->setId(2)
->setItem((new Item())->setName('Service Credit'))
->setPrice((new Price())->setPriceAmount(25)->setBaseQuantity(1)->setUnitCode(UnitCode::UNIT))
->setInvoicedQuantity(1);
$creditNote->setCreditNoteLines($creditNoteLines);Mark a credit note as a copy:
$creditNote = (new CreditNote())
->setId('CN-2024-001')
->setCopyIndicator(true)
// ... rest of credit note setup$creditNote = (new CreditNote())
->setUBLVersionId('2.1')
->setCustomizationId('urn:cen.eu:en16931:2017')
->setProfileId('urn:fdc:peppol.eu:2017:poacc:billing:01:1.0')
->setId('CN-2024-001')
// ... rest of credit note setupSee tests/Write/SimpleCreditNoteTest.php for a complete working example that validates against the UBL 2.1 schema.
Credit the entire original invoice amount:
// Match the original invoice exactly
$creditNote = (new CreditNote())
->setId('CN-2024-001')
->setBillingReference($billingReference) // Reference original invoice
->setCreditNoteLines($originalInvoiceLines) // Same lines
->setTaxTotal($originalTaxTotal)
->setLegalMonetaryTotal($originalMonetaryTotal);When the original invoice had incorrect pricing:
// Credit the difference
$priceDifference = (new CreditNoteLine())
->setId(1)
->setItem((new Item())->setName('Price Adjustment - Product X'))
->setPrice((new Price())->setPriceAmount(10)->setBaseQuantity(1)->setUnitCode(UnitCode::UNIT))
->setInvoicedQuantity(5); // 5 units × €10 overcharge = €50 creditWhen fewer items were delivered than invoiced:
$quantityAdjustment = (new CreditNoteLine())
->setId(1)
->setItem($originalProduct)
->setPrice($originalPrice)
->setInvoicedQuantity(2); // Credit for 2 undelivered items- Creating Invoices - Standard invoice creation
- Advanced Features - Payment means, attachments, allowances
- Reading UBL Files - Parse existing UBL documents