Recurring invoices
What the recurring flag configures, what generates the next one, and what does not.
A recurring invoice is not a subscription. It is an ordinary invoice marked as a template: Wajub copies it into a new document each cycle, overnight, and every copy still has to be opened for payment and settled by the customer. Nothing is debited automatically, because nothing is stored that could be debited.
An invoice flagged recurring before 2026-10-11 stays inert
A recurring invoice created, or made recurring, before 11 October 2026 does not generate. While it is a draft, save its recurrence again and it is armed like a new one. Once it has been sent or paid it can no longer be edited: stop it and create a new recurring invoice instead.
Marking an invoice recurring
There is no separate endpoint and no subscription resource. Two fields on the ordinary create call are the whole surface.
https://api.wajub.com/invoicesis_recurringbooleanoptionaldefault : falseinvoice_date. Only an invoice can recur: on a quote or an estimate, true answers 422.recurring_intervalenumoptionaldaily, weekly, monthly, quarterly or yearly. The gap between copies.recurring_frequencyenumoptionalrecurring_interval, same five values.customer_idstringoptionalEverything else on the invoice, the lines, the totals, the notes, behaves exactly as on a one-off.
curl https://api.wajub.com/invoices \
-H "Authorization: sk.xxxxxxxxxxxxxxxx…" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cus_7Kq2mX9vL4tRb3nP8sZcWd1e",
"customer_name": "Amina Traoré",
"invoice_date": "2026-09-11",
"currency": "XAF",
"items": [
{ "name": "Retainer", "quantity": 1, "unit_price": 250000 }
],
"is_recurring": true,
"recurring_interval": "monthly"
}'The response is the same 201 Created as any other invoice, status: "draft" included, carrying
two recurring fields and no more.
recurring_frequency is a spelling, not a multiplier
Sending recurring_frequency: "monthly" sets recurring_interval to monthly: it is another
spelling of the same unit, not a number of units. An interval of every N months cannot be set
through the API. Update does not accept the alias at all, so send recurring_interval and treat
the other spelling as legacy.
What the API cannot set
The recurrence has more settings, and none of them is on the API. An end after N occurrences, or an interval of every N months, cannot be set through the API.
| Setting | What it does | Where |
|---|---|---|
| A start date | Puts the first copy on a date you choose, instead of one interval after the invoice | The Dashboard form |
| An end date | The last day a cycle is generated for | The Dashboard form |
| An end after a number of copies | Stop after this many copies | Not available |
| A multiple of the interval | Every two months, every three weeks | Not available |
An end date entered in the Dashboard is applied: the cycle that falls on it is the last one generated, and the series then stops for good. A recurrence created through the API has no end rule at all: it runs until you stop it.
What comes back, and what does not
Four recurring fields come back on the invoice object.
| Field | On a recurring invoice | On a generated copy |
|---|---|---|
is_recurring | true while the series runs, false once it is stopped | false: a copy generates nothing |
recurring_interval | daily, weekly, monthly, quarterly or yearly | The template's, copied |
next_invoice_date | The date of the next copy, YYYY-MM-DD. null once the series is stopped or the invoice cancelled. It stays set while generation is skipped for want of a plan, and past an end date until the next nightly run | null |
recurring_parent | null | The id of the recurring invoice it was generated from |
So a copy is the invoice whose recurring_parent is set. The end rule is not in the response, and
GET /invoices has no recurring filter, though the Dashboard list does.
How a cycle runs
The next date is set when the invoice is created recurring, or made recurring by an update: one
interval after its invoice_date. It is never set in the past, so a backdated invoice does not
produce the cycles that went by before it was recurring, and an update that turns the flag off
clears it. A series switched off and on again resumes after its latest copy: a cycle already
generated is never generated twice. A copy cannot be made recurring itself (422), and a duplicate
of a recurring invoice is a plain draft that recurs only if you set it to.
Every night at 02:00 UTC, Wajub generates the copies that have come due: for every invoice that is flagged recurring, whose next date has come, and that is not cancelled, it checks the plan, then the end rule, then copies.
| The copy inherits | The copy has of its own |
|---|---|
| The lines, with their quantities, prices and taxes | No invoice_number until it is sent, like any draft |
| The currency and the whole-invoice discount | invoice_date, set to the cycle that just came due |
| The notes, terms, footer and payment instructions | due_date, thirty days later |
| The template, the language and the display settings | The customer block, re-read from the customer record |
| The payment methods it accepts | is_recurring: false. A copy is an ordinary invoice and never generates copies of its own |
Then the original's next date moves forward by one interval, and the cycle is armed again. Each cycle produces exactly one copy.
Three details of the calendar. A run generates every cycle that has come due, not only the latest. A monthly, quarterly or yearly series never skips a month: one month after 31 January is 28 February, and the series goes on from the 28th. And the dates are UTC: a cycle dated the 11th is generated at 02:00 UTC on the 11th.
Two of those deserve a second look. The customer block is re-snapshotted from the live customer
each time, so an address or a company name corrected on the record flows into the next document and
leaves the earlier ones untouched. And due_date is always thirty days after the copy's date,
whatever terms the original carried.
A copy is a draft, not a charge
Each generated invoice lands as draft, with amount_paid back to zero. It is not opened for
payment, not emailed, and not paid, and it stays a draft past its due date: only a sent invoice
turns overdue. Somebody still has to call /send and deliver the URL every
cycle, exactly as for a one-off. Recurrence saves you writing the document, nothing else.
No customer record, no copy
An invoice without customer_id never generates. An invoice addressed to a customer_name alone,
which is perfectly valid for a one-off, silently produces no copy. Pass customer_id when you set
is_recurring.
Stopping a recurrence
An end date, where the Dashboard set one, ends the series on its own. Otherwise you stop it, at any point and whatever the invoice's status, paid included.
https://api.wajub.com/invoices/{id}/stop-recurringcurl -X POST https://api.wajub.com/invoices/inv_LRQqYvlhrgUOE225KMKU/stop-recurring \
-H "Authorization: sk.xxxxxxxxxxxxxxxx…"The call takes no body. The invoice comes back with is_recurring: false and next_invoice_date: null, nothing else about it changes, and invoice.updated is sent. No copy is generated after
this, and the copies already generated stay as they are: each one is an invoice of its own, to send,
cancel or delete like any other. Stopping a series already stopped answers 200 and changes
nothing. In the Dashboard the same action is Stop recurring, in the invoice's actions menu.
Call it on the recurring invoice, not on a copy. A copy has no series of its own, so the call
answers 400 on it, with the template's id in recurring_parent:
Two other calls touch the series, and both are narrower. PUT /invoices/{id} with
is_recurring: false stops it too, but only while the invoice is a draft, since only a draft can
be edited. Cancelling the invoice stops generation as well, and clears
next_invoice_date, but cancelling is refused once it is paid.
What it costs in plan
Recurrence needs the Recurring billing feature, which starts at Growth.
The Dashboard refuses to save a recurring invoice without it. Without the plan, generation is
skipped and the document is left untouched, so a downgraded account resumes on its own if it
upgrades again, with the cycles that came due in the meantime. POST /invoices does not check the
plan, so creating a recurring invoice through the API succeeds on any plan and simply never
generates.