Factuarea API

Annul or correct

Four operations look like "undo an invoice" and only one is right for each case — delete, cancel, annul and corrective. Pick wrong and you either lose a fiscal document or file a declaration you did not intend.

An issued invoice cannot be edited. Everything that looks like editing one is really one of four different operations, each with its own preconditions and its own consequence at the tax authority. This page is the decision table, and the reason behind each branch.

When this applies

Whenever something is wrong with an invoice and you need to undo it. The invoice's current status narrows the legal options; where more than one is legal, your intent decides. How serious the mistake is never enters into it.

Invoice statusNumber assigned?OperationConsequence
draft, and nothing about it is worth keepingNoDeleteDELETE /v1/invoices/{id}The record disappears. Nothing was ever fiscal.
draft, but you want the attempt on recordNoCancel — change status to cancelledThe draft is retired but kept.
sent, overdue — the invoice should never have been issuedYesAnnulPOST /v1/invoices/{id}/annulThe invoice stops being collectable and an annulment is declared to the AEAT.
sent, paid — the invoice was right to exist, its content is wrongYesCorrectivePOST /v1/invoices/{id}/correctiveA new fiscal document referencing the original.
sent, but only the delivery mark was wrongYesClear delivery markPOST /v1/invoices/{id}/unsendThe delivery timestamp is cleared. The invoice stays issued.

Three rules make the table unambiguous:

A numbered invoice is never physically deleted. Deletion requires status draft (or a cancelled that came from a draft) and a number that is still the draft placeholder. Any invoice that consumed a number from its series is protected by fiscal soft-delete; the way to retire it is annulment (BR-INV-002, art. 29.4 of the Spanish General Tax Act on the duty to preserve documents with tax relevance).

A paid invoice is closed. paid is terminal: its output VAT has been or will be declared for the period and the collection is identified, so annulling it would break traceability and distort the VAT returns. The canonical path is a corrective (BR-INV-023).

On sent, both are legal — so ask what went wrong. A corrective is allowed on sent or paid (BR-INV-001) and an annulment on sent or overdue (BR-INV-003), so sent is the one status where the API will accept either. The status cannot decide for you; the question does:

  • The invoice should never have existed — the order was cancelled, it went to the wrong customer, it duplicates another one → annul.
  • The invoice was right to issue but its content is wrong — wrong amount, wrong tax rate, wrong recipient details, a partial return → corrective.

Reach for annulment on a merely wrong amount and you declare an ANULACION to the AEAT and burn the number for nothing; the corrective was the clean path and it stays available on sent.

Cancel is not annul

They are different acts, and the domain keeps them apart on purpose.

Cancelling retires a draft — a document that is not yet fiscally binding. It is only available from draft, and cancelled is terminal: a cancelled draft cannot be revived, you create a new one (BR-INV-012).

Annulling retires an issued invoice. It is only available from sent or overdue. It is not a delete: the invoice stays in the ledger, in status annulled, and if the company is on VeriFactu the annulment is itself declared.

Trying to cancel an issued invoice, or to annul a draft, answers 422 with an invalid-transition error. That status code is deliberate: this is a business-rule violation, not a permissions problem.

Correctives cannot be annulled

A corrective invoice is never annulled. If a corrective itself is wrong, you issue a new corrective of the original invoice (BR-INV-003). Attempting it answers 422.

The reasoning is that a corrective's whole meaning is "this document modifies that one". Annulling the modification would leave the original in an ambiguous state at the tax authority, where both documents are already registered.

Unsend undoes a delivery mark, not an issue

unsend exists for one specific mistake: marking an invoice as delivered when it was not. It clears the delivery timestamp and keeps the status at sent. The series number, the registration at the AEAT and the frozen snapshots are all untouched, because an issued invoice is immutable (BR-INV-030, RD 1007/2023).

Two properties matter for integrations:

  • It is idempotent. Calling it again when the timestamp is already cleared is a controlled no-op, never a 500.
  • It is strictly scoped to sent. On a paid, annulled, cancelled or scheduled invoice it answers 422 — never 403.

