Skip to main content

Correct an invoice (subsanación)

When AEAT registers a billing record but flags admissible errors, the invoice ends in status accepted_with_errors (see Invoice lifecycle). VERI*FACTU lets you fix such a record with a subsanación: a new billing record for the same invoice that carries the corrected data.

POST /invoices/{uuid}/correction does this for you. You send the corrected document, and A-Cube builds the subsanación record (Subsanacion S), chains it after the original record, and reports it to AEAT, which replaces the record it holds. The original record is kept unaltered in the issuer's chain; the invoice keeps its uuid and its data is replaced by the corrected document.

info

A subsanación fixes the data of a billing record that AEAT accepted with errors. It is not a corrective invoice: to change the amounts of an invoice you already issued, issue a factura rectificativa, see Credit notes.

Rules​

  • Only an invoice in status accepted_with_errors can be corrected. Any other status returns 409 Conflict.
  • The correction must keep the identity of the invoice it corrects: the same issuer (IDEmisorFactura / seller tax id), number (NumSerieFactura / InvoiceNumber) and issue date. A different identity returns 422 and leaves the invoice untouched.
  • The correction must come in the same format as the invoice it corrects, otherwise it returns 415 Unsupported Media Type:
Invoice created withAccepted Content-Type for the correction
Facturae (POST /invoices)application/xml, text/xml or application/json (Facturae)
Native VERI*FACTU (POST /invoices)application/vnd.verifactu+xml
Simplified invoiceapplication/vnd.verifactu+xml or application/json
  • The body is a complete document, validated like a new invoice (see Validation), not a patch.
  • The invoice must belong to you: another owner's invoice returns 404. Correcting requires the ROLE_WRITER role, like sending.

Request​

The most common case is an invoice whose recipient AEAT could not identify. In a native VERI*FACTU correction you can identify such a recipient through IDOtro instead of NIF:

POST /invoices/01a03e4a-ee3a-7e1f-b372-c8382bd4ec73/correction
Authorization: Bearer {{jwt}}
Content-Type: application/vnd.verifactu+xml
Accept: application/json
<RegistroAlta>
<IDFactura>
<IDEmisorFactura>A58818501</IDEmisorFactura>
<NumSerieFactura>FV-2026-0002</NumSerieFactura>
<FechaExpedicionFactura>15-01-2026</FechaExpedicionFactura>
</IDFactura>
<NombreRazonEmisor>SupplierOfficialName Ltd.</NombreRazonEmisor>
<TipoFactura>F1</TipoFactura>
<DescripcionOperacion>Servicios de consultoria</DescripcionOperacion>
<Destinatarios>
<IDDestinatario>
<NombreRazon>Buyer Official Name</NombreRazon>
<IDOtro>
<CodigoPais>ES</CodigoPais>
<IDType>07</IDType>
<ID>12345678Z</ID>
</IDOtro>
</IDDestinatario>
</Destinatarios>
<Desglose>
<DetalleDesglose>
<TipoImpositivo>21.00</TipoImpositivo>
<BaseImponibleOimporteNoSujeto>1200.00</BaseImponibleOimporteNoSujeto>
<CuotaRepercutida>252.00</CuotaRepercutida>
</DetalleDesglose>
</Desglose>
<CuotaTotal>252.00</CuotaTotal>
<ImporteTotal>1452.00</ImporteTotal>
</RegistroAlta>

IDType 07 (no censado, not registered in the AEAT census) is only valid with CodigoPais ES; any other country is rejected with 422.

For a Facturae invoice, send the full corrected Facturae document (XML or JSON) with the same InvoiceNumber and IssueDate.

Sample response (202 Accepted)​

The response is the invoice resource, with the outcome of the subsanación record:

{
"uuid": "01a03e4a-ee3a-7e1f-b372-c8382bd4ec73",
"invoiceNumber": "FV-2026-0002",
"invoiceDate": "2026-01-15",
"dueDate": null,
"currency": "EUR",
"totalAmount": "1452.00",
"netAmount": "1200.00",
"direction": "outgoing",
"sender": { "name": "SupplierOfficialName Ltd.", "fiscalId": "A58818501" },
"recipient": { "name": "Buyer Official Name", "fiscalId": "12345678Z" },
"status": "accepted",
"errorReason": null,
"aeatErrorCode": null,
"aeatErrorDescription": null,
"sendAttempts": 1,
"lastSendAttemptAt": "2026-01-16T09:30:41+00:00",
"sentWithIncident": false,
"downloaded": false,
"downloadedAt": null,
"createdAt": "2026-01-15T10:12:04+00:00",
"updatedAt": "2026-01-16T09:30:41+00:00"
}

Outcome​

AEAT outcome of the subsanaciónResulting status
acceptedaccepted
rejectedback to accepted_with_errors, with errorReason, aeatErrorCode and aeatErrorDescription describing the rejection

A rejected correction does not lose the invoice: the original record is still registered with AEAT, and you can send a new correction to the same endpoint.

In the sandbox, the outcome follows the same reserved recipient tax ids as a normal send. Create an invoice for ESSANDBOXACC0001 to get an invoice accepted_with_errors, then correct it with an ordinary recipient to get accepted, or with a rejecting one (for example ESSANDBOXERR0001) to test a rejected correction.

See the POST /invoices/{uuid}/correction API reference for the full schema.