VeriFactu-Nachweise (ES)
Zwei Endpunkte, eine Frage: Wie weisen Sie gegenüber der AEAT nach, dass Ihre Rechnungsstellung den spanischen Vorgaben folgt? Der eine gibt die declaración responsable der Software aus, der andere die vollständige registro-Kette einer NIF.
/api/v1/verifactu/declaracion/api/v1/verifactu/chain/{vatId}/exportWarum es diese zwei Endpunkte gibt
Real Decreto 1007/2023 verlangt zwei Dinge, die ein Prüfer sehen können muss: die Verantwortungserklärung des Software-Herstellers (Art. 13.2, ausgeführt in Art. 15 Orden HAC/1177/2024) und die Aufzeichnungen selbst (Art. 14). Die Verordnung sagt, sie müssen im System einsehbar sein — bei einem API-Produkt heißt das: über die API abrufbar. Genau das leisten diese beiden Aufrufe.
Die declaración responsable
Art. 13.2Gibt die Verantwortungserklärung zu diesem Rechnungssystem als Klartext plus Metadaten aus. Sie beschreibt den Hersteller der Software — uns —, nicht Ihre Organisation, und ist deshalb für jeden API-Key identisch.
1curl https://service.invoice-api.xhub.io/api/v1/verifactu/declaracion \2 -H "Authorization: Bearer sk_live_abc123..."Achten Sie auf hasPendingLegalReview. Solange dort true steht, trägt der Wortlaut noch unsere interne Prüfmarkierung: Das Dokument ist dann ein Entwurf, keine unterschriebene Erklärung. Für eine Vorlage bei der AEAT warten Sie, bis dort false steht.
Antwort der declaración
200 OK1{2 "text": "DECLARACIÓN RESPONSABLE\n\nEl productor del sistema informático de facturación ...",3 "version": "1.5.0",4 "hasPendingLegalReview": false,5 "producedAt": "2026-09-28T09:14:22.318Z"6}| Feld | Typ | Beschreibung |
|---|---|---|
text | string | Die declaración responsable im Volltext, als Klartext (spanisch, Art. 13.2). |
version | string | Software-Version, für die die Erklärung gilt — die Version aus IdSistemaInformatico. |
hasPendingLegalReview | boolean | true, solange der Wortlaut unsere interne Prüfmarkierung trägt. Dann ist das Dokument ein Entwurf. |
producedAt | string (ISO-8601) | ISO-8601-Zeitstempel dieser Ausgabe. |
Der Export der registro-Kette
Art. 14Gibt jeden registro der Kette zu einer NIF als EIN JSON-Dokument aus, geordnet nach Sequenznummer. Jeder Eintrag trägt den eingefrorenen registro neben seiner huella — genau das Objekt, über das der Hash gebildet wurde, unverändert durchgereicht und nie umgeformt. Der Empfänger kann den Hash damit selbst nachrechnen.
Der Export ist auf die Organisation hinter dem API-Key beschränkt. Eine Kette, die jemand anderem gehört, ist nicht sichtbar und kommt als leerer Export zurück — nicht als Fehler.
Ab 5.000 Einträgen ist ein Zeitraum Pflicht: from, to oder beide. Fehlt er, antwortet die API mit 400 und nennt die Zahl der Einträge. Beide Werte sind ISO-8601 und grenzen nach dem Zeitstempel des Eintrags ein.
Query-Parameter
| Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
from | string (ISO-8601) | - | Nur Einträge, die zu diesem ISO-8601-Zeitpunkt oder danach angehängt wurden. Pflicht — allein oder zusammen mit to —, sobald die Kette das Exportlimit übersteigt. |
to | string (ISO-8601) | - | Nur Einträge, die zu diesem ISO-8601-Zeitpunkt oder davor angehängt wurden. |
Beispiel
1# The whole chain of one NIF2curl "https://service.invoice-api.xhub.io/api/v1/verifactu/chain/B12345678/export" \3 -H "Authorization: Bearer sk_live_abc123..."4 5# Narrowed to a range — mandatory above 5000 entries6curl "https://service.invoice-api.xhub.io/api/v1/verifactu/chain/B12345678/export?from=2026-01-01T00:00:00Z&to=2026-03-31T23:59:59Z" \7 -H "Authorization: Bearer sk_live_abc123..."Antwort des Kettenexports
200 OK1{2 "vatId": "B12345678",3 "exportedAt": "2026-09-28T09:20:04.771Z",4 "from": "2026-01-01T00:00:00.000Z",5 "to": "2026-03-31T23:59:59.000Z",6 "entryCount": 2,7 "entries": [8 {9 "sequenceNumber": 1,10 "invoiceId": "inv_01J8Z3K9QW",11 "invoiceNumber": "A/2026-0001",12 "huella": "3C1F9A72B84E05D6C7A1938E4F20B5D8A6C3E71F9B2D48065A1C7E39F2B8D4E60",13 "previousHuella": "",14 "recordType": "ALTA",15 "createdAt": "2026-01-03T08:41:12.004Z",16 "registro": {17 "IDFactura": {18 "IDEmisorFactura": "B12345678",19 "NumSerieFactura": "A/2026-0001",20 "FechaExpedicionFactura": "03-01-2026"21 },22 "ImporteTotal": "1785.00"23 },24 "status": "ACCEPTED",25 "resultCsv": "AAAgOKbwQ8iQ7wAAAAA",26 "lastError": null27 },28 {29 "sequenceNumber": 2,30 "invoiceId": "inv_01J8Z4M2RT",31 "invoiceNumber": "A/2026-0002",32 "huella": "B7E2D46901C8A35F7E1B9D24608C5A3F1E7B9D2460C8A5F3E1B7D9460C2A8F5E3",33 "previousHuella": "3C1F9A72B84E05D6C7A1938E4F20B5D8A6C3E71F9B2D48065A1C7E39F2B8D4E60",34 "recordType": "ALTA",35 "createdAt": "2026-01-04T10:02:55.612Z",36 "registro": {37 "IDFactura": {38 "IDEmisorFactura": "B12345678",39 "NumSerieFactura": "A/2026-0002",40 "FechaExpedicionFactura": "04-01-2026"41 },42 "ImporteTotal": "952.00"43 },44 "status": "PENDING",45 "resultCsv": null,46 "lastError": null47 }48 ]49}| Feld | Typ | Beschreibung |
|---|---|---|
vatId | string | Die NIF, zu der die Kette gehört — der Kettenschlüssel. |
exportedAt | string (ISO-8601) | ISO-8601-Zeitstempel DIESES Exports, nicht des letzten Eintrags. |
from | string | null | Untere Grenze des exportierten Zeitraums, oder null. |
to | string | null | Obere Grenze des exportierten Zeitraums, oder null. |
entryCount | integer | Anzahl der Einträge in entries. |
entries | array | Die Einträge, geordnet nach Sequenznummer — Aufbau unten. |
Ein Eintrag der Kette
| Feld | Typ | Beschreibung |
|---|---|---|
sequenceNumber | integer | Position in der Kette, ab 1 und ohne Lücken. |
invoiceId | string | Interne Id der Rechnung, zu der der Eintrag gehört. |
invoiceNumber | string | null | Rechnungsnummer wie ausgestellt, oder null, wenn der Eintrag älter als die Nummerierung ist. |
huella | string | Der Eintrags-Hash (huella) wie gespeichert — aus registro nachrechenbar. |
previousHuella | string | Huella des vorangehenden Eintrags; beim ersten Eintrag der Kette ein leerer String. |
recordType | string | null | ALTA für die Ausstellung oder ANULACION für den Storno, wie aufgezeichnet. |
createdAt | string (ISO-8601) | ISO-8601-Zeitstempel, zu dem der Eintrag an die Kette gehängt wurde. |
registro | object | Der eingefrorene registro genau so, wie er an die AEAT ging — das Objekt, über das die huella gebildet wurde. Nicht umgeformt. |
status | string | null | Übermittlungsstand der zugehörigen Warteschlangenzeile, etwa ACCEPTED oder PENDING, oder null. |
resultCsv | string | null | Der CSV der AEAT, sobald der registro angenommen wurde. |
lastError | string | null | Letzter Übermittlungsfehler zu diesem Eintrag, wörtlich. |
Fehler
| Status | Code | Beschreibung |
|---|---|---|
| 400 | Bad Request | from oder to ist kein gültiges ISO-8601-Datum, oder die Kette ist zu groß für einen Export ohne Zeitraum — die Meldung nennt die Zahl der Einträge. |
| 401 | UNAUTHORIZED | API-Key fehlt, ist ungültig, oder der Key hat keine Organisation. |
| 502 | CONFIG_MISSING | Der Plattform fehlt zwingende VERIFACTU-Konfiguration. Die Meldung nennt jede fehlende Variable. |