Corrective invoices
R1 to R5, substitution versus differences, and how the lines of a corrective are built — the four decisions that determine what the AEAT and the VAT return actually receive.
A corrective invoice (rectificativa) is a fiscal document in its own right: it gets its own number, its own registration at the AEAT and its own effect on the VAT return. Issuing one involves four independent decisions, and integrations tend to conflate them:
- Which invoice may be corrected.
- Which R-code the correction carries — the legal reason.
- Substitution or differences — whether the corrective states the correct amounts or only the delta.
- Which lines the corrective ends up with.
Get the third and fourth wrong together and you will file a VAT return with the sign inverted.
When this applies
The original invoice must be sent or paid. Nothing else qualifies
(BR-INV-001, RD 1619/2012 art. 15):
| Original status | Corrective? |
|---|---|
sent, paid | Yes. |
draft, cancelled | No — edit or delete it, it is not a fiscal document yet. |
overdue | No. Register the payment or annul it first. |
annulled | No — it has already been retired. |
| Already a corrective | No. Issue a new corrective of the original invoice. |
For a paid invoice this is not one option among several: it is the only one. A
paid invoice cannot be annulled, because its output VAT is already committed to a
period (BR-INV-023). See
Annul or correct.
The R-code matrix is legal, not cosmetic
The R-code states why the original is being corrected, and the AEAT constrains which codes are legal for which original.
| Original invoice type | Legal codes |
|---|---|
Simplified F2 | R5 only |
Complete F1, substitute F3 | R1–R4 only |
Force a code outside its row and the API answers 422 with the legal values in
allowed_values (BR-INV-035).
There are two ways to arrive at the code. By default it is derived from the
correction_reason slug you send (BR-INV-018):
correction_reason | Code | Legal basis |
|---|---|---|
error_fundado | R1 | Art. 80.Uno, Dos y Seis LIVA — well-founded error in law |
concurso | R2 | Art. 80.Tres LIVA — insolvency proceedings |
incobrable | R3 | Art. 80.Cuatro LIVA — bad debt |
error_importe, error_cliente, devolucion, descuento, otras | R4 | RD 1619/2012 art. 15 — remaining causes |
R5 is never derived from a reason. It comes from the type of the original: a
corrective of an F2 is always born R5, whatever reason you pass
(BR-INV-019).
Alternatively you set correction_code explicitly. On a complete original, an
explicit R1–R4 wins over the slug-based derivation and becomes the code
that travels in the VeriFactu chain. Use it when your own system already knows
the legal cause and you do not want it inferred from a slug.
R2 and R3 require supporting documentation by law. Pass justification
(10 to 1000 characters); it is prepended to the corrective's notes as documentary
traceability.
Substitution or differences
This is the decision with the largest blast radius, and in the v1 contract you do
not set it directly — you set correction_type and the nature follows:
correction_type | Nature | The corrective contains | Sign |
|---|---|---|---|
full | S — substitution | The correct amounts, complete. It replaces the original in full. | Always positive or zero. |
partial | I — differences | Only the difference between what was invoiced and what is correct. | May be negative. |
The rule the tax engine enforces: a taxable base may be negative only in a
corrective by differences. In a substitution — and in any ordinary invoice — a
negative base is incoherent data and is rejected with 422
(BR-VFC-033, BR-INV-017).
This is the mechanism for a downward correction. A refund is a corrective by differences whose base and VAT quota are negative, and the AEAT accepts it precisely because that is the fiscally correct way to express a credit. Trying to express the same refund as a substitution with negative amounts is rejected.
A corrective by differences on an invoice at 0% VAT has a negative base and a zero quota — not a negative quota. The tax engine inherits the rate of the original lines and never invents one; a fabricated 21% here is the classic way to get a rejection from the AEAT.
What the API sends
POST /v1/invoices/{id}/corrective,
scope invoices:write. It answers 201 with the new invoice and a
Location header pointing at it.
| Field | Required | Notes |
|---|---|---|
correction_reason | Yes | One of the eight slugs above. |
correction_type | Yes | full or partial. |
correction_code | No | R1–R5. Validated against the legal matrix. |
justification | No | 10–1000 characters. Mandatory in practice for R2 and R3. |
notes | No | Free text, up to 1000 characters. |
lines | Required when correction_type is partial | description, quantity, unit_price, and optionally tax_rate, discount_percent, indirect_tax_regime, product_id. |
The API Reference ships one ready-to-send example per code — r1_error_fundado,
r2_concurso, r3_incobrable, r4_otras and r5_simplificada — in the
request-body examples dropdown of that operation. They are also published as
reusable components.examples.corrective_* entries in the OpenAPI document, so
generated clients can resolve them by $ref.
curl -X POST https://api.factuarea.com/v1/invoices/0197a2a8-4cf0-7a31-9a5e-3f2b8c1d6e42/corrective \
-H "Authorization: Bearer fact_live_3pXnR2VbY7TcA9eFmN5z8KqW" \
-H "Content-Type: application/json" \
-d '{
"correction_reason": "otras",
"correction_type": "partial",
"correction_code": "R3",
"justification": "Crédito declarado incobrable por resolución judicial firme.",
"lines": [
{ "description": "Ajuste por impago", "quantity": -1, "unit_price": 100, "tax_rate": 21 }
]
}'The response is an ordinary invoice object whose is_corrective is true and
whose corrective block carries original_id, original_number,
original_date, correction_reason, correction_type, correction_nature,
base_rectificada, cuota_rectificada and correction_aeat_type — the last one
being the R-code that actually travelled to the AEAT.
To list every corrective issued against an invoice, use
GET /v1/invoices/{id}/correctives.
How the lines are built
The three combinations produce genuinely different documents
(BR-INV-036):
full with no lines — a full cancellation. One line is generated per
original line with the quantity negated, preserving the product, the price,
the tax rate, the retention, the surcharge, the discount and the indirect-tax
regime of the original.
full with lines — a substitution. The lines you send are the final
lines; there is no diffing. Every field you omit is inherited by index from
the equivalent original line, taxation included. The inheritance never falls back
to a default rate, so an exempt operation stays exempt instead of acquiring a
phantom 21%. If you send more lines than the original had, the extra ones have no
counterpart: they carry no product and their taxation defaults to zero.
partial — adjustment lines. There is no original line to match by index, so
defaults are zero and product_id travels only if you declare it explicitly. A
line without product_id does not move inventory.
Index-based inheritance assumes the corrected lines arrive in the same order as the original ones. Reordering or dropping lines crosses the inherited defaults. When your caller reorders, declare the fields explicitly per line instead of relying on inheritance.
Disbursement lines are inherited from the original as well, which is why the
corrective payload accepts line_type and source_invoice_reference on a line.
See Disbursements.
What appears on the PDF
The corrective is printed as a separate document with its own number, derived
from the original: SERIE-YYYY-NNN-REC{n}, where {n} counts the correctives
already issued against that original (BR-INV-021).
Its recipient and issuer blocks are frozen at its own issue time, not copied
from the original. That is deliberate: a common reason to correct is precisely
that the recipient's data were wrong, so the corrective must print the corrected
ones (BR-INV-024).
Like any issued invoice from a VeriFactu company, it carries the legal QR block.
What reaches the AEAT
As a VeriFactu record, the corrective is an ordinary registration whose
invoice_type is the R-code. Its tax breakdown carries the sign described in
Substitution or differences: negative base and quota for a downward
correction by differences, always non-negative for a substitution. The
substitution additionally declares the rectified base and quota of the original;
a correction by differences does not, in line with the AEAT schema
(BR-VFC-033).
In the quarterly VAT return, a correction of a general-regime operation lands
in boxes [14] and [15] with its sign: a downward correction subtracts, an
upward one adds. The fiscal snapshot preserves the real code (R1–R4) rather
than collapsing every corrective to R5 (BR-TXR-019).
That routing applies to the general regime only. A corrective whose header
operation regime is something else follows that regime's own boxes — reverse
charge and exempt or export operations are declared elsewhere and therefore do
not reach [14]/[15]. See Regime keys for how the
header regime is determined.
Traceability
Derived from the domain rules of the Factuarea backend:
BR-INV-001— a corrective must reference an issued original; the eligible statuses.BR-INV-017— the correction nature is exactlySorI.BR-INV-018— the mapping from reason slug toR1–R4.BR-INV-019— a corrective of anF2is bornR5.BR-INV-021— the-REC{n}numbering of correctives.BR-INV-024— the immutable recipient snapshot, frozen at the corrective's own issue time.BR-INV-035— explicitcorrection_code, the AEAT legal matrix, andjustification.BR-INV-036— how corrective lines are generated and what is inherited by index.BR-VFC-033— negative base and quota admitted only in corrections by differences.BR-TXR-019— the sign in boxes[14]/[15]and the preservation of the real R-code.