Newchaining_hash leaves the documentation
BeeL
Get StartedMulti-NIFVeriFactuStripeAPI ReferenceChangelog

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.


ChangelogBreaking

Five ways a write to a recurring template used to answer 200/201 and quietly do something other than what you asked. They are now named rejections, each with its own code.

If a request of yours is in this list, it was never doing what you thought — but it did answer success, so check before the next deploy.

What breaks

  • The trap: PATCH {"payment_iban": "ES…"} with no payment_method. It answered 200 and changed nothing. It now answers 422 PAYMENT_DETAILS_REQUIRE_METHOD. payment_iban, payment_swift and payment_term_days are detail of payment_method, not standalone fields: they are only accepted alongside a method that is present, non-null and not NONE. Clearing the payment method is unchanged — send payment_method: null without mentioning the other three and they are released, as always.
  • A template numbering against an inactive series is rejected with SERIES_INACTIVE, and nothing is written. It is judged on the resulting template, so an update that leaves an inactive series in place is rejected too, even when the body does not mention the series.
  • A frequency and an end_date that are impossible together — no occurrence at all between start_date and end_date, the everyday case for a yearly template created with the year under way — are rejected with RECURRING_NO_OCCURRENCE_IN_WINDOW, hanging off end_date, the field you can move. It is not RECURRING_END_DATE_BEFORE_START: that one says the next generation falls past the end, this one says there is no first invoice and never will be.
  • A line priced by declared total whose derived unit price does not fit is rejected with LINE_UNIT_PRICE_OUT_OF_RANGE, whose details name the offending line and carry the limit and the derived quotient as JSON numbers — so you do not have to parse the message.
  • A blank name is rejected as empty rather than as "characters not allowed", on all five write requests.
  • A line whose exemption requires a specific recipient identifier (today EXENTA_ART_25 needs NIF_IVA) is rejected with EXEMPTION_REQUIRES_RECIPIENT_ID_TYPE when the referenced customer does not carry it — the same rejection invoice creation already gave, brought forward to the template instead of every generated invoice bouncing at the AEAT.
  • RECURRING_ALREADY_ENDED answers 409, not 422 — since 8 September, and in every place it appears: writes, generate and preview. A completed template rejects every write, including a PATCH that only touches notes. If you branch on the status code, that code moved; if you branch on error.code, nothing changed.

Does this affect you?

  • Grep your client for a write to a recurring template that sends payment_iban, payment_swift or payment_term_days. If payment_method is not in the same body, that call now answers 422.
  • Replay a template creation against an inactive series, and one with a yearly cadence inside a window shorter than a year: both used to succeed.
  • Check whether you treat RECURRING_ALREADY_ENDED as a 422.

What else changed

  • None of this changes a read. Templates already stored are untouched — what changes is which writes are accepted.
  • Block replacement is unchanged. Changing payment_method without resending the detail still releases it, and a PATCH that mentions none of the four fields still leaves them alone.

Endpoints

  • POST|PUT|PATCH/v1/companies/{company_id}/recurring-invoicesNew rejections: PAYMENT_DETAILS_REQUIRE_METHOD, SERIES_INACTIVE, RECURRING_NO_OCCURRENCE_IN_WINDOW, LINE_UNIT_PRICE_OUT_OF_RANGE

Where to go next