Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/mdiago/VeriFactu/llms.txt

Use this file to discover all available pages before exploring further.

Each VERI*FACTU invoice must include a QR code that encodes a URL pointing to the AEAT’s invoice validation service. This allows buyers, auditors, or any third party to verify that the invoice was correctly registered with the tax authority. VeriFactu exposes two methods directly on the RegistroAlta object — GetUrlValidate() and GetValidateQr() — so you can generate both the URL and the QR bitmap without any external dependencies.

Obtener la URL de validación

Call invoice.GetRegistroAlta() to obtain a RegistroAlta instance, then call GetUrlValidate() to build the validation URL. The URL parameters (nif, numserie, fecha, importe) are URL-encoded automatically from the invoice data.
// Creamos una instancia de la clase factura
var invoice = new Invoice("GITHUB-EJ-004", new DateTime(2024, 11, 4), "B72877814")
{
    InvoiceType = TipoFactura.F1,
    SellerName = "WEFINZ GANDIA SL",
    BuyerID = "B44531218",
    BuyerName = "WEFINZ SOLUTIONS SL",
    Text = "PRESTACION SERVICIOS DESARROLLO SOFTWARE",
    TaxItems = new List<TaxItem>() {
        new TaxItem()
        {
            TaxRate = 4,
            TaxBase = 10,
            TaxAmount = 0.4m
        },
        new TaxItem()
        {
            TaxRate = 21,
            TaxBase = 100,
            TaxAmount = 21
        }
    }
};

// Obtenemos una instancia de RegistroAlta a partir del objeto Invoice
var registro = invoice.GetRegistroAlta();

// Obtenemos la URL de validación
var url = registro.GetUrlValidate();
// https://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR?nif=B72877814&numserie=GITHUB-EJ-004&fecha=04-11-2024&importe=131.4
The returned URL contains four query parameters derived from the invoice:
ParámetroOrigen
nifIDFacturaAlta.IDEmisorFactura — seller’s tax ID.
numserieIDFacturaAlta.NumSerieFactura — invoice number / series.
fechaIDFacturaAlta.FechaExpedicionFactura — invoice date in dd-MM-yyyy format.
importeImporteTotal — total invoice amount including taxes.

Obtener el QR como bitmap

GetValidateQr() calls GetUrlValidate() internally and encodes the resulting URL as a QR code, returning the image as a raw BMP byte array.
// Obtenemos una instancia de RegistroAlta a partir del objeto Invoice
var registro = invoice.GetRegistroAlta();

// Obtenemos el bitmap del QR
var bmQr = registro.GetValidateQr();

// Guardamos la imagen en disco
File.WriteAllBytes(@"C:\Users\usuario\Downloads\ValidateQrSample.bmp", bmQr);
The QR bitmap is returned in BMP format. Embed it directly into your invoice PDF generation workflow (e.g. via System.Drawing, a PDF library, or a reporting tool) as required by the VERI*FACTU regulation. The regulation requires the QR code to appear visibly on the printed or electronic invoice.

Cálculo de la huella (hash)

The chain-of-custody hash (Huella) is a SHA-256 digest computed over key fields of the RegistroAlta as defined in Artículo 137, Orden HAC/1177/2024. Call GetHashOutput() to obtain the hex-encoded hash string. In normal operation the hash is computed automatically when a record is saved. You can also compute it manually — useful for auditing, testing, or verifying a specific registration record matches what was submitted to the AEAT:
// Creamos una instancia de la clase factura
var invoice = new Invoice("GITHUB-EJ-003", new DateTime(2024, 11, 4), "B72877814")
{
    BuyerID = "B44531218",
    BuyerName = "WEFINZ SOLUTIONS SL",
    TaxItems = new List<TaxItem>() {
        new TaxItem()
        {
            TaxRate = 4,
            TaxBase = 10,
            TaxAmount = 0.4m
        },
        new TaxItem()
        {
            TaxRate = 21,
            TaxBase = 100,
            TaxAmount = 21
        }
    }
};

// Obtenemos una instancia de RegistroAlta
var registro = invoice.GetRegistroAlta();

// Establecemos la fecha y hora de generación del registro
// (normalmente asignada automáticamente durante el envío)
var fechaHoraHusoGenRegistro = new DateTime(2024, 11, 4, 12, 36, 39);
registro.FechaHoraHusoGenRegistro = XmlParser.GetXmlDateTimeIso8601(fechaHoraHusoGenRegistro);

// Establecemos el encadenamiento con el registro anterior
registro.Encadenamiento = new Encadenamiento()
{
    RegistroAnterior = new RegistroAnterior()
    {
        Huella = "8C8DCEFB120522E0C71BC19902F44D5334FF6C98E74F0E3AC1D1E5A30C2EA836"
    }
};

// Obtenemos el valor de la huella en hexadecimal
var hash = registro.GetHashOutput();
// 4EECCE4DD48C0539665385D61D451BA921B7160CA6FEF46CD3C2E2BC5C778E14
The input string hashed by GetHashOutput() is built from the following fields in order (per Artículo 137):
  1. IDEmisorFactura — seller NIF
  2. NumSerieFactura — invoice number and series
  3. FechaExpedicionFactura — invoice issue date
  4. TipoFactura — invoice type
  5. CuotaTotal — total tax amount
  6. ImporteTotal — total invoice amount
  7. Huella of the previous registration record
  8. FechaHoraHusoGenRegistro — timestamp including timezone offset

URL de preproducción vs producción

The validation endpoint prefix is controlled by Settings.Current.VeriFactuEndPointValidatePrefix. By default it points to the AEAT preproduction environment. Switch it to the production value before going live:
// Producción
Settings.Current.VeriFactuEndPointValidatePrefix = VeriFactuEndPointPrefixes.ProdValidate;
Settings.Save();

// Preproducción (valor por defecto)
Settings.Current.VeriFactuEndPointValidatePrefix = VeriFactuEndPointPrefixes.TestValidate;
Settings.Save();
The available constants from VeriFactuEndPointPrefixes are:
EntornoConstanteURL base
PreproducciónVeriFactuEndPointPrefixes.TestValidatehttps://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR
ProducciónVeriFactuEndPointPrefixes.ProdValidatehttps://www2.agenciatributaria.gob.es/wlpl/TIKE-CONT/ValidarQR
The same Settings object also controls the SOAP submission endpoint via VeriFactuEndPointPrefix (VeriFactuEndPointPrefixes.Test / VeriFactuEndPointPrefixes.Prod). Make sure both prefixes are set to the same environment (test or production) consistently.

Build docs developers (and LLMs) love