Corrective invoices (R1–R5)

Pick the right rectification type and code, and see the canonical request shapes BeeL accepts for each scenario.


A corrective invoice (factura rectificativa) corrects a previously issued invoice. BeeL exposes them through POST /v1/invoices/{invoice_id}/corrective — the URL points to the original invoice, and the body describes the correction.

You decide two things:

  • rectification_typeTOTAL (replace / cancel the original) or PARTIAL (apply a delta)
  • rectification_codeR1R5 (the legal motive)

Plus a free-text reason describing the situation in human language.

The two axes

           PARTIAL  (one delta registro, easy bookkeeping)
        ┌────────────────────────────────────────────────┐
why →   │  R1   │  R2   │  R3   │  R4   │  R5  (F2 only) │
        ├────────────────────────────────────────────────┤
           TOTAL    (one registro replaces the original)
rectification_typeAEAT tipo_rectificativaWhat BeeL sends to AEAT
PARTIALI (por diferencias)One registro with delta lines; no importe_rectificativa block
TOTALS (por sustitución)One registro with the new totals + the original totals echoed in importe_rectificativa

The original invoice's status changes after issuance:

  • PARTIAL → original becomes RECTIFIED (can be corrected again)
  • TOTAL → original becomes VOIDED (terminal, no further correctives)

Pick the reason (R1–R5)

rectification_codeWhen to useLegal basis
R1Almost every common correction: wrong amount, post-issuance discount, returned goodsArt. 80 Uno/Dos/Seis LIVA + error fundado en derecho
R2The customer is in formal concurso de acreedoresArt. 80 Tres LIVA
R3Bad debt: invoice is uncollectable after the legal procedureArt. 80 Cuatro LIVA
R4Customer-requested cancellation, post-issuance changes outside R1–R3Resto de causas
R5Correcting a simplified (F2) invoice — any reasonArt. 80 Uno/Dos LIVA for F2

R5 is for F2 only. You cannot correct an F1 with R5, and you cannot correct an F2 with R1–R4. BeeL rejects mismatches at the API boundary.

Scenario 1 — TOTAL cancellation (R1)

The original should be cancelled outright (e.g. project cancelled before commencement). No lines needed for TOTAL — BeeL replaces the original with empty content.

curl -X POST "https://app.beel.es/api/v1/invoices/{invoice_id}/corrective" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "rectification_type": "TOTAL",
    "rectification_code": "R1",
    "reason": "Cancellation of invoice issued due to a legally founded error under Art. 80 Uno LIVA. The transaction was not completed due to project cancellation before commencement.",
    "notes": "Original invoice F/2025/0042 fully cancelled. Customer notified."
  }'

The original becomes VOIDED; the corrective carries the matching tipo_rectificativa S to AEAT.

Scenario 2 — PARTIAL adjustment for bankruptcy (R2)

Customer entered concurso de acreedores; you adjust the outstanding amount to what the insolvency administrator agreed. Send the delta as a PARTIAL:

curl -X POST "https://app.beel.es/api/v1/invoices/{invoice_id}/corrective" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "rectification_type": "PARTIAL",
    "rectification_code": "R2",
    "reason": "Partial correction of invoice due to customer bankruptcy proceedings under Art. 80 Tres LIVA. Amount adjusted to the agreement reached with the insolvency administrator.",
    "lines": [
      {
        "description": "Adjustment for bankruptcy proceedings - 40% amount reduction",
        "quantity": -16,
        "unit": "hours",
        "unit_price": 37.5,
        "discount_percentage": 0,
        "main_tax": {
          "type": "IVA",
          "percentage": 21,
          "regime_key": "01"
        }
      }
    ],
    "notes": "Correction approved by insolvency administrator. Case 123/2024 Commercial Court No. 2 Madrid."
  }'

Lines carry negative quantity (or negative unit_price) to express the reduction. The original stays RECTIFIED.

Scenario 3 — PARTIAL bad-debt write-off (R3)

Documented bad debt under Art. 80 Cuatro LIVA. Send a negative line that zeroes out the IVA on the uncollectible part:

curl -X POST "https://app.beel.es/api/v1/invoices/{invoice_id}/corrective" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "rectification_type": "PARTIAL",
    "rectification_code": "R3",
    "reason": "Partial correction for bad debt under Art. 80 Cuatro LIVA. More than 6 months have elapsed since the invoice due date and collection efforts via notarial demands have been documented without result.",
    "lines": [
      {
        "description": "Bad debt adjustment - Full cancellation of outstanding amount",
        "quantity": -40,
        "unit": "hours",
        "unit_price": 37.5,
        "discount_percentage": 0,
        "main_tax": {
          "type": "IVA",
          "percentage": 21,
          "regime_key": "01"
        }
      }
    ],
    "notes": "Collection efforts documented via notarial demands (Protocol 456/2024). Original invoice due on 15/03/2024."
  }'

Scenario 4 — TOTAL customer-requested cancellation (R4)

Catch-all for valid corrections outside R1–R3. The customer asked to cancel the whole invoice:

curl -X POST "https://app.beel.es/api/v1/invoices/{invoice_id}/corrective" \
  -H "Authorization: Bearer beel_sk_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{
    "rectification_type": "TOTAL",
    "rectification_code": "R4",
    "reason": "Invoice cancellation at customer'\''s request. The service was cancelled before delivery and full cancellation of the invoice has been agreed.",
    "notes": "Invoice cancelled at customer'\''s request. No outstanding amount pending collection."
  }'

Scenario 5 — R5: cancelling an F2 to issue a proper F1

You issued an F2 ticket and the customer now needs an identified F1. The clean path:

  1. TOTAL corrective with rectification_code: R5 on the F2

    curl -X POST "https://app.beel.es/api/v1/invoices/{f2_invoice_id}/corrective" \
      -H "Authorization: Bearer beel_sk_live_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "rectification_type": "TOTAL",
        "rectification_code": "R5",
        "reason": "Customer requested an identified invoice replacing the original simplified ticket.",
        "notes": "Replaced by F1 issued same date with full recipient data."
      }'
  2. New F1 (POST /v1/invoices with type: STANDARD) with the customer's NIF and full data.

Both records stay in AEAT (the F2, its R5 cancellation, and the new F1). The running fiscal total reconciles.

Validation rules BeeL applies

RuleWhat happens if you break it
rectification_code must match the original type (R5 ↔ F2, R1–R4 ↔ F1)Rejected at issuance with a clear error
Original must exist and belong to your accountRejected — the URL {invoice_id} resolves to nothing
Original cannot already be VOIDED (TOTAL terminates the chain)Rejected — chain is closed
For PARTIAL, line totals can be negative or positive — anything goes mathematically
For TOTAL, omit lines (BeeL clears the original); for PARTIAL, lines are required