Compliance9 min readAlberto García

EU VAT Invoice Requirements for SaaS: The 16-Field Article 226 Checklist

Article 226 of the EU VAT Directive mandates 16 specific invoice fields. Missing any one of them makes the invoice non-compliant — even if you validated the VAT number correctly.

vatinvoicecomplianceeusaasarticle226

An EU VAT invoice is not just a payment receipt. Under Article 226 of the EU VAT Directive (2006/112/EC), a VAT invoice must contain 16 specific items of information. Missing any one of them makes the invoice legally non-compliant — which can cause the buyer to lose their right to deduct input VAT and expose you to questions from tax authorities. For SaaS companies issuing hundreds or thousands of invoices per month, getting this right in code is essential.

The 16 mandatory invoice fields under Article 226

#FieldNotes
1Date of issueDate the invoice was generated
2Sequential invoice numberMust be unique, must be sequential within a series
3Seller's VAT identification numberYour VAT number, prefixed with country code
4Buyer's VAT number (B2B only)Required for reverse charge; not required for B2C
5Seller's full name and addressLegal entity name, not just the trading name
6Buyer's full name and address
7Description of goods/services suppliede.g. 'TaxID API subscription — June 2026'
8Date of supply (if different from invoice date)Or the date of advance payment
9Taxable amount per VAT rateNet amount before VAT, grouped by rate
10VAT rate appliede.g. 0%, 21%, 25%
11VAT amount payableIn the currency of the invoice
12Unit price (excluding VAT)Per unit if applicable
13Any discounts or rebatesIf not included in unit price
14Reference to applicable VAT exemption or zero-rate provisione.g. 'Art. 196 EU VAT Directive' for reverse charge
15For new means of transport: technical detailsRarely applicable to digital services
16For margin scheme: reference to the scheme appliedNot applicable to standard digital service supply

Warning

Missing even one of the 16 mandatory fields makes the invoice non-compliant under EU law. Buyers receiving a non-compliant invoice may lose their right to deduct the input VAT — which can create disputes and chargebacks even when the underlying supply was correct.

Fields that change based on customer type

Fields 4, 10, 11, and 14 all change based on whether the customer is a B2B reverse-charge customer or a B2C customer. Getting these right is where most SaaS invoice implementations go wrong.

FieldB2B reverse chargeB2C (OSS)
Buyer's VAT number (field 4)Required — the VIES-validated numberNot required (consumer has none)
VAT rate (field 10)0%Customer's country rate (e.g. 20% UK, 19% DE)
VAT amount (field 11)€0.00Calculated: net × rate
Legal reference (field 14)"Reverse charge — Art. 196 EU VAT Directive"Not required
'Reverse charge' notationRequired — explicit text on invoice faceNot applicable

Generating compliant invoices in code

typescriptlib/invoice.ts
interface InvoiceData {
  invoiceNumber: string;
  issueDate: Date;
  supplyDate: Date;
  seller: { name: string; address: string; vatNumber: string };
  buyer: { name: string; address: string; vatNumber?: string };
  lineItems: Array<{ description: string; unitPrice: number; quantity: number }>;
  vatTreatment: 'reverse_charge' | 'oss_b2c' | 'domestic';
  vatRate: number; // 0 for reverse_charge, customer country rate for oss_b2c
  currency: string;
}

function generateInvoiceFields(data: InvoiceData) {
  const netAmount = data.lineItems.reduce(
    (sum, item) => sum + item.unitPrice * item.quantity, 0
  );
  const vatAmount = netAmount * data.vatRate;

  return {
    // Article 226 required fields
    invoiceNumber:     data.invoiceNumber,           // field 2
    issueDate:         data.issueDate.toISOString(),  // field 1
    supplyDate:        data.supplyDate.toISOString(), // field 8
    sellerName:        data.seller.name,              // field 5
    sellerAddress:     data.seller.address,           // field 5
    sellerVatNumber:   data.seller.vatNumber,         // field 3
    buyerName:         data.buyer.name,               // field 6
    buyerAddress:      data.buyer.address,            // field 6
    buyerVatNumber:    data.buyer.vatNumber ?? null,  // field 4 (B2B only)
    lineItems:         data.lineItems,                // field 7, 12
    netAmount:         netAmount,                     // field 9
    vatRate:           data.vatRate,                  // field 10
    vatAmount:         vatAmount,                     // field 11
    currency:          data.currency,

    // Reverse-charge specific
    reverseChargeNotation: data.vatTreatment === 'reverse_charge'
      ? 'VAT: Reverse charge — Article 196, Council Directive 2006/112/EC'
      : null,                                        // field 14
  };
}
typescriptlib/invoice-renderer.tsx
// Invoice HTML generation (simplified)
function renderInvoiceLegalSection(invoice: ReturnType<typeof generateInvoiceFields>) {
  if (invoice.reverseChargeNotation) {
    return (
      <div className="invoice-legal">
        <p>VAT: 0.00 {invoice.currency}</p>
        <p><strong>Reverse charge</strong> — Article 196, EU VAT Directive 2006/112/EC.</p>
        <p>The VAT on this supply is to be accounted for by the recipient.</p>
        <p>Buyer VAT number: {invoice.buyerVatNumber}</p>
      </div>
    );
  }
  return (
    <div className="invoice-legal">
      <p>VAT ({(invoice.vatRate * 100).toFixed(0)}%): {invoice.vatAmount.toFixed(2)} {invoice.currency}</p>
    </div>
  );
}

What Stripe, Paddle, and Chargebee handle automatically

Billing platforms vary significantly in how much Article 226 compliance they handle for you. Stripe Tax generates invoices with most required fields but requires you to supply the customer's VAT number and set tax_exempt correctly — it does not validate the number via VIES. Paddle (as a Merchant of Record) handles the entire VAT compliance chain including VIES validation, invoice generation, and OSS remittance. Chargebee generates compliant invoice PDFs when you supply the tax configuration and customer data correctly, but does not validate VAT numbers.

Storing the validation record with the invoice

The link between the VIES validation and the invoice is critical for audit purposes. Store the request_id from the validation call alongside the invoice ID, and include the validation timestamp. If you are ever audited, this record demonstrates that you verified the customer's taxable status before applying zero-rate treatment.

sql
CREATE TABLE invoices (
  id             UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  invoice_number TEXT NOT NULL UNIQUE,
  customer_id    UUID NOT NULL REFERENCES customers(id),
  issue_date     TIMESTAMPTZ NOT NULL,
  net_amount     NUMERIC(12,2) NOT NULL,
  vat_rate       NUMERIC(5,4) NOT NULL,
  vat_amount     NUMERIC(12,2) NOT NULL,
  vat_treatment  TEXT NOT NULL, -- 'reverse_charge' | 'oss_b2c' | 'domestic'
  created_at     TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE TABLE invoice_vat_validations (
  invoice_id      UUID NOT NULL REFERENCES invoices(id),
  vat_number      TEXT NOT NULL,
  country_code    TEXT NOT NULL,
  validation_status TEXT NOT NULL,  -- 'active' | 'service_unavailable'
  request_id      TEXT NOT NULL,   -- TaxID API request_id for audit trail
  validated_at    TIMESTAMPTZ NOT NULL,
  PRIMARY KEY (invoice_id)
);

Start validating EU VAT numbers

Free plan — 100 validations/month. No credit card required.

AG
Alberto García

Founder, TaxID

Building EU VAT validation tools for developers. Obsessed with compliance automation and developer experience.