---
title: "Generate an invoice now from a recurring template"
method: POST
path: "/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}/generate"
tags: ["CompanyRecurringInvoices"]
---

# Generate an invoice now from a recurring template

`POST /v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}/generate`

## Request

- Base URL: `https://app.beel.es/api`
- URL: `https://app.beel.es/api/v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}/generate`
- Auth: HTTP bearer

Runs the generation of this recurring template immediately, out of its schedule. It is a
fiscal act: the generated invoice consumes numbering from the series of the template and,
when the template says so, is issued and sent.

- **It brings the upcoming occurrence forward, it does not add one:** the call consumes
  the period that was pending, so the invoice is created now and `next_generation`
  advances one period. Generating manually, skipping and letting the schedule run each
  consume exactly one occurrence, so a monthly template still produces twelve invoices a
  year however you mix the three.
- **`next_generation` in the response:** the template's next date after this call
  consumed the pending occurrence, or `null` when the advance took the template past its
  `end_date` and its status is now `COMPLETED`.
- **Templates with `draft_in_advance`:** when the pending period's scheduled date is
  today or earlier, its review window has passed and the invoice is issued on the spot,
  dated today. When it is still ahead, the call creates the review draft with the
  scheduled date, and it is issued on that day.
- **An extra invoice outside the calendar:** do not use this endpoint. Create a normal
  invoice, or derive a draft from one the template already generated with
  `POST /v1/companies/{company_id}/invoices/derivations`. Either way the schedule stays
  where it was.
- **Custom fields:** the invoice copies those of the template, each with the label the
  field has now. A field archived since the template was saved is left out; it does not
  make the generation fail.

## Headers

- `Idempotency-Key` string

## Response `201`

Invoice generated successfully

- object: The envelope every successful JSON response of the BeeL. API is wrapped in. There are no bare resources in v1 and none are planned: the payload always hangs off `data`. - A **single resource** is an object in `data`. - A **collection** hangs off a named key inside `data`, together with its `pagination`, also inside `data` — `data: {invoices: [...], pagination: {...}}`. - A collection carries `pagination` unless its operation declares itself a **closed catalogue**: a fixed, bounded list with nothing to page through. The declaration is explicit in the operation; a missing `pagination` is never something to infer. - `GET /v1/accounts` pages by cursor (`data: {accounts: [...], next_cursor}`). It is a documented variant of pagination, not another envelope. Putting the array straight into `data` with `pagination` as its sibling is the shape a v2 would adopt; v1 is not being flipped to it.
  - `success` boolean, required
  - `data` object, required: The payload. An object for a single resource; an object holding the named collection (and its `pagination`) for a listing. Never a bare array at this level in v1.
    - `invoice_id` string, uuid
    - `next_generation` string, date, nullable: The template's next generation date **after** this call consumed the pending occurrence. `null` when the advance took the template past its `end_date` and its status is now `COMPLETED`: there is no next generation left.
  - `meta` ResponseMeta
    - `timestamp` string, date-time
    - `request_id` string

## Other responses

