LiveES

VeriFactu QR (ES)

The QR code a Spanish invoice has to carry: NIF, series, invoice number, date and total become the AEAT verification URL — returned as a URL, as PNG (base64) and as SVG.

POST/api/v1/invoice/es/verifactu-qr

A QR code, not a submission to the AEAT

This endpoint builds the QR code and nothing else. It does not register the invoice with the AEAT and sends no data there — it produces the verification URL a recipient can open on their phone, and renders it.

The host inside the URL follows the service configuration, not the request. Measured on 2026-09-15, the hosted service answered with the AEAT test service (prewww2.aeat.es). If you need the production host, settle that with us before the first invoice goes to print.

Request

FieldTypeRequiredDescription
sellerNifstringThe issuer's NIF/CIF, e.g. B12345678.
invoiceSeriesstringInvoice series. Together with invoiceNumber it forms the AEAT numserie parameter; reserved characters are URL-encoded.
invoiceNumberstringInvoice number within the series.
invoiceDatestringInvoice date in the AEAT QR format DD-MM-YYYY — not ISO.
totalnumberTotal amount as a number. Negative totals are accepted for credit notes.
verifactuModeboolean-Deprecated and ignored. The platform is VERI*FACTU-only, so the QR always points at the ValidarQR verification service. The field is accepted for backwards compatibility and will be removed.

Example

bash
1curl -X POST https://service.invoice-api.xhub.io/api/v1/invoice/es/verifactu-qr \
2 -H "Authorization: Bearer sk_live_abc123..." \
3 -H "Content-Type: application/json" \
4 -d '{
5 "sellerNif": "B12345678",
6 "invoiceSeries": "A",
7 "invoiceNumber": "2026-0042",
8 "invoiceDate": "20-03-2026",
9 "total": 5712.00
10 }'

Response

200 OK
json
1{
2 "url": "https://prewww2.aeat.es/wlpl/TIKE-CONT/ValidarQR?nif=B12345678&numserie=A%2F2026-0042&fecha=20-03-2026&importe=5712.00",
3 "png": "iVBORw0KGgoAAAANSUhEUgAAAMQAAA...",
4 "svg": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 49 49\" shape-rendering=\"crispEdges\">..."
5}

Measured on 2026-09-15: numserie is built as series, slash, invoice number (here A/2026-0042) and URL-encoded — the example in the OpenAPI file writes it without a separator. The value in the response is what counts; do not assemble the URL yourself, take the one you get.

FieldTypeDescription
urlstringThe AEAT verification URL encoded in the QR code.
pngstringThe QR code as a PNG, base64-encoded and without a data: prefix.
svgstringThe same QR code as SVG markup.

Error cases

StatusCodeDescription
400Bad RequestA field is missing or has the wrong type.
401UNAUTHORIZEDThe API key is missing or invalid.
403FORBIDDENThe entitlement is missing: e-invoice:es:facturae:create is required.

The Spanish invoice itself

The QR code is an addition to the document, not the document. The invoice itself comes from the Creator: for Spain it offers Facturae and PDF — the QR then goes into the PDF template.

Creator API