The status transition matrix contains no path from sent back to draft by any route, including the generic status-change endpoint. There is no "un-issue".

What the API sends

Check first. GET /v1/invoices/{id}/can-annul (scope invoices:read) tells you the answer before you commit, including whether the annulment will produce an extra VeriFactu record:

curl https://api.factuarea.com/v1/invoices/0197a2a8-4cf0-7a31-9a5e-3f2b8c1d6e42/can-annul \
  -H "Authorization: Bearer fact_live_3pXnR2VbY7TcA9eFmN5z8KqW"
{
  "data": {
    "can_annul": false,
    "reasons": ["La factura está pagada."],
    "will_create_verifactu": false,
    "info": []
  }
}

Then annul. POST /v1/invoices/{id}/annul (scope invoices:void) records the reason:

curl -X POST https://api.factuarea.com/v1/invoices/0197a2a8-4cf0-7a31-9a5e-3f2b8c1d6e42/annul \
  -H "Authorization: Bearer fact_live_3pXnR2VbY7TcA9eFmN5z8KqW" \
  -H "Content-Type: application/json" \
  -d '{"reason": "El cliente cancela el pedido tras la emisión"}'

POST /v1/invoices/{id}/void reaches the same domain operation under the external name the API contract uses for the state (voided). Prefer annul when you want the reason recorded; a second call on an already-annulled invoice answers 422 either way.

For the corrective path — payload, R-codes, line inheritance — see Corrective invoices.

What appears on the PDF

Annulment does not rewrite the original document. The invoice keeps its number, its frozen recipient and issuer data and its QR block; what changes is its status in the ledger and the fact that a second declaration now exists at the AEAT.

Deleting a draft removes the document altogether — but a draft never had a definitive number, a frozen snapshot or a QR to begin with, which is exactly why deletion is safe there and nowhere else.

unsend changes nothing on the printed document. It only clears a delivery timestamp; the invoice does not become editable again (BR-INV-030).

What reaches the AEAT

Annulment of an invoice from a VeriFactu company produces a second billing record of kind ANULACION, chained to the company's latest record and referring to the original registration (BR-VFC-014). It is created asynchronously, after the transaction commits, so the invoice reaches annulled in your database before the declaration is transmitted. Poll the record if you need to confirm the AEAT accepted it — see VeriFactu submission states.

There is one subtlety with real consequences. If the original registration was never accepted — it is rejected, errored, or still pending — the annulment must declare explicitly that no previous record exists at the AEAT. The system derives that flag from the registration's status at the moment the annulment is created and persists it as a snapshot, so a later change of the original's status does not desynchronise the XML that was already transmitted. Without the flag, the AEAT refuses the annulment outright with "the billing record does not exist" (BR-VFC-026).

Cancelling and deleting a draft reach the AEAT in no way at all: a draft was never declared.

Correctives are ordinary fiscal documents and produce their own registration, exactly like any other invoice.

If the company is not on VeriFactu, annulment still works and simply produces no declaration.

Traceability

Derived from the domain rules of the Factuarea backend:

  • BR-INV-001 — a corrective requires an original in sent or paid; that overlap with annulment on sent is why intent, not status, decides there.
  • BR-INV-002 — fiscal soft-delete: a numbered invoice is never physically deleted.
  • BR-INV-003 — annulment is limited to issued invoices; correctives are never annulled.
  • BR-INV-012 — cancellation is limited to drafts and is terminal.
  • BR-INV-023paid is a closed state; correct it with a corrective, never an annulment.
  • BR-INV-030unsend clears the delivery mark, keeps the invoice issued, is idempotent, and answers 422 rather than 403.
  • BR-VFC-014 — the annulment record kind and the chain it belongs to.
  • BR-VFC-026 — the "no previous record" flag on the annulment of a registration that was never accepted.

Also derived from the invoice status machine documented alongside those rules, which is the source of truth for the transitions quoted in When this applies.

On this page