Factuarea API

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:

  1. Which invoice may be corrected.
  2. Which R-code the correction carries — the legal reason.
  3. Substitution or differences — whether the corrective states the correct amounts or only the delta.
  4. 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 statusCorrective?
sent, paidYes.
draft, cancelledNo — edit or delete it, it is not a fiscal document yet.
overdueNo. Register the payment or annul it first.
annulledNo — it has already been retired.
Already a correctiveNo. 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 typeLegal codes
Simplified F2R5 only
Complete F1, substitute F3R1R4 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_reasonCodeLegal basis
error_fundadoR1Art. 80.Uno, Dos y Seis LIVA — well-founded error in law
concursoR2Art. 80.Tres LIVA — insolvency proceedings
incobrableR3Art. 80.Cuatro LIVA — bad debt
error_importe, error_cliente, devolucion, descuento, otrasR4RD 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 R1R4 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_typeNatureThe corrective containsSign
fullS — substitutionThe correct amounts, complete. It replaces the original in full.Always positive or zero.
partialI — differencesOnly 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.

FieldRequiredNotes
correction_reasonYesOne of the eight slugs above.
correction_typeYesfull or partial.
correction_codeNoR1R5. Validated against the legal matrix.
justificationNo10–1000 characters. Mandatory in practice for R2 and R3.
notesNoFree text, up to 1000 characters.
linesRequired when correction_type is partialdescription, 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 (R1R4) 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 exactly S or I.
  • BR-INV-018 — the mapping from reason slug to R1R4.
  • BR-INV-019 — a corrective of an F2 is born R5.
  • 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 — explicit correction_code, the AEAT legal matrix, and justification.
  • 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.

On this page