NewProvince is only required for addresses in Spain
BeeL
Get startedMulti-NIFVeriFactuRulesStripeAPI referenceChangelog

Series by type, and what AEAT would reject is refused before numbering

A series numbers only its own type, and an invoice AEAT would reject answers 422 before a number is used. Zero-total invoices are accepted and issued paid.


ChangelogBreaking

Two changes move failures earlier. A series numbers only the documents of its own type, as the invoicing regulation requires. And with VeriFactu, BeeL. builds the record it will send to AEAT before numbering the invoice and checks it: what used to be an issued invoice with its registration rejected is now a 422, with the invoice still a draft and the number unused. Invoices already issued do not change.

What breaks

  • A series numbers only its own type. A series still UNASSIGNED numbers nothing: creating, editing or issuing with it answers 422 SERIES_INCOMPATIBLE_DOC_TYPE. Every live UNASSIGNED series was given the type it numbered most (STANDARD when it numbered none or there was a tie). A company whose only default was such a series may have no default STANDARD series now: a standard invoice without series_id answers 422 SERIES_DEFAULT_NOT_FOUND until you create or mark one. Drafts and recurring templates pointing at a series that now has another type fail with SERIES_INCOMPATIBLE_DOC_TYPE until you change their series.
  • document_type is locked once a series has numbered. Changing it answers 400 SERIES_DOCUMENT_TYPE_LOCKED_HAS_INVOICES, except to give an UNASSIGNED series its type. Listing series with document_type no longer includes the UNASSIGNED ones.
  • The VeriFactu record is checked before numbering. More than 12 different tax groups on one invoice answers 422 INVOICE_TAX_BREAKDOWN_TOO_LONG; a tax or surcharge rate with more than two decimals, 422 INVOICE_TAX_RATE_TOO_MANY_DECIMALS; any other rule of AEAT's validations the record breaks, its specific code or 422 VERIFACTU_RECORD_NOT_DECLARABLE, with the AEAT section in the message.
  • The recipient's legal_name fits AEAT's 120 characters, counted as AEAT counts them. Under VeriFactu a longer one answers 422 FIELD_TOO_LONG at issue. Length is measured in UTF-16 code units: an emoji or any character outside the Basic Multilingual Plane counts as two, so a name that looks like 119 characters can be too long. The operation description sent to AEAT is shortened to its 500-unit limit, never rejected.
  • An invoice of disbursements only is refused again, with 422 INVOICE_REQUIRES_AT_LEAST_ONE_NORMAL_LINE, a corrective included: put the SUPLIDO line on the invoice of the operation it belongs to.
  • operation_date more than twenty years old answers 422 OPERATION_DATE_TOO_OLD, on create, edit and issue.
  • A simplified invoice cannot document an operation located outside Spain. A line with exemption_reason NO_SUJETA_LOCALIZACION, like EXENTA_ART_25 before it, answers 400 SIMPLIFICADA_FORBIDS_CROSS_BORDER, now also when an edit makes the invoice SIMPLIFIED, when it is issued, and on an R5 corrective that adds such a line.

Does this affect you?

  • If you pass a series_id stored long ago, check its document_type with GET /v1/companies/{company_id}/series/{series_id}.
  • If you issue standard invoices without series_id, check GET /v1/companies/{company_id}/series/defaults.
  • If your recipients' names can carry emojis or long legal forms, cut them to 120 UTF-16 code units (string.length in JavaScript, Java or C#).
  • If you create invoices of disbursements only, or that total 0 and then mark them paid, adjust that flow.

What else changed

  • The default SIMPLIFIED and CORRECTIVE series are created on first use (code S or R, or the next free one). Only a missing default STANDARD series still answers SERIES_DEFAULT_NOT_FOUND, and the issuing readiness reports only that one.
  • An invoice whose total is 0 is accepted and issued as PAID, with payment_date equal to issue_date, and registered with AEAT with a total of 0. INVOICE_ZERO_AMOUNT is retired. Calling mark-paid or mark-sent on it answers 400: it is already paid.
  • Fewer asynchronous rejections. These invoices used to reach AEAT and come back REJECTED; now they fail on the request, so an integration that handles verifactu.status.updated sees fewer rejections and more 422s.

Endpoints

  • POST/v1/companies/{company_id}/invoices422 SERIES_INCOMPATIBLE_DOC_TYPE, INVOICE_REQUIRES_AT_LEAST_ONE_NORMAL_LINE, OPERATION_DATE_TOO_OLD; a total of 0 is accepted
  • POST/v1/companies/{company_id}/invoices/{invoice_id}/issue422 INVOICE_TAX_BREAKDOWN_TOO_LONG / INVOICE_TAX_RATE_TOO_MANY_DECIMALS / VERIFACTU_RECORD_NOT_DECLARABLE / FIELD_TOO_LONG before numbering
  • PATCH/v1/companies/{company_id}/series/{series_id}400 SERIES_DOCUMENT_TYPE_LOCKED_HAS_INVOICES
  • GET/v1/companies/{company_id}/seriesdocument_type returns only the series of that type

Where to go next