UpdateRecurringInvoiceRequest
Request to **replace** a recurring invoice (`PUT`). Send the template complete: `end_date`, `payment_method` (with its `payment_iban`, `payment_swift` and `payment_term_days`), `notes` and `email_configuration` are cleared when you leave them out. To change a few fields and keep the rest untouched, use `PATCH /v1/recurring-invoices/{recurring_invoice_id}`. `custom_fields` is not part of this request: a replacement keeps the template's custom fields as they are. Change them with `PATCH /v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}`.
Properties
| Name | Type | Description |
|---|---|---|
| name | string | |
| frequency | string | Generation cadence: `MONTHLY` every month, `QUARTERLY` every 3 months, `YEARLY` every 12 months. Omitted, the current one is kept — it is never reset to `MONTHLY`. **Changing it reschedules the templa |
| day_of_month | integer | Day of the month the invoices are issued. A month that does not have that day falls back to its last day: a template on `31` issues on 28 February (29 in a leap year) and on 30 April. So `31` is how y |
| start_date | string | Date the subscription started. A past date is accepted and stored as sent — useful when migrating subscriptions from another system — but it never anchors generation in the past. `next_generation` bec |
| draft_in_advance | boolean | Whether the template prepares a draft for review before emitting. The window is fixed at 5 days and both options emit on the scheduled day. Generating manually a period whose scheduled date is today o |
| preview_days | integer | **Deprecated.** Superseded by `draft_in_advance`, because the review window is no longer a number you pick: it is fixed at 5 days. Still accepted so nothing breaks — any value greater than `0` means t |
| end_date | stringnull | |
| max_invoices | integernull | Total number of invoices this template will generate before ending on its own, between 2 and 600. Like `end_date`, it is **cleared when you leave it out**: this is a replacement. A recurrence ends in |
| series_id | string | |
| invoice_type | object | Type of the invoices the template generates. Omitted, the current type is kept. A change is judged on the resulting template, with the rules of the new type: its series must accept it (`SERIES_INCOMPA |
| customer_id | stringnull | Recipient of the generated invoices. Send `null` to leave the template without a recipient; omit it to keep the current one. |
| lines | arraynull | Template lines, replaced as a whole. Omit them (or send `null`) to keep the current ones — a template with no lines invoices nothing, so an empty array is rejected. |
| payment_method | object | Payment method. `payment_iban`, `payment_swift` and `payment_term_days` are detail of this method, not standalone fields: sending any of them without a `payment_method` that is present, non-null and d |
| payment_iban | stringnull | |
| payment_swift | stringnull | |
| payment_term_days | integernull | |
| notes | stringnull | |
| send_automatically | boolean | |
| email_configuration | object |
JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://artifacts.apis.io/beel-es/json-schema/beel-es-update-recurring-invoice-request-schema.json",
"title": "UpdateRecurringInvoiceRequest",
"description": "Request to **replace** a recurring invoice (`PUT`).\n\nSend the template complete: `end_date`, `payment_method` (with its `payment_iban`,\n`payment_swift` and `payment_term_days`), `notes` and `email_configuration` are\ncleared when you leave them out. To change a few fields and keep the rest\nuntouched, use `PATCH /v1/recurring-invoices/{recurring_invoice_id}`.\n\n`custom_fields` is not part of this request: a replacement keeps the template's custom\nfields as they are. Change them with\n`PATCH /v1/companies/{company_id}/recurring-invoices/{recurring_invoice_id}`.\n",
"x-generated": "2026-10-30",
"x-method": "derived",
"x-generator": "derive-json-schema.py",
"x-source": "openapi/beel-es-openapi.json#/components/schemas/UpdateRecurringInvoiceRequest",
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1,
"maxLength": 255,
"pattern": "^\\S.*$"
},
"frequency": {
"type": "string",
"enum": [
"MONTHLY",
"QUARTERLY",
"YEARLY"
],
"description": "Generation cadence: `MONTHLY` every month, `QUARTERLY` every 3 months, `YEARLY` every 12 months. Omitted, the current one is kept — it is\nnever reset to `MONTHLY`.\n\n**Changing it reschedules the template.** The next generation is recalculated on the new\ngrid — the `day_of_month` dates anchored at `start_date`, one every cadence — so it can\nland months later than the one you saw before the call. **If the template has already\nissued invoices, the landing respects that**: it is never a period that was already\nbilled, and never before today either — the first point of the new grid strictly after\nthe last invoiced one. It also **discards a pending skip**: the skipped period only\nexisted as a point of the old grid, and that grid is gone. Send the same cadence and\nnothing is rescheduled.\n"
},
"day_of_month": {
"type": "integer",
"minimum": 1,
"maximum": 31,
"description": "Day of the month the invoices are issued. A month that does not have that day falls\nback to its last day: a template on `31` issues on 28 February (29 in a leap year)\nand on 30 April. So `31` is how you ask for the last day of the month it generates\nin — there is no separate flag for it, and the accepted range stays 1–31.\n\nThe adjustment does not stick and the schedule does not drift: every generation is\nrecalculated from the `day_of_month` you sent, never from the date it was adjusted\nto (31 Jan → 28 Feb → 31 Mar).\n"
},
"start_date": {
"type": "string",
"format": "date",
"description": "Date the subscription started. A past date is accepted and stored as sent — useful\nwhen migrating subscriptions from another system — but it never anchors generation\nin the past. `next_generation` becomes the first date of the template's own calendar\non or after today (today included): the grid of `day_of_month` dates anchored at\n`start_date`, one every `frequency`. On a quarterly or yearly template that can be\nmonths from now, not this month. Invoices are never back-dated, so the missed periods\nare not generated. If today's period was already invoiced in the system you are\nmigrating from, send a `start_date` of tomorrow (or of the next period) so it is not\ninvoiced twice.\n\nOnce the template has issued, only a *different* date is rejected with a 422\n`RECURRING_START_DATE_NOT_EDITABLE`. Resending the value it already has is a no-op,\nso this request can keep sending the template complete, as it asks above.\n"
},
"draft_in_advance": {
"type": "boolean",
"description": "Whether the template prepares a draft for review before emitting. The window is fixed at\n5 days and both options emit on the scheduled day. Generating manually a period whose\nscheduled date is today or earlier emits it on the spot. Omitted, the current value is\nkept.\n"
},
"preview_days": {
"type": "integer",
"minimum": 0,
"maximum": 30,
"deprecated": true,
"description": "**Deprecated.** Superseded by `draft_in_advance`, because the review window is no longer\na number you pick: it is fixed at 5 days. Still accepted so nothing breaks — any value\ngreater than `0` means the same as `draft_in_advance: true`, and `0` the same as `false`.\nWhen both are sent, `draft_in_advance` wins. It will be removed in a future version.\n"
},
"end_date": {
"type": [
"string",
"null"
],
"format": "date"
},
"max_invoices": {
"type": [
"integer",
"null"
],
"description": "Total number of invoices this template will generate before ending on its own, between\n2 and 600. Like `end_date`, it is **cleared when you leave it out**: this is a replacement.\n\nA recurrence ends in ONE way: open-ended, on `end_date`, or after `max_invoices`. Sending\nboth with a value is rejected with `RECURRING_END_MODE_CONFLICT`. The range is not enforced\nby this schema on purpose, so the rejection carries its own code and its own message: below\n2 you do not want a recurrence but a scheduled invoice (`PUT /v1/companies/{company_id}/invoices/{invoice_id}/schedule`).\n\nLowering it below the invoices already generated is rejected: issued invoices are fiscal\nfacts and are not undone by moving the cap. Setting it exactly to the number already\ngenerated is accepted and ends the template in that same call.\n"
},
"series_id": {
"type": "string",
"format": "uuid"
},
"invoice_type": {
"allOf": [
{
"$ref": "#/$defs/RecurringInvoiceType"
}
],
"description": "Type of the invoices the template generates. Omitted, the current type is kept.\nA change is judged on the resulting template, with the rules of the new type: its series\nmust accept it (`SERIES_INCOMPATIBLE_DOC_TYPE` otherwise), a `SIMPLIFIED` template\ncannot keep an identified recipient (`SIMPLIFIED_INVOICE_FORBIDS_IDENTIFIED_RECIPIENT`)\nnor lines a simplified invoice does not admit. Send the new `series_id`, and\n`customer_id: null` when moving to `SIMPLIFIED`, in the same call.\n"
},
"customer_id": {
"type": [
"string",
"null"
],
"format": "uuid",
"description": "Recipient of the generated invoices. Send `null` to leave the template without\na recipient; omit it to keep the current one.\n"
},
"lines": {
"type": [
"array",
"null"
],
"minItems": 1,
"items": {
"$ref": "#/$defs/RecurringLineRequest"
},
"description": "Template lines, replaced as a whole. Omit them (or send `null`) to keep the\ncurrent ones — a template with no lines invoices nothing, so an empty array is\nrejected.\n"
},
"payment_method": {
"allOf": [
{
"$ref": "#/$defs/PaymentMethod"
}
],
"nullable": true,
"description": "Payment method. `payment_iban`, `payment_swift` and `payment_term_days` are\ndetail of this method, not standalone fields: sending any of them without a\n`payment_method` that is present, non-null and different from `NONE` is\nrejected with `422` (`PAYMENT_DETAILS_REQUIRE_METHOD`).\n"
},
"payment_iban": {
"type": [
"string",
"null"
]
},
"payment_swift": {
"type": [
"string",
"null"
]
},
"payment_term_days": {
"type": [
"integer",
"null"
]
},
"notes": {
"type": [
"string",
"null"
]
},
"send_automatically": {
"type": "boolean"
},
"email_configuration": {
"$ref": "#/$defs/RecurringEmailConfigRequest"
}
},
"$defs": {
"Email": {
"type": "string",
"format": "email",
"minLength": 5,
"maxLength": 255,
"description": "Email address (minimum valid email is 5 chars, e.g. a@b.co)"
},
"ExemptionReason": {
"type": "string",
"enum": [
"EXENTA_ART_20",
"EXENTA_ART_21",
"EXENTA_ART_22",
"EXENTA_ART_24",
"EXENTA_ART_25",
"EXENTA_ART_26",
"EXENTA_ART_140",
"NO_SUJETA_ART_7_9",
"NO_SUJETA_LOCALIZACION",
"ISP_ART_84_2_A",
"ISP_ART_84_2_B",
"ISP_ART_84_2_C",
"ISP_ART_84_2_D",
"ISP_ART_84_2_E",
"ISP_ART_84_2_F",
"ISP_ART_84_2_G",
"REGIMEN_ART_129",
"REGIMEN_ART_135",
"REGIMEN_ART_141",
"REGIMEN_ART_154",
"REGIMEN_ART_163_DECIES",
"OTRO"
],
"description": "Tax exemption reason code per the Spanish VAT Law (Ley 37/1992, LIVA), with the\nVeriFactu code each one is reported as.\n\n- `EXENTA_ART_20`: exempt, art. 20 (domestic operations such as medical, educational,\n cultural and financial services, or housing rentals). E1.\n- `EXENTA_ART_21`: exempt, art. 21 (exports of goods). E2.\n- `EXENTA_ART_22`: exempt, art. 22 (operations treated as exports). E3.\n- `EXENTA_ART_24`: exempt, art. 24 (free zones, warehouses and customs regimes). E4.\n- `EXENTA_ART_25`: exempt, art. 25 (intra-community supplies of goods). E5.\n- `EXENTA_ART_26`: exempt, art. 26 (intra-community acquisitions of goods). It exempts the\n buyer's acquisition, not a supply the seller invoices, so an invoice line that carries it\n is rejected with `EXEMPTION_NOT_FOR_ISSUED_INVOICE`; a supply to another Member State is\n `EXENTA_ART_25`.\n- `NO_SUJETA_ART_7_9`: not subject under art. 7 (such as the transfer of a business as\n a going concern, art. 7.1º). N1.\n- `NO_SUJETA_LOCALIZACION`: not subject by the place-of-supply rules (intra-community\n or non-EU services, arts. 69 and 70). N2.\n- `ISP_ART_84_2_A` … `ISP_ART_84_2_F`: reverse charge (the invoice states «inversión del\n sujeto pasivo»), art. 84.Uno.2.º letters a) (supplier not established in Spain), b) (unwrought\n or semi-finished gold), c) (scrap, waste and recovery materials, plastic, paper, cardboard, glass and textile waste, and semi-finished non-ferrous metal products), d) (greenhouse gas emission\n allowances), e) (certain real estate supplies: in insolvency proceedings, with the exemption\n waived, or enforcing a security) and f) (construction or renovation works). S2.\n- `ISP_ART_84_2_G`: reverse charge of letter g) (silver, platinum, palladium, mobile phones,\n consoles, laptops and tablets). The law requires these supplies to be invoiced in a special\n series, so an invoice line that carries it is rejected with\n `REVERSE_CHARGE_CASE_NOT_SUPPORTED`.\n- `EXENTA_ART_140`: investment gold exemption, art. 140 bis (usually with `regime_key`\n `04`). E6.\n- `REGIMEN_ART_129` (agriculture,\n livestock and fishing, arts. 124 to 134 bis), `REGIMEN_ART_135` (second-hand goods,\n art and antiques), `REGIMEN_ART_141` (travel agencies), `REGIMEN_ART_154` (equivalence\n surcharge) and `REGIMEN_ART_163_DECIES` (cash basis, arts. 163 decies to 163\n sexiesdecies): operations of special regimes, which VeriFactu identifies by the regime\n key rather than by an exemption code. An\n invoice line that carries one is rejected with `EXEMPTION_REGIME_NOT_SUPPORTED_IN_VERIFACTU`;\n declare the regime with `regime_key` instead.\n- `OTRO`: any other provision. Requires the text in `exemption_reason_text`. E6.\n"
},
"PaymentMethod": {
"type": "string",
"description": "Payment method shown on invoices and recurring invoices.\n\n- `NONE`: no payment information is shown.\n- `BANK_TRANSFER`: bank transfer to the IBAN of the payment details; the only method\n that requires an IBAN.\n- `CARD`: card payment.\n- `CASH`: cash payment.\n- `CHECK`: payment by cheque.\n- `DIRECT_DEBIT`: direct debit from the customer's bank account.\n- `BIZUM`: payment through Bizum.\n- `OTHER`: any other method.\n",
"enum": [
"NONE",
"BANK_TRANSFER",
"CARD",
"CASH",
"CHECK",
"DIRECT_DEBIT",
"BIZUM",
"OTHER"
]
},
"RecurringEmailConfigRequest": {
"type": [
"object",
"null"
],
"properties": {
"recipients": {
"type": "array",
"items": {
"$ref": "#/$defs/Email"
}
},
"cc": {
"type": "array",
"items": {
"$ref": "#/$defs/Email"
}
},
"subject": {
"type": [
"string",
"null"
]
},
"message": {
"type": [
"string",
"null"
]
}
}
},
"RecurringInvoiceType": {
"type": "string",
"enum": [
"STANDARD",
"SIMPLIFIED"
],
"description": "Type of the invoices a recurring template generates: `STANDARD` for an identified recipient,\n`SIMPLIFIED` for a recipient that is not identified.\n"
},
"RecurringLineRequest": {
"type": "object",
"description": "Recurring-invoice line. Unlike invoice lines (which nest tax data under a `main_tax` object),\nrecurring lines use flat tax fields: `vat_rate`, `tax_type`, `regime_key`,\n`equivalence_surcharge_rate` and `irpf_rate`. Do not send a `main_tax` object here.\n\n**Line amount**: send **exactly one** of `unit_price`, `total_excluding_tax` or\n`total_including_tax` — same contract as an invoice line. Sending none, or more than\none, is rejected with `LINE_UNIT_PRICE_XOR_DECLARED_TOTAL`; a declared total together\nwith an explicit `discount_percentage` is rejected with\n`LINE_DECLARED_TOTAL_FORBIDS_DISCOUNT` (the discount, if any, already lives inside\nthe total).\n\nThe mode is what the template promises, and it is re-applied on **every** generation:\na line declared as `total_including_tax: 1.00` over 300 units invoices 1,00 € on every\ngeneration, not 300 × 0,0033 = 0,99 €. Because `PATCH` replaces the lines as a whole,\nresending a line with a different amount field switches its mode.\n",
"required": [
"description",
"quantity",
"vat_rate"
],
"properties": {
"description": {
"type": "string",
"maxLength": 2000
},
"quantity": {
"type": "number",
"minimum": 0.01,
"multipleOf": 0.0001
},
"unit": {
"type": "string",
"maxLength": 20
},
"unit_price": {
"type": "number",
"minimum": 0,
"maximum": 999999.9999,
"description": "Unit price before taxes. Supports up to 4 decimal places for micro-pricing\n(e.g. €0.0897/unit for labels, packaging); the generated invoices always round\ntheir amounts to 2 decimals. Mutually exclusive with `total_excluding_tax` and\n`total_including_tax`.\n\nThe upper bound is the same one the invoice line declares, and so is the\nacceptance of `0` (a discount granted before or simultaneously with the sale,\ne.g. a free introductory month). A price outside the range is rejected with\n`422 VALIDATION_ERROR` and the offending field in `details`.\n\nNegative prices are NOT accepted, unlike an invoice line of a corrective invoice:\na recurring template only issues `STANDARD` or `SIMPLIFIED` invoices, and a\ncorrective is created through its own endpoint over an already issued invoice —\nnever generated by a template.\n"
},
"total_excluding_tax": {
"type": "number",
"minimum": 0,
"maximum": 99999999.99,
"description": "Declared line total excluding taxes: this amount IS the taxable base, exactly,\nwith no recalculation. The stored `unit_price` becomes derived and informational\n(`total / quantity`, 4 decimals). Mutually exclusive with `unit_price` and\n`total_including_tax`.\n\nNegative totals are NOT accepted, for the same reason `unit_price` does not accept\nnegative prices: a template only issues `STANDARD` or `SIMPLIFIED` invoices, and only\na corrective invoice — created through its own endpoint over an already issued\ninvoice — carries a negative amount. A total outside the range is rejected with\n`422 VALIDATION_ERROR` and the offending field in `details`.\n\nThe upper bound is the same one `POST /v1/invoices` declares for a line total: a\ntemplate is a promise to issue an invoice, and it cannot accept less than the\ninvoice it will generate does. The derived `unit_price` (`total / quantity`) can\nstill exceed the `maximum` this contract accepts for `unit_price` itself — what\nactually bounds it then is the domain's price ceiling, not this field's contract.\n"
},
"total_including_tax": {
"type": "number",
"minimum": 0,
"maximum": 99999999.99,
"description": "Declared line total including taxes — what the customer pays. The engine works\nthe breakdown backwards so that taxable base + VAT + equivalence surcharge equals\nthis amount exactly on every generated invoice. IRPF withholding is never part of\nthe decomposition: it is a retention, not a price. Mutually exclusive with\n`unit_price` and `total_excluding_tax`.\n\nNegative totals are NOT accepted, same as `total_excluding_tax`.\n\nThe upper bound is the same one `POST /v1/invoices` declares for a line total, for\nthe same reason: the template cannot promise more than the invoice it generates\ncould ever accept. The derived `unit_price` (`total / quantity`) can still exceed\nthe `maximum` this contract accepts for `unit_price` itself — what actually bounds\nit then is the domain's price ceiling, not this field's contract.\n"
},
"discount_percentage": {
"type": "number",
"minimum": 0,
"maximum": 100
},
"tax_type": {
"type": "string",
"description": "Tax type. Omitted, `IVA` applies."
},
"vat_rate": {
"type": "number"
},
"regime_key": {
"type": "string",
"description": "VeriFactu regime key. Omitted, `01` (general regime) applies."
},
"equivalence_surcharge_rate": {
"type": [
"number",
"null"
]
},
"irpf_rate": {
"type": [
"number",
"null"
]
},
"exemption_reason": {
"$ref": "#/$defs/ExemptionReason",
"nullable": true
},
"exemption_reason_text": {
"type": [
"string",
"null"
],
"maxLength": 500,
"description": "Custom exemption text. Only used when `exemption_reason` is `OTRO`.\n\nSame shape as an invoice line: the template declares WHY the operation carries no tax,\nand every invoice it generates inherits it. A 0% line without a reason is rejected on\nwrite — VeriFactu does not accept an exempt line with no explicit motive.\n"
}
}
}
}
}
Work with this as data
Every JSON Schema here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for schemas
4 MCP tools reach this
find_json_schemasBrowse and filter every JSON Schema in the catalog.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.
Call it yourself
curl for this page
curl "https://apis.io/api/v1/json-schemas/beel-es-update-recurring-invoice-request"
curl "https://apis.io/api/v1/json-schemas?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.