Factuarea APIDevelopers

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 issued: issued or overdue, whether or not it has been paid. Nothing else qualifies (BR-INV-001, RD 1619/2012 art. 15):

Original statusCorrective?
issued, overdueYes — paid or not, the correction is fiscal and the payment state does not condition it.
draft, scheduled, cancelledNo — edit or delete it, it is not a fiscal document yet.
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: by default it is the only one. A paid invoice is not annulled by default, because its output VAT is already committed to a period (BR-INV-023); the only exception is an invoice issued by mistake, annulled with revert_collections: true. See Annul or correct.

An invoice already voided in full (a full corrective by differences) admits no further corrective at all (invoice_already_rectified_in_full). One replaced in full admits no second full correction, but it still admits a partial one.

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 F3R1–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_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 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. Article 15.5 of RD 1619/2012 lets a correction state either the amount of the rectification, whatever its sign (by differences, I), or the invoice as it ends up (substitution, S). You choose with correction_type and, optionally, correction_nature; the three ways to correct an invoice are:

Way to correctRequestThe corrective containsNature
Void the whole invoice (full refund)correction_type: full, no linesEvery original line, negated.I — negative base.
Correct some amountscorrection_type: partial with the adjustment linesOnly the difference between what was invoiced and what is correct; a negative quantity subtracts.I
Replace it with the correct versioncorrection_type: full with the final linesThe correct amounts, complete; no negative quantity.S

correction_nature is optional. Without it, full with lines is a substitution (S) and full without lines and partial are by differences (I). The nature you send always wins, but it must be coherent with the rest of the request: an incoherent combination is rejected with 422 before anything is created.

CombinationAnswer
full with lines and an explicit correction_nature: Iparameter_invalid_value, subcode corrective_full_cancellation_with_lines.
Substitution or partial correction without linesmissing_required_param, param: lines.
Substitution with a negative quantityparameter_invalid_value, subcode corrective_substitution_negative_amount, with line_index.
Partial substitutionparameter_invalid_value, subcode corrective_substitution_requires_full.

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, BR-INV-078). A corrective with a negative base is always read as I, and unit_price is never negative: a negative quantity is what subtracts.

A refund is therefore 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. VeriFactu registers it as TipoRectificativa I; a substitution is registered as TipoRectificativa S together with ImporteRectificacion, the base and tax of the original.

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/companies/{company}/invoices/{id}/corrective, scope invoices:write. It answers 201 with the new invoice and a Location header pointing at it.

All the routes in this guide hang off /v1/companies/{company}/…: {company} is the id (UUID v7) of the tax ID you operate on, and in the curl examples it is $COMPANY_ID. Reach a tax ID explains how to resolve it.

FieldRequiredNotes
correction_reasonYesOne of the eight slugs above.
correction_typeYesfull or partial.
correction_natureNoI (by differences) or S (substitution). See Substitution or differences.
correction_codeNoR1–R5. Validated against the legal matrix.
series_idNoSeries the corrective is numbered in. It must be a corrective series (invoice_kind: corrective, or simplified_corrective for an R5); without it, the default one is used. See Numbering and series.
justificationNo10–1000 characters. Mandatory in practice for R2 and R3.
notesNoFree text, up to 1000 characters.
pdf_template_idNoUUID of the PDF template (or null to inherit). See Choosing the template.
linesRequired for a partial correction and for a substitutiondescription, quantity, unit_price, and optionally tax_rate, discount_percent, indirect_tax_regime, product_id and the fiscal nature of the line: unit, regime_key, exemption_reason, exemption_reason_text.

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/companies/$COMPANY_ID/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/companies/{company}/invoices/{id}/correctives.

How the lines are built

The three ways to correct 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 and prefixed [ANULACION], 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, and correction_nature: S is optional because this combination is a substitution by default. 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, prefixed [AJUSTE]. 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.

Nature of each corrected line. A line may declare unit, regime_key, exemption_reason and exemption_reason_text, with the same rules as POST /v1/companies/{company}/invoices. They follow the presence of the key: a key you omit inherits the value of the original line at the same index; a key you send — even null — replaces it, and null means explicitly none. For example, exemption_reason: null turns an exempt original line into a taxed one. It applies to both a substitution and a correction by differences, and the same keys exist in the MCP tool create_corrective_invoice.

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.

Numbering and series

Every invoice series has a fixed purpose (invoice_kind), and a document is only numbered in a series of its own purpose (BR-INV-076):

DocumentSeries purposeCreated automatically if missing
Corrective of a complete invoice (R1–R4)correctiveR
Corrective of a simplified invoice (R5)simplified_correctiveRS

A corrective is numbered with the correlative counter of that series and its format, so with the default format the numbers are R-2026-001, R-2026-002… for complete invoices and RS-2026-001… for simplified ones. The original keeps its own number, its status and its VeriFactu record; the corrective references it by its number.

Send series_id to choose the series, otherwise the default series of the right purpose is used and, if the company has none, it is created on the spot. A series of another purpose is rejected with 422 series_invoice_kind_mismatch; so is an archived one or one of another company. A corrective is never duplicated (invoice_not_duplicatable_in_current_state): to correct the original again, issue a new corrective from it.

What appears on the PDF

The corrective is printed as a separate document with its own number, taken from its corrective series (see Numbering and series).

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.

Choosing the template

A corrective is a new document with its own presentation: it does not copy the template of the original. Both POST /v1/companies/{company}/invoices/{invoice}/corrective and POST /v1/companies/{company}/invoices/substitute-simplified accept the optional pdf_template_id:

You sendResult
Nothing, or "pdf_template_id": nullThe template is inherited, in this order: the corrective series (R or RS), the customer, the company default for the document type and purpose, the company default.
"pdf_template_id": "<uuid>"Manual choice. It must be compatible with the purpose of the document.

The purpose decides which templates fit: corrective for a correction of a complete invoice (R1–R4), simplified_corrective for one of a simplified invoice (R5) and complete for the complete invoice that substitutes simplified ones. expected_selection_version is not accepted on these two operations — there is no earlier version to compare — and neither is pdf_template_uuid; sending either answers 422 when the revisioned presentation is active for your company and is ignored otherwise. While the revisioned presentation is not active for your company, pdf_template_id is ignored and the corrective renders as before.

curl -X POST https://api.factuarea.com/v1/companies/$COMPANY_ID/invoices/0197b1c2-89ab-7def-8123-456789abcdef/corrective \
  -H "Authorization: Bearer $FACTUAREA_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -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 }
    ],
    "pdf_template_id": "0197c4a1-02aa-7c31-9e5b-6d2f8a4c1b73"
  }'

The corrective is issued as it is created, so its presentation is retained at that moment. Changing how its PDF looks later is a presentation revision, never an edit: see Document presentations. The structured business data of an invoice (payment schedule, references, DIR3 centres) is covered in Invoice business data: a corrective takes a payment schedule of its own (negative instalments are valid) and inherits line references only through source_line_id. A corrective falls due on the day of its last instalment, or 30 days after it is issued when it has no schedule.

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 exactly S or I.
  • BR-INV-018 — the mapping from reason slug to R1–R4.
  • BR-INV-019 — a corrective of an F2 is born R5.
  • BR-INV-021 — the invoice number format SERIES-YYYY-NNN.
  • BR-INV-076 — a series only numbers documents of its own purpose; correctives in their own series.
  • BR-INV-078 — the three ways to correct and the coherence of nature, scope and lines.
  • 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.
  • BR-PDF-022 — how the template of a document is selected and the precedence ladder.
  • BR-INV-086 — line identity and what a corrective inherits by source_line_id.

On this page

Need a hand?Contact support