# A new series needs its document type, and what else changes in this release

A new series needs `document_type`, several rejections now carry a specific code or status, and an issued invoice's PDF never changes. Plus behaviour changes.

Sep 25, 2026 · Breaking

Several changes can break a request that works today: a new invoice series must say which documents it numbers, a `NIF_IVA` or any foreign identifier must be one AEAT accepts, recipient data that used to be ignored is now refused, and many rejections that answered a generic code now name their cause. The rest change what a working integration receives, without any request having to change. Existing series, invoices, numbers and PDFs are not touched.

## What breaks

- **`document_type` is required when you create a series**, on `POST /v1/companies/{company_id}/series`, on `POST /v1/configuration/series` and in `options.series[]` of the managed-account import and its preview. Without it the request answers `422 VALIDATION_ERROR`. `UNASSIGNED` is no longer accepted for a new series, nor as the new type of an existing one: `422 SERIES_UNASSIGNED_TYPE_NOT_ALLOWED`. Series that were `UNASSIGNED` now number only one type: see [a series numbers only its own type](/changelog/invoice-checks-before-numbering).
- **A `NIF_IVA` must be one AEAT accepts.** An `alternative_id` of type `NIF_IVA` is accepted only with the country of another EU Member State (`422 ALTERNATIVE_ID_VAT_REQUIRES_EU_COUNTRY`) and in that State's EU VAT number format, the country prefix (`EL` for Greece) followed by the national number (`422 ALTERNATIVE_ID_VAT_INVALID_FORMAT`). It applies when you create or edit a customer, create an invoice or a recurring invoice with the recipient inline, and when you issue, before a number is used. Until now such an invoice was issued and then refused by VeriFactu, ending up `REJECTED` with its number spent. A customer saved earlier with one of these identifiers can still be read and edited; to invoice it, change the identifier.
- **A simplified invoice with an identified recipient answers `422`, not `400`, and on every path.** `SIMPLIFIED_INVOICE_FORBIDS_IDENTIFIED_RECIPIENT` now answers `422` when you create a `SIMPLIFIED` invoice whose recipient carries `nif` or `alternative_id`, when an edit changes its type or its recipient, when you issue it — one by one, in bulk or on schedule — and when you write a recurring invoice template. A draft created earlier with an identifier can still be edited, but it is not issued until it becomes `STANDARD` or loses the identifier. When you read invoices, an older simplified invoice may still carry a `nif`.
- **Specific codes instead of generic ones.** Rejections that answered `BUSINESS_RULE_VIOLATION` or `VALIDATION_ERROR` now carry a code of their own, with the same HTTP status: if you branch on `error.code`, they reach a different branch. Sending an invoice: `400 INVOICE_DRAFT_NOT_SENDABLE` for a draft or a scheduled invoice and `422 INVOICE_EMAIL_NO_RECIPIENTS` with no recipients, on a single send and on a batch. Correctives: `CORRECTIVE_RECENT_DUPLICATE`, `CORRECTIVE_TOTAL_ALREADY_EXISTS`, `CORRECTIVE_ORIGINAL_NOT_FOUND`, `CORRECTIVE_ORIGINAL_DELETED`, `CORRECTIVE_ORIGINAL_IS_DRAFT`, `CORRECTIVE_ORIGINAL_REQUIRED`, `RECTIFICATION_REASON_REQUIRED` and `ORIGINAL_REFERENCE_ONLY_ON_CORRECTIVE`. An invoice with no recipient: `RECIPIENT_NOT_PROVIDED`. Fields: `FIELD_TOO_LONG`, `FIELD_OUT_OF_RANGE`, and `INVALID_IRPF` / `INVALID_SURCHARGE` on products as on invoice lines. Managed accounts: `PROVISIONING_TAX_PROFILE_REQUIRED`, `PROVISIONING_EMAIL_REQUIRED`, `PROVISIONING_INVALID_CURSOR` and `CLAIM_TOKEN_EMAIL_REQUIRED`. The VeriFactu representation: `REPRESENTATION_NOT_FOUND`, `REPRESENTATION_DOCUMENT_NOT_STORED`, `REPRESENTATION_ALREADY_ACTIVE`, `REPRESENTATION_NOT_ACTIVE` and `NIF_NOT_CONFIGURED`.
- **`SERIES_DOCUMENT_TYPE_INCOMPATIBLE` is retired.** A series that does not fit the document's type answers `422 SERIES_INCOMPATIBLE_DOC_TYPE` everywhere: when you create or edit an invoice, when you issue it, and when a recurring invoice template changes its type or series.
- **`customer_id` together with recipient data answers `422 RECIPIENT_CUSTOMER_AND_DATA_EXCLUSIVE`**, on create and on edit. Until now the other recipient fields were ignored and the invoice took the customer's data. Send one or the other.
- **A corrective with `recipient` answers `422 CORRECTIVE_RECIPIENT_NOT_ACCEPTED`** and nothing is created. A corrective always goes to the recipient of the invoice it corrects, with that invoice's data; the field used to be ignored. The one exception is correcting the recipient's data with an `R4`: see [corrective invoices and voids](/changelog/correctives-and-voids-follow-the-law).
- **`alternative_id.country_code` is required**, except for `PASSPORT` and `NOT_REGISTERED`, which take `ES` when you omit it. Any other type without it answers `422 ALTERNATIVE_ID_COUNTRY_REQUIRED`, naming the field, on a customer and on an invoice recipient. Until now an invoice recipient without it answered `400 VALIDATION_ERROR`, even for a passport, and a customer without it was judged as Spanish and answered `ALTERNATIVE_ID_SPAIN_INVALID_TYPE` or `ALTERNATIVE_ID_VAT_REQUIRES_EU_COUNTRY`.
- **An unknown `sort_by` on the invoice lists answers `400 VALIDATION_ERROR`**, naming `sort_by` and the accepted fields, as customers and products already did. Until now it was ignored and the list came back in the default order. `due_date` is a new accepted field.
- **An empty element in a list filter answers `400 VALIDATION_ERROR`** naming the parameter, on every list: `status=ISSUED,` or `status=ISSUED&status=`. It used to fail with a `500`. A list parameter sent entirely empty (`status=`) is now the same as omitting it.
- **Sending an invoice whose PDF does not exist yet answers `202`**, not an error. It happens right after issuing, and under VeriFactu while the invoice waits for the QR of its registration. The email goes out shortly after the PDF is stored (minutes, if VeriFactu or the PDF is delayed); `sent_at` in the `202` is when the request was accepted, and `invoice.email.sent` tells you when it left. If the invoice ends without a PDF, or its PDF is not stored within a day, the email is recorded as failed with its reason, and a failed email sends no webhook. The preview image answers `202` with `Retry-After` in the same case.
- **An invoice under VeriFactu that is not registered with the AEAT has no PDF.** Downloading it, its preview image, or emailing it with the PDF answers `400 INVOICE_NOT_REGISTERED_NO_PDF` at once: its registration was rejected before reaching the AEAT, or it was voided without being registered. `verifactu.error_message` says why.

