Cancel vs amend

Decide between cancelling an invoice (void) and issuing a corrective (rectificativa). Each operation has different fiscal weight.


The AEAT VeriFactu spec exposes three distinct fix operations: anulación, subsanación, and rectificativa. They look similar but mean very different things. Pick the wrong one and you either misreport or burn an invoice number.

The 30-second decision

What's wrong with the invoice?

├─ Issued by mistake — never should have existed
│  → ANULACIÓN  (POST /invoices/{id}/void)

├─ Numbers / customer / amount need correction
│  → RECTIFICATIVA  (POST /invoices/{id}/corrective — see Corrective invoices)

└─ Non-fiscal metadata typo (descripción, custom field, ...)
   → SUBSANACIÓN  (BeeL handles internally on AEAT rejection;
                    no public endpoint to drive manually)
OperationUse whenFiscal weightOriginal status after
Anulación (void)The invoice shouldn't exist at all — wrong customer billed, accidental duplicateA registro de anulación is sent to AEAT, linked to the originalVOIDED (no corrective in chain)
Rectificativa (corrective)The invoice should exist but the data is wrongNew registro corrects or replacesRECTIFIED (PARTIAL) / VOIDED (TOTAL)
Subsanación (internal)A previous registro was rejected by AEAT for a non-fiscal reason and needs a retry with the corrected metadataUpdates the in-flight registro, no new fiscal recordSame as before

Anulación does not fix errors. AEAT explicitly says: if the invoice has incorrect data but the operation actually happened, you must issue a rectificativa. Use anulación only for invoices that were issued in error and have no commercial reality.

Anulación (void)

curl -X POST "https://app.beel.es/api/v1/invoices/{invoice_id}/void" \
  -H "Authorization: Bearer beel_sk_live_xxx"

What happens:

  1. The invoice's commercial status moves to VOIDED.
  2. BeeL submits a registro de anulación to AEAT (separate from the original registro de alta).
  3. AEAT processes the cancellation and BeeL updates the invoice's verifactu.submission_status to reflect the cancellation response.

What you give up:

  • You cannot reissue the same serie + numero afterwards. AEAT remembers the number was used.
  • The original registro de alta stays in AEAT's records (with the anulación linked to it).

If you simply realised the customer never existed and you want to "free up" the invoice number, this is not the way — AEAT does not allow renumbering. Pick a different serie + numero for the next attempt.

See the voidInvoice API reference for the full schema.

Rectificativa (corrective)

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": "R1",
    "reason": "Customer-agreed post-issuance discount on professional services.",
    "lines": [
      { "description": "Discount adjustment", "quantity": -1, "unit_price": 200, "discount_percentage": 0,
        "main_tax": { "type": "IVA", "percentage": 21, "regime_key": "01" } }
    ]
  }'

A new invoice is issued, referencing the original. Its own AEAT tipo_factura is R1/R2/R3/R4/R5, and it has its own registro de alta (no anulación). The original stays RECTIFIED (PARTIAL) or VOIDED (TOTAL) — but is never erased from AEAT.

Use rectificativa for:

  • Wrong amount / IVA rate
  • Wrong customer NIF or name
  • Post-issuance discount or quantity adjustment
  • Bad debt write-off
  • Concurso de acreedores adjustment
  • Converting an F2 ticket into a proper F1 (R5 TOTAL on the F2 + new F1)

See Corrective invoices for every scenario with payloads.

Subsanación (amend the registro)

Subsanación is the AEAT mechanism for resubmitting a rejected registro with corrected metadata. The fiscal record stays the same — only the metadata changes.

BeeL handles subsanación for you on AEAT rejection: when an invoice's verifactu_status is REJECTED because of a non-fiscal field (typo in description, wrong serie code mapping), BeeL retries the submission with the corrected metadata. There is no public API endpoint to drive subsanación manually.

If subsanación isn't enough (e.g. you need a rechazo_previo value that BeeL doesn't set automatically), write to it@beel.es — we'll handle it operationally.

Decision matrix

SymptomOperationNotes
Issued an invoice for the wrong customer entirelyAnulación (void)Then issue a new one for the right customer
Invoice was a duplicate (you accidentally fired the endpoint twice)Anulación (void) on the duplicateOriginal stays valid
Customer's NIF was wrongRectificativa R1 TOTALAnulación + reissue also works but leaves an anulación in the AEAT trail
Amount was wrong (under-/over-charged)Rectificativa R1 PARTIAL (delta) or TOTAL (replace)Pick based on bookkeeping preference
Customer didn't pay and you wrote off the debtRectificativa R3Pair with the legal claim documentation
AEAT rejected because of a typo in descripcionBeeL retries automaticallyNo new invoice needed
AEAT rejected because of a wrong NIFAnulación + reissue with correct NIF, or rectificativa R1Subsanación can't fix fiscal data
Invoice was sent to AEAT but you've discovered an IVA-rate errorRectificativa R1Most common case