- `400`: `VALIDATION_ERROR` — the body parses but a value is not acceptable. `details` is a flat map from the offending property's name (in the contract's `snake_case`, nested paths joined with a dot, e.g. `recipient.address.postal_code`) to a message describing what is wrong with it, one entry per property. When the rejected value is one outside an enum's vocabulary, `details` instead follows `FieldDeserializationError` (`field`, `invalid_value`, `allowed_values`). Two more codes share this status for a value that passes the contract but does not fit where it is stored: `VALUE_TOO_LONG` (a text longer than its column holds) and `VALUE_OUT_OF_RANGE` (a number outside what its column holds). Nothing was written. Other `error.code` values with this status: - `EXEMPTION_INCOMPATIBLE_WITH_REGIME` — the line's `exemption_reason` cannot be declared under its `regime_key` (e.g. E2/E3 with key `01`); change the key or the reason. - `EXEMPTION_REGIME_NOT_SUPPORTED_IN_VERIFACTU` — `REGIMEN_ART_*` reasons are special regimes, not exemptions; declare the matching `regime_key` instead of an exemption reason. - `ISP_INCOMPATIBLE_WITH_SURCHARGE` — a reverse-charge line (`ISP_*`) cannot carry an equivalence surcharge; remove the surcharge or the reverse-charge reason. - `LINE_TOTAL_INCONSISTENT` — the computed line amounts do not add up to its total within 1 cent; this is an internal safeguard, report it with the request id. - `OSS_REGIME_INCOMPATIBLE_WITH_ISP` — regime key `17` (OSS/IOSS) cannot be combined with a reverse-charge `exemption_reason`; choose one. - `RECURRING_NOT_ACTIVE` — the template is not `ACTIVE`, so it cannot generate, skip or preview. `error.details.current_status` says its state; resume it first if it is `PAUSED`.
- `401`: Missing or invalid authentication. Like every other error, `message`/`detail` is localized according to `Accept-Language` (`es`, `en`, `ca`); defaults to English when the header is missing or asks for none of those.
- `403`: Your account does not own or manage this company, or does not hold the required access over it. A NIF that does not exist answers the same way. That case answers `error.code` `ACTIVE_COMPANY_NOT_ACCESSIBLE`.
- `404`: The resource addressed by the path does not exist, or is not one this credential can see — the two are answered identically, so existence is never disclosed. `error.code` names the kind of resource that was missing, so a client can tell which of several ids in a path failed to resolve: - `INVOICE_NOT_FOUND` — the `{invoice_id}` (invoices, proformas and their sub-resources). - `RECURRING_NOT_FOUND` — the `{recurring_invoice_id}`. - `CLIENT_NOT_FOUND` — the `{customer_id}`. - `INVOICE_CLIENT_NOT_FOUND` — the `customer_id` referenced by an invoice body does not resolve to a customer of the issuing company. - `PRODUCT_NOT_FOUND` — the `{product_id}`. - `SERIES_NOT_FOUND` — the `{series_id}`. - `WEBHOOK_SUBSCRIPTION_NOT_FOUND`, `DELIVERY_LOG_NOT_FOUND` — the `{webhook_id}` and the `{delivery_id}`. - `PROFILE_NOT_FOUND` — the credential's account has no company profile yet: its holder has not completed onboarding, so there is no issuer to act as. - `NOT_FOUND` — the generic fallback, for the few resources that carry no code of their own. Some resources declare a more specific `404` response of their own (`CONNECTION_NOT_FOUND`, `MEMBER_NOT_FOUND`, `GRANT_NOT_FOUND`, `INVITATION_NOT_FOUND`, `REQUEST_LOG_NOT_FOUND`); it is documented on the operation. A `404` with `ENDPOINT_NOT_FOUND` is a different answer: the **path itself** does not exist in this API (a typo in the route, or a resource that was never here). It says nothing about any resource. When the path exists but not with that method, the answer is `405`, not `404`.
- `409`: The request is well formed but collides with the state that is already there. Three families, told apart by `error.code`: - **Uniqueness** — something with that identity already exists (`CLIENT_DUPLICATE`, `PRODUCT_DUPLICATE`, `SERIES_CODE_DUPLICATED`, `NIF_ALREADY_REGISTERED`, `MEMBER_ALREADY_IN_ACCOUNT`, `INVOICE_DUPLICATE_EXTERNAL_REFERENCE`). - **Lifecycle** — the transition does not apply from where the resource is (`INVOICE_ALREADY_VOIDED`, `PROFORMA_ALREADY_CONVERTED`, `CLIENT_HAS_INVOICES`, `RECURRING_ALREADY_ENDED`, `CUSTOM_FIELD_ARCHIVED` — the custom field is archived and cannot be assigned, `RECURRING_OCCURRENCE_ALREADY_CONSUMED` — the occurrence the recurring template points at has already been billed; read its history instead of retrying). Read the resource before retrying: the state you assumed is not its state. - **Concurrency and idempotency** — another write got there first (`CONCURRENT_MODIFICATION`), or the `Idempotency-Key` you sent is still in flight (`IDEMPOTENCY_KEY_PROCESSING`, retry after a moment) or was already used for a different body (`IDEMPOTENCY_KEY_MISMATCH`, use a new key). `CONFLICT` is the generic fallback of the uniqueness family, when the uniqueness that was violated has no code of its own.
- `422`: The template cannot generate right now, or the company/NIF is not ready to issue in this environment (`error.code` `EMISSION_NOT_READY`). When the template's `start_date` is still in the future, `error.code` is `RECURRING_NOT_STARTED`: there is no occurrence to bring forward yet, nothing is created and `next_generation` does not move. To bill before that date, create a normal invoice. The fiscal rules on the lines are checked again here and answer `422` with their own `error.code`: `SIMPLIFICADA_FORBIDS_ISP`, `SIMPLIFICADA_FORBIDS_SURCHARGE` and `SIMPLIFICADA_FORBIDS_CROSS_BORDER` (a `SIMPLIFIED` invoice cannot carry reverse charge, an equivalence surcharge or an operation of art. 4.4 RD 1619/2012), `EXEMPTION_REQUIRES_RECIPIENT_ID_TYPE` (the recipient lacks the identifier type the `exemption_reason` needs, for example after the customer lost its `NIF_IVA`), `EXEMPTION_NOT_FOR_ISSUED_INVOICE` (an exemption no longer accepted on a new invoice), `REGIME_REQUIRES_INCOMPATIBLE_EXEMPTION` (a `regime_key` that requires an exemption the line does not carry) and `VAT_RATE_NOT_ACCEPTED_ON_DATE` (a VAT rate AEAT does not accept on the operation date, whose message names the dates that rate is accepted). Other `error.code` values with this status: - `EXEMPT_ZERO_RATE_REQUIRES_REASON` — a 0 % IVA or IPSI line is the exemption sentinel and needs an `exemption_reason`; add one or use a real rate. - `INVALID_IRPF` — the `irpf_rate` is not a withholding rate in force (see `IrpfPercentage`); send one of the published rates. - `INVALID_IVA_SURCHARGE_PAIR` — the equivalence surcharge does not match the line's VAT rate (21↔5.2, 10↔1.4, 5↔0.62, 4↔0.5); fix either rate. - `INVALID_SURCHARGE` — the `equivalence_surcharge_rate` is not an equivalence surcharge rate (see `EquivalenceSurchargePercentage`); send one of the published values. - `IRPF_RATE_NOT_FOR_CORPORATE_ISSUER` — the issuer is a company (corporate income tax), which can only withhold 0, 19 or 24 %; use one of those. - `IRPF_RATE_ONLY_FOR_CORPORATE_ISSUER` — the rate (e.g. 9.5 % Ceuta/Melilla) only applies to corporate issuers; an individual issuer must use a personal-income-tax rate. - `RECIPIENT_ID_REQUIRED` — a standard invoice needs an identified recipient: a `customer_id`, or inline data with `nif` or `alternative_id`. - `REGIME_KEY_CLASSIFICATION_NOT_ACCEPTED` — AEAT does not accept that `exemption_reason` (or its absence) with the line's `regime_key`; the message lists the reasons it admits. - `REGIME_KEY_NOT_SUPPORTED` — BeeL. cannot declare that `regime_key` to AEAT (e.g. `06`, `14`); use another key. - `REGIME_KEY_REQUIRES_RECIPIENT_NIF` — regime key `10` (collections on behalf of third parties) requires a recipient identified with a Spanish NIF. - `REGIME_KEY_REQUIRES_STANDARD_INVOICE` — the line's `regime_key` is only accepted on a standard (F1) invoice; change the invoice type or the key. - `REGIME_KEY_REQUIRES_VAT_RATE` — the line's `regime_key` only admits one VAT rate (named in the message); use that rate or an exemption reason. - `REVERSE_CHARGE_CASE_NOT_SUPPORTED` — that reverse-charge case (e.g. `ISP_ART_84_2_G`, which needs a special series) is not supported; issue it outside BeeL. or use another reason. - `SIMPLIFICADA_FORBIDS_IRPF` — a simplified invoice cannot carry IRPF withholding; remove `irpf_rate` or issue a standard invoice. - `SURCHARGE_RATE_NOT_ACCEPTED_ON_DATE` — AEAT does not accept that surcharge rate on the operation date (or issue date if none); send the right `operation_date` or rate. - `SURCHARGE_REQUIRES_REGIME` — an equivalence surcharge was sent with a `regime_key` other than `01`/`18` (e.g. `02`, `03`, `17`); only regime `18` admits it.
- `429`: Rate limit exceeded. `RATE_LIMIT_EXCEEDED` when the request rate of your credential is over its limit; `TOO_MANY_REQUESTS` when an email the operation sends is held back because too many went out to that recipient in a short time. Either way, retry after the `Retry-After` seconds. `QUOTA_EXCEEDED` is the other `429`: the operation would go over a quota of your plan for the current period (issued invoices, for instance). Retrying does not help until the quota resets or the plan changes. `error.details` carries `feature_code`, `current_usage`, `quota_limit` and `reset_date`, and `RateLimit-Reset` the seconds until the reset when it is known.
- `500`: Internal server error
- `default`: Any status code the operation does not list above. Every operation declares it, so a generated client always has a branch to fall into and never loses the cause of a failure it did not anticipate. This is where the transport-level answers land — `405`, `406`, `415` and `429` — together with any status a future version of the API starts returning. All of them carry the same error envelope as the codes listed explicitly, so `error.code` is what tells them apart: switching on the status code alone is not enough. See «Transport-level errors» in the API description for when each one is produced. A `402` carrying `SUBSCRIPTION_REQUIRED` lands here when the account has no active subscription. `error.details` says why and what to do: `current_status` (absent if it never had one), `required_permission` and `action`. A `503` carrying `SERVICE_UNAVAILABLE` lands here too, with a `Retry-After` header: a dependency of BeeL itself (the database, the email provider) was momentarily unavailable and nothing was done. Retry after those seconds. A `502` carrying `EXTERNAL_SERVICE_ERROR` also lands here: an outbound integration the operation depends on failed or did not answer in time. It is a transient condition — retry with the same `Idempotency-Key` where the operation accepts one. One exception to the envelope: a failure of the network edge that never reaches the application (`502`, `503`, `504`, `524`) is generated by Cloudflare and its body is not BeeL's — it may not even be JSON. Treat those as "no answer", and retry.

---

[API](https://skmtc.dev/beel/apis/beel-public-api.md) · [All operations](https://skmtc.dev/beel/apis/beel-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/beel/apis/beel-public-api/revisions/ffbc0ae31f79?raw)
