Factuarea API

VeriFactu record subsanación

Fix and resubmit VeriFactu billing records rejected by the AEAT — when subsanación applies, when you need an annulment or a corrective instead, and the exact API flow.

When the AEAT rejects a VeriFactu billing record because of a data error (record status: rejected), the VeriFactu regulation (Royal Decree 1007/2023, art. 11) lets you subsanar the record: resubmit the same record with the corrected content. It is not a new invoice, not a corrective and not an annulment — the rejected record itself is repaired and transmitted again.

POST /v1/verifactu/records/{record}/subsanar
  • Scope: verifactu:write
  • Request body: none — the subsanable content is regenerated server-side from the source invoice and the current master data.
  • Response: 202 Accepted — the resubmission is queued and sent to the AEAT within seconds.

Subsanación never recalculates the original fingerprint (huella), the previous-record chain link or the original generation timestamp: the AEAT matches the resubmission to the rejected record precisely because they are preserved. There is no cap on subsanación attempts — the technical retry cap applies only to blind retries of transmission failures.

When to use it — and when not

SituationWhat to do
Record rejected by the AEAT for a data error — recipient NIF not identified in the census, wrong recipient name, description issues…Subsanación. Fix the data at its source, then call POST …/subsanar.
Record in error (technical transmission failure: timeout, AEAT down).Nothing — transmission retries automatically (manual retry available). Subsanación answers record_not_rejected.
Record accepted but the invoice carries wrong data.A corrective invoice (R1–R5). An accepted record is immutable — subsanación answers record_not_rejected.
The correction changes a fingerprint field: issuer NIF, series + number, issue date, invoice type, total tax amount or total amount.Annulment + new record (new invoice or corrective). Subsanación answers requires_annulment without modifying anything.

The flow

Detect the rejection. Subscribe to the invoice.verifactu_failed webhook event, or poll the record list for status: rejected. The record carries the AEAT rejection detail.

Fix the data at its source. The resubmitted content is regenerated from the source invoice and the current master data — e.g. correct the client's NIF or registered name and the new values are picked up automatically. The invoice's frozen legal snapshot is deliberately refreshed so the PDF matches what the AEAT receives.

Call the endpoint. The record re-enters the transmission queue with a fresh round of attempts:

curl -X POST https://api.factuarea.com/v1/verifactu/records/0197a2a8-4cf0-7a31-9a5e-3f2b8c1d6e42/subsanar \
  -H "Authorization: Bearer fact_live_3pXnR2VbY7TcA9eFmN5z8KqW"

Response (202):

{
  "data": {
    "id": "0197a2a8-4cf0-7a31-9a5e-3f2b8c1d6e42",
    "message": "Subsanación encolada. El registro se reenviará a la AEAT en unos segundos."
  }
}

Watch the outcome. The record is transmitted again and ends accepted — or rejected once more if the data is still wrong, in which case you can subsanar again (there is no attempt limit).

Errors

Business-rule violations return 422 with code: business_rule_violation and a subcode that pinpoints the cause:

{
  "error": {
    "type": "invalid_request_error",
    "code": "business_rule_violation",
    "subcode": "record_not_rejected",
    "message": "El registro #842 no está rechazado por la AEAT (estado actual: accepted). Solo los registros rechazados admiten subsanación; para fallos técnicos usa el reintento."
  }
}
HTTPcode / subcodeWhen
404resource_not_foundThe record doesn't exist or belongs to another company.
422business_rule_violation / record_not_rejectedThe record is not in rejected (it is accepted, pending, submitted — or a technical error, which the automatic retry covers).
422business_rule_violation / requires_annulmentThe correction touches fingerprint fields. Annul the record and issue a new invoice or a corrective.
422business_rule_violation / record_not_subsanableThe record is not an alta record, or it has no source invoice to regenerate from.
403insufficient_scopeThe key lacks the verifactu:write scope.

Avoid the rejection in the first place

The most frequent data rejection is a recipient that the AEAT census does not identify (rejection 1239). Verify the name + NIF pair of a client with POST /v1/clients/census-verification before issuing VeriFactu invoices to them — subsanación then remains what it should be: a safety net, not a routine.

On this page