Recurring templates: quarterly, yearly, and an invoice cap
Templates gain quarterly and yearly cadences, an end after max_invoices, a completion reason, draft_in_advance, and the amount of the next invoice on every row.
Recurring templates stop being monthly-only, stop being open-ended-or-dated-only, and start telling you what they are going to charge.
Everything here is additive: a template you create today the way you created it yesterday behaves identically.
What else changed
frequencyacceptsMONTHLY,QUARTERLYandYEARLY— every 1, 3 or 12 months, on the sameday_of_monthanchor. Omitted,MONTHLYapplies. The cadence governs the step from the first invoice onwards, not where the first one lands: a yearly template starting 15 February withday_of_month10 first invoices on 10 March, then every 10 March — it does not wait a year.max_invoicesends the recurrence by number (2 to 600). It is the total agreed, not what is left: remaining ismax_invoices - generated_invoices, and there is deliberately no second field for it. What counts against it is invoices generated, so a skip does not spend cap and a generate-now does. A recurrence ends in exactly one way — open-ended, onend_date, or aftermax_invoices.completionsays why a template ended:USER,END_DATE_REACHEDorMAX_INVOICES_REACHED, with the instant inat.statuskeeps its three values andCOMPLETEDstays a single terminal status, so nothing breaks an exhaustiveswitch— new causes land inreason, so treat it as an open set. Templates completed before this was recorded carry nocompletion, because that cause is not known and is not invented.draft_in_advancereplacespreview_days. The review window is no longer a number you pick: it is fixed at 5 days.preview_daysis deprecated and still accepted — any value above0meansdraft_in_advance: true,0meansfalse, and if both arrivedraft_in_advancewins. Either way the invoice is emitted on the scheduled day; what changes is whether there is a draft to look at first.amounton every template — what the customer will be asked to transfer on the next invoice it generates: base + VAT + equivalence surcharge − withholding + disbursements. The same number the next occurrence publishes astotal_to_pay, to the cent. It is computed on the fly, so it always matches the lines the template carries right now — and for that reason it is not sortable or filterable.nullwhen the lines cannot be priced.day_of_month: 31is how you ask for the last day of the month. A month without that day falls back to its last one — 28 February, 30 April — and the adjustment never sticks: every generation is recalculated from the value you sent, so the schedule does not drift.- Three more fields on the response:
payment_iban,payment_swiftandpayment_term_daysof the template's own payment method, andrecipient_alternative_idfor a recipient identified by something other than a Spanish NIF (mutually exclusive withrecipient_nif). start_dateis a no-op when you resend the value it already has, instead of being rejected once the template has issued — so a read-modify-write cycle no longer has to strip the field out of the body.
Endpoints
- POST/v1/companies/{company_id}/recurring-invoicesfrequency QUARTERLY|YEARLY, max_invoices, draft_in_advance
- GET/v1/companies/{company_id}/recurring-invoicesEvery row carries amount, completion and the payment detail
Where to go next
An OSS line keeps the destination country's VAT
Our OSS examples set `percentage: 0`, which drops the destination VAT from the breakdown. The API never required it. Check your `regime_key: "17"` lines.
Recurring writes reject what they used to swallow
Payment detail without a method, an inactive series, a window with no occurrence and a blank name are now rejected instead of silently discarded.