## Does this affect you?

- If you create series from code, add `document_type` to the request.
- If you parse error messages or depend on their language, send `Accept-Language` explicitly.
- If your customers have both `email` and `billing_emails`, their invoices now go to `billing_emails`.
- If you relied on `initial_number` restarting every year at the same number, create the series for next year yourself.
- If you send customers from outside the EU as `NIF_IVA`, or EU VAT numbers without their country prefix, change them: use `OTHER_DOCUMENT` or `COUNTRY_ID` outside the EU, and the full number with its prefix inside it.
- If you branch on the status of `SIMPLIFIED_INVOICE_FORBIDS_IDENTIFIED_RECIPIENT`, expect `422`; better, compare `error.code`.
- If you branch on `error.code` being `BUSINESS_RULE_VIOLATION` or `VALIDATION_ERROR`, or on `SERIES_DOCUMENT_TYPE_INCOMPATIBLE`, add the new codes to those branches.
- If you send `customer_id` together with recipient fields, or a `recipient` on a corrective, remove them.
- If you send `alternative_id` without `country_code`, add it.
- If you pass `sort_by` to the invoice lists, check it is one of the accepted fields; if you build list filters by joining values with commas, make sure no element is empty.
- If you call `/send` right after issuing, handle `202`: the email is on its way, not sent yet.
- If you store invoice PDFs, keep them: an issued invoice's PDF does not change after voiding or correcting it.

## What else changed

