Create a rectifying invoice
Issue rectificativas through the same create endpoint: correct an invoice by differences or substitution, whether the original was issued through Finseed or elsewhere.
POST /v1/invoices endpoint as an ordinary invoice: add a rectifies block. A rectificativa is a real invoice — its own number from a rectifying series, its own Verifactu record and hash, its own PDF — so the response is the full invoice object, with kind set to rectifying_differences or rectifying_substitution and rectifies[] pointing at the corrected original.
Choosing method and reference
Method decides how the correction books:differencesrecords only the delta. Theline_itemsare the change (usually negative lines to reduce, positive to add).substitutionrestates the invoice in full. Theline_itemsare the complete replacement.
-
invoice_id: an invoice issued through Finseed, by its opaqueinv_id. This is a linked rectificativa.typemust state the form the rectificativa takes, and by default it matches the corrected invoice. Whentypematches, the recipient is inherited from the corrected invoice, so on adifferencesyou omit the recipient entirely, and on asubstitutionyou may supply arecipientblock to restate it. Declaringtype: "simplified"over a complete original is rejected withdowngrade_to_simplified_not_allowed, because an invoice that already identifies its recipient cannot drop that identification. The original must have finished registering at the tax agency before it can be corrected. A rectificativa sent while it is still registering is refused with503 invoice_pending_at_aeat, and nothing is persisted. Registration usually completes within minutes and needs no action on your side, so wait for the interval in theRetry-Afterheader, or poll the invoice until itsverifactu.statusleavespending. The retry can carry the sameIdempotency-Key: this status releases the key, so the retry runs against the current state instead of replaying the refusal. Arecipientblock that restates the fiscal identity of a complete original is validated before the rectificativa exists, exactly as on any other complete invoice. Fiscal identity means the tax id, its type, its country, and the recipient’s name (nameandcompany_name, since either can be the name filed to the tax agency). How far that validation goes depends on the id type, as it does for an original: a Spanish NIF is checked against the AEAT census together with the name, an EU VAT number against VIES, which checks the number only, and the remaining types are never checked against an external register. Restating only address or contact data is not validated and costs no round trip. Six refusals follow, and in every one nothing is persisted:invalid_tax_id: the restated tax id is not usable. For a Spanish NIF that means the AEAT census does not recognize the id and name together; for an EU VAT number, that VIES does not recognize the number. For every type it also covers a tax id whose format is wrong, which is decided locally.insufficient_recipient_data: the recipient data cannot be used to identify anyone. This is decided locally, before any register is contacted, so retrying does not help. The contract is looser than the register on several fields, so a request that passes schema validation can still be refused here: a name shorter than 2 or longer than 100 characters, where the contract allows 1 to 200 (the limit applies tocompany_namewhen you send one, otherwise toname); or anaddress.countryortax_id_countrythat is a valid two-character code the register does not accept as a recipient country, such asUK.tax_id_validation_unavailable: AEAT or VIES is down. Retry with the sameIdempotency-Key.tax_id_type_country_mismatch: thetax_id_typeandtax_id_countrycontradict each other. This is decided before any register is contacted.recipient_changed_during_validation: another operation changed the corrected invoice’s recipient tax data between this request’s checks and its write. Retry with the sameIdempotency-Key.invalid_tax_data: a line’s tax has no classification in the merchant’s tax catalog. This is decided locally, before any register is contacted, because the restated recipient runs the same payload validation as any other invoice. The fix is to classify the tax, not to change the recipient. Classifying it does not change the request body, so retry with a newIdempotency-Key: the same key replays the stored refusal verbatim.
-
external— an invoice issued elsewhere (a pre-Finseed original a migrated merchant corrects). This is an external rectificativa: because there is no original in Finseed, a complete invoice requires a fullrecipient, and asubstitutionrequiresrectified_amounts(the base, tax and optional surcharge of the original, which the tax agency needs and Finseed cannot infer).
invoice_id and external, or neither, is rejected with invalid_rectifies_reference.
Reason (reason) encodes the cause in the AEAT R1-R4 code. It defaults to correction (R1). Use insolvency (R2) for concurso, uncollectible (R3) for créditos incobrables, or other (R4). Simplified rectificativas always register as R5.
The number_series_id, when supplied, must name a rectifying series (unlike an ordinary invoice, which uses a standard series). Omit it to use the environment’s default rectifying series. For a linked rectificativa against an order-linked invoice, number_series_id is rejected with num_series_not_applicable_for_order_invoice: that correction always numbers on the rectifying series its integration owns for its kind (simplified or complete), and cannot be overridden.
The form of a linked rectificativa
On a linked rectificativatype must match the form of the corrected invoice. type: "simplified" over a complete original is refused with downgrade_to_simplified_not_allowed. type: "complete" over a simplified original is refused with upgrade_to_complete_not_allowed: a rectificativa cannot add a recipient to a simplified invoice.
The instrument that issues a complete invoice for a simplified one is a factura de canje (AEAT invoice type F3), and this API does not offer it yet. Which route applies depends on where the simplified invoice came from. An original created directly in Finseed, through this API or the app, can be exchanged in the Finseed app, as long as it is not itself a rectificativa and is still the only active invoice of its correction chain. One generated from an integration order is not exchanged that way: it becomes complete automatically once the order carries the recipient tax data.
Examples
Partial refund by differences against a Finseed invoice (linked). The recipient is inherited from the corrected invoice:recipient block restates the recipient on the replacement:
rectified_amounts. The amounts are the original’s base and tax in cents:
Dry-running and errors
POST /v1/invoices/validate accepts the same rectifies block and runs the identical checks without persisting anything, returning the totals the rectificativa would carry. Every corrective rule surfaces as a stable error code — for example invoice_pending_at_aeat when the original has not finished registering, invoice_not_family_tip when a later rectificativa already supersedes it, or rectified_amounts_required_for_substitution on an external substitution. See Errors for the full list.Autorizaciones
API key sent as a bearer token in the Authorization header.
Encabezados
Optional key that makes the request safe to retry: 1 to 255 printable ASCII characters. Sending the same key with the same body within 24 hours returns the stored response instead of executing again; such a replay carries an Idempotent-Replayed: true header. Reusing a key with a different body is rejected.
Cuerpo
The invoice to issue.
- Option 1
- Option 2
The invoice to issue. The invoice number, issue date and totals are assigned server-side; the optional operation_date is the only date the caller sets. Issuance is immediate and the AEAT registration progresses asynchronously (poll verifactu.status). Include a rectifies block to issue a rectificativa instead of an ordinary invoice.
The lines to bill. At least one.
1 - 500 elementsA complete invoice: the recipient is identified and their tax id is validated against the census when it is a Spanish NIF or an EU VAT number. On a linked rectificativa (a rectifies.invoice_id) of a complete original, the recipient is inherited from the corrected invoice and may be omitted; when supplied on a substitution it restates the recipient. On a linked rectificativa type must match the corrected invoice: complete over a simplified original is refused with upgrade_to_complete_not_allowed, and simplified over a complete original with downgrade_to_simplified_not_allowed.
"complete"Your own reference for this invoice, such as an order id: 1 to 255 characters, no control characters. Unique per environment: a later request carrying the same value is rejected with external_id_already_used no matter how old the original is, which is the guard against duplicates that the 24-hour Idempotency-Key window cannot give. Once used, a value stays taken even after the invoice is voided. Echoed as external_id on the invoice.
1 - 255^[^\p{Cc}]{1,255}$"order-84312"
Number series to issue on (see the Number Series resource). Defaults to the environment default series. For an ordinary invoice this must be a standard series; for a rectificativa (a rectifies block) it must be a rectifying series. Rejected with num_series_not_applicable_for_order_invoice on a linked rectificativa against an order-linked invoice, which always numbers on the rectifying series its integration owns for that kind of correction.
"ns_clx456def789"
Turns this request into a rectificativa (corrective invoice). Reference the original with exactly one of invoice_id (issued through Finseed) or external (issued elsewhere). Omit the whole block to issue an ordinary invoice.
Date the underlying operation took place, as a calendar day (YYYY-MM-DD) interpreted in the Europe/Madrid timezone. Must be an existing calendar day between 2025-01-01 and today. When omitted, or when it equals the issue date, the invoice carries the issue date as its operation date. Not supported together with a rectifies block.
^(\d{4})-(\d{2})-(\d{2})$"2025-06-15"
Applies the Spanish recargo de equivalencia regime: every VAT line gains its legally paired surcharge (21%→5.2%, 10%→1.4%, 4%→0.5%), computed server-side.
false
Free-form text printed at the bottom of the invoice PDF.
2000"Pago a 30 días."
The identified recipient of a complete invoice.
Respuesta
The issued invoice.
A tax invoice as exposed by the public API.
Opaque, prefixed invoice identifier.
"inv_clx123abc456"
Lifecycle status of the invoice. This is an extensible enum: new values may be added in the future, so clients must tolerate values not listed here. Known values: issued, voided.
"issued"
Human-readable invoice number.
"2026-000123"
Lowercase ISO 4217 currency code.
"eur"
Net total before tax, in minor units (cents) of the currency.
8300
Total tax, in minor units (cents) of the currency.
1743
Gross total including tax, in minor units (cents) of the currency. Always equals subtotal + tax.
10043
Fiscal name of the invoice recipient (company or person), or null when none is recorded.
"ACME, S.L."
Tax identifier of the recipient (e.g. NIF/CIF), or null when none is recorded.
"B12345678"
Recipient email, or null when none is recorded.
Customer identifier from the originating integration, or null when unavailable.
"cus_9aZ"
The external_id supplied when the invoice was created through the API, or null when none was given.
"order-84312"
Invoice issue date, RFC 3339 in UTC.
"2026-06-01T09:30:00Z"
Date the underlying operation took place, RFC 3339 in UTC. Often equal to invoice_date.
"2026-06-01T09:30:00Z"
Creation timestamp, RFC 3339 in UTC.
"2026-06-01T09:30:00Z"
Whether this is a complete invoice (identified recipient) or a simplified invoice (ticket). This is an extensible enum: new values may be added in the future, so clients must tolerate values not listed here. Known values: complete, simplified.
"complete"
Identifier of the number series the invoice was issued on. See the Number Series resource.
"ns_clx456def789"
Full recipient block as recorded on the document, or null when no recipient data exists (simplified invoices). The flat recipient_name/recipient_tax_id/email fields remain as convenience aliases.
Signed link to the invoice PDF, valid for at least 24 hours from the moment this response was produced. Fetch a fresh one anytime by re-reading the invoice, or use the download endpoint. The PDF is generated shortly after creation; downloading earlier just takes a moment longer.
"https://api.finseed.es/v1/invoices/inv_clx123abc456/file?token=..."
Verifactu artifacts and AEAT registration state. Null only for legacy invoices imported before Verifactu tracking existed.
The lines that make up the invoice.
Whether this is an original invoice, a rectifying (corrective) one and by which method, or an exchange invoice. rectifying_differences corrects by the delta; rectifying_substitution replaces the original in full; exchange is the complete invoice issued in exchange for one or more correct simplified invoices (AEAT type F3), which stay valid and are not corrected. This is an extensible enum: new values may be added in the future, so clients must tolerate values not listed here. Known values: original, rectifying_differences, rectifying_substitution, exchange.
"original"
The invoices this invoice rectifies. Empty for originals. A rectificativa issued against invoices in Finseed carries one { invoice_id } entry per corrected invoice; one issued against an external original carries a single { external: { number, issued_on } } entry.
An invoice a rectificativa corrects: either a local invoice ({ invoice_id }) or an external original ({ external: { number, issued_on } }).
- Option 1
- Option 2
The rectifying invoices that correct this invoice, one { invoice_id } entry each. Empty when nothing rectifies it. Voided rectificativas are excluded.