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.
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_errorscan be corrected. Any other status returns409 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 returns422and 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 with | Accepted 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 invoice | application/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 theROLE_WRITERrole, 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ón | Resulting status |
|---|---|
| accepted | accepted |
| rejected | back 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.