- **Simplified invoices generated from Stripe never identify the customer.** Below the connection's simplified threshold, for a customer with a NIF but no address, or when the connection has no default standard series, the simplified invoice keeps the name, email and address of the payment but not the NIF or `alternative_id`, and it is not linked to the customer. A customer who needs an identified invoice needs a charge at or above the threshold, with full fiscal data.
- **English is the default language.** A request without `Accept-Language`, or with one that asks for none of `es`, `en` and `ca`, gets its messages in English.
- **A missing scope answers `403` first.** A key without the scope of the operation gets `403 INSUFFICIENT_SCOPE` before the body or the parameters are validated, instead of a `422` or `400` about them.
- **Invoice emails go to `billing_emails` before `email`.** Without `recipients` in the request or in the invoice's `email_config`, an invoice goes to the customer's `billing_emails`, and to `email` only when there are none. It applies to `/send`, to the automatic send on issue and to recurring invoices. A corrective with `send_automatically: true` uses the customer's addresses too.
- **One number per issuer.** Creating or editing a series that could print a number another series of the company prints answers `409 SERIES_FORMAT_OVERLAPS`. Issuing a number another invoice of the company already has answers `400 SERIES_NUMBER_COLLISION`, without issuing or using a number.
- **`initial_number` applies to the first period only.** With an `ANNUAL` or `MONTHLY` reset, every later year or month starts at 1. No number already issued changes.
- **Invoice numbers fit the AEAT.** A series whose longest number exceeds 60 characters, or would carry `"`, `'`, `<`, `>` or `=`, answers `422` when you create or edit it; an invoice number that breaks the rule at issue answers `422` without using the number.
- **VeriFactu: fewer, clearer webhooks.** `verifactu.status.updated` is sent only when the public status changes. A temporary AEAT error keeps the invoice `PENDING`, with no `error_code` or `error_message`, while BeeL. retries it. A submission refused before it reached AEAT, or one BeeL. stopped waiting for, is `REJECTED` and now also sends the webhook; its `error_message` is BeeL.'s own text.
- **Addresses: `country_code` decides the country.** `country` is accepted only as a real ISO code or the country's official name in Spanish, English or Catalan (`UK` answers `422 COUNTRY_CODE_REQUIRED`; the code is `GB`), and a `country` that contradicts `country_code` answers `422 COUNTRY_CODE_MISMATCH`. Responses always carry the code and the Spanish name derived from it.
- **Webhooks.** Turning a paused subscription back on also counts towards the 10 active subscriptions: `400 WEBHOOK_ACTIVE_SUBSCRIPTION_LIMIT_REACHED`, the code an 11th subscription now gets too. The new retry schedule is in [its own entry](/changelog/webhook-retries-span-three-days).
- **Managed accounts.** An account claimed by its holder with no NIF yet reads `CLAIMED`, not `ACTIVE`, in the account, the list and its `status` filter. Every account is born with one company, so `POST /v1/accounts` returns a `company_id` with or without a `tax_profile`.
- **Companies.** Creating a company keeps the trade name and the whole address, and answers `502 EXTERNAL_SERVICE_ERROR` when the AEAT census cannot be reached, storing nothing. A Spanish postal code without 5 digits answers `422 POSTAL_CODE_INVALID_ES`. Changing `nif`, `entity_type` or `legal_form` answers `422 IMMUTABLE_…`, and a `legal_name` change with the census down answers `200` and is checked again later.
- **Imports.** A Holded file over 5,000 contacts or 10 MB is rejected whole with `400 TOO_MANY_RECORDS` or `CSV_FILE_TOO_LARGE`, instead of being cut.
- **The invoice PDF prints the QR centred at the top of the first page**, at the size the AEAT requires, with «QR tributario:» above it and the AEAT legend below, both centred. It applies to invoices issued from now on: the PDF of an invoice already issued is not generated again.
- **Filter invoices by payment method.** The invoice lists accept `payment_method`, one value or several separated by commas (`payment_method=DIRECT_DEBIT,CARD`); `NONE` also matches invoices with no payment method stored.
- **Provisioning again keeps a valid claim link.** Resending the `external_ref` of an unclaimed account, or re-importing it, no longer replaces a claim link that is still valid: `claim_token` and `claim_url` come back `null` with `claim_link_already_issued: true`, and no email is sent. A fresh link is issued only when none is valid; to replace one on purpose, use `POST /v1/accounts/{account_id}/claim-tokens`.
- **The VeriFactu records of an invoice** list a registration refused before it reached AEAT as `REJECTED` until the invoice is sent again, when the new attempt takes its place. `error_message` is BeeL.'s own text when AEAT gave no answer, and `error_code` travels only when AEAT gave one.
- **The PDF of an issued invoice never changes.** It is generated once, with its VeriFactu QR when that applies, and served as it was delivered. Voiding the invoice or issuing a corrective for it, including a `TOTAL` one, does not change the PDF or add a watermark: the status is in `status` and `verifactu.submission_status`. In the sandbox every PDF keeps the test-invoice watermark.
- **`invoice.pdf.generated` fires once for an issued invoice** and carries `data.generation`, which numbers the stored PDF (`1` for the first). It only goes past `1` in the exceptional case that BeeL. staff regenerate the PDF to fix a rendering defect. Events recorded before the field existed do not carry it: treat a missing value as unknown, not as `1`.
- **The simplified-invoice cap is checked on every path.** A `SIMPLIFIED` invoice over 3,000 € (VAT included) answers `400 SIMPLIFIED_INVOICE_EXCEEDS_LEGAL_LIMIT` when it is created, as it always did, and now also when an edit takes it over the cap and when it is issued; an edit used to fail with a `500`. The reference said `422` for this code: the status was always `400`, and the reference now says so.
- **A recurring invoice template can change its type.** `PATCH` accepts `invoice_type`; the change is judged on the resulting template with the rules of the new type, so send the new `series_id`, and `customer_id: null` when moving to `SIMPLIFIED`, in the same call.
- **Creating a company returns the whole company.** The `201` carries every field `GET /v1/companies/{company_id}` returns, with the same values, plus `series`.
- **VeriFactu: a number AEAT already holds for another invoice.** If AEAT already has a record with an invoice's number and issue date that is not that invoice, for example one issued with the software you used before, the invoice ends `REJECTED`, with no `error_code` and an `error_message` that says the number is taken. Issue it again with a number AEAT does not hold yet.
- **Customers in bulk.** Every row error carries a `code`, the same one the single create answers or one of its own (`CUSTOMER_DUPLICATED_IN_BATCH`, `CUSTOMER_FIELD_REQUIRED`…). If the AEAT census cannot be reached, the whole request answers `502` or `503` and nothing is saved, instead of blaming the rows.
- **`POST /v1/nif/validate` answers a NIF with bad syntax with `200` and `status: INVALID`**, as its reference says, instead of an error. Its `message` comes in the language of the request.
- **Webhook deliveries carry only the documented headers**, plus `User-Agent: BeeL-Webhooks`, and whatever HTTP itself adds.
- **The daily cap on distinct recipient addresses applies per environment, and the sandbox now enforces it.** The sandbox and production each count their own addresses, and the sandbox applies its [published cap](/guides/sending-email#send-quotas), which it did not until now: a sandbox integration that emails many different addresses in a day may start getting `429`. Keep sandbox sends to a few addresses of your own.

## Endpoints

- `POST /v1/companies/{company_id}/invoices` — 422 SIMPLIFIED_INVOICE_FORBIDS_IDENTIFIED_RECIPIENT (was 400); also on PATCH, issue, bulk and recurring templates; 422 RECIPIENT_CUSTOMER_AND_DATA_EXCLUSIVE
- `POST /v1/companies/{company_id}/series` — document_type required; 409 SERIES_FORMAT_OVERLAPS
- `PATCH /v1/companies/{company_id}/series/{series_id}` — 409 SERIES_FORMAT_OVERLAPS; UNASSIGNED no longer accepted
- `POST /v1/companies/{company_id}/invoices/{invoice_id}/issue` — 400 SERIES_NUMBER_COLLISION; 422 when the number does not fit the AEAT
- `PATCH /v1/accounts/{account_id}/webhooks/{webhook_id}` — Turning a subscription back on counts towards the limit of 10
- `POST /v1/companies/{company_id}/customers` — 422 ALTERNATIVE_ID_VAT_REQUIRES_EU_COUNTRY / ALTERNATIVE_ID_VAT_INVALID_FORMAT / ALTERNATIVE_ID_COUNTRY_REQUIRED
- `GET /v1/companies/{company_id}/invoices` — New payment_method filter
- `POST /v1/companies/{company_id}/invoices/{invoice_id}/send` — 202 while the PDF does not exist yet; 400 INVOICE_DRAFT_NOT_SENDABLE (draft or scheduled) / INVOICE_NOT_REGISTERED_NO_PDF; 422 INVOICE_EMAIL_NO_RECIPIENTS
- `GET /v1/companies/{company_id}/invoices/{invoice_id}/pdf` — 400 INVOICE_NOT_REGISTERED_NO_PDF; the PDF of an issued invoice never changes
- `POST /v1/companies/{company_id}/invoices/{invoice_id}/corrective` — 422 CORRECTIVE_RECIPIENT_NOT_ACCEPTED and specific CORRECTIVE_* codes
- `GET /v1/companies/{company_id}/invoices` — Unknown sort_by and empty list elements answer 400; new sort field due_date
- `PATCH /v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}` — Accepts invoice_type; 422 SERIES_INCOMPATIBLE_DOC_TYPE

## Where to go next

- [Series and numbering](/guides/series-and-numbering)
- [Submission states](/verifactu/submission-states)
- [Sending email](/guides/sending-email#recipients)
- [Create a series](/invoice-series/createCompanySeries)
- [International customers](/verifactu/international-customers#identifying-foreign-customers)
- [Simplified vs standard](/verifactu/simplified-vs-standard#on-the-f2-path)
- [Sending before the PDF exists](/guides/sending-email#sending-before-the-pdf-exists)
- [The PDF and the QR](/verifactu/qr-and-pdf#the-pdf-and-the-qr)
- [The number is already taken at AEAT](/verifactu/handling-rejections#the-number-is-already-taken-at-aeat)

---

Full OpenAPI spec: https://docs.beel.es/api/openapi