Recurring invoices
Skip a cycle, create a recurrence from an invoice, configure auto-delivery, preview the next document and set per-line fiscal fields.
A recurring invoice is a template plus a cadence: Factuarea generates a real invoice on every scheduled run. This guide covers the controls that go beyond basic create/update — skipping a cycle, bootstrapping a recurrence from an existing invoice, automatic email delivery, previewing the computed document and the per-line fiscal fields that VeriFactu requires.
All endpoints below live under https://api.factuarea.com/v1 and use the same
error envelope, cursor pagination and
scopes as the rest of the API.
Skip the next generation
POST /v1/recurring_invoices/{recurring_invoice}/skipAdvances next_run_at by exactly one period without generating an invoice
for the current cycle. The skipped occurrence is not counted against
max_occurrences — the generated-invoice counter does not move. Use it to jump
over a billing period (holidays, a paused client) while keeping the schedule
intact.
Requires the recurring_invoices:write scope. Returns 200 with the
recurring-invoice resource (note the advanced next_run_at). A cancelled or
completed recurrence responds 422; a recurring invoice that belongs to another
company responds 404.
curl -X POST https://api.factuarea.com/v1/recurring_invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b/skip \
-H "Authorization: Bearer $FACTUAREA_API_KEY"Skipping logs a skipped entry in the recurring-invoice activity — the
history shows the cycle was deliberately omitted, not missed.
Create a recurrence from an existing invoice
POST /v1/invoices/{invoice}/create-recurringCopies the lines, client and series of a source invoice into a brand-new
recurring invoice (its own UUID v7) and applies the cadence supplied in the
body. The source invoice is untouched. Requires the recurring_invoices:write
scope.
| Field | Type | Required | Notes |
|---|---|---|---|
frequency | string | yes | daily, weekly, biweekly, monthly, quarterly, semiannual, yearly. |
start_on | string (YYYY-MM-DD) | yes | First scheduled run. |
end_on | string (YYYY-MM-DD) | no | Last allowed run. |
name | string | no | Label for the recurrence (≤255). |
description | string | no | |
notes | string | no | |
metadata | object | no | Your key/value pairs. |
holiday_handling | string | no | How to shift a run that falls on a holiday. |
days_before_due | integer | no | Due date offset for each generated invoice. |
max_occurrences | integer | no | Stop after N generated invoices. |
auto_delivery | object | no | See Auto-delivery. |
Returns 201 with the new recurring invoice and a Location header pointing to
it. A source invoice that belongs to another company responds 404.
curl -X POST https://api.factuarea.com/v1/invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a42/create-recurring \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"frequency": "monthly",
"start_on": "2026-07-01",
"max_occurrences": 12,
"auto_delivery": {
"send_automatically": true,
"recipients": ["billing@acme.example"]
}
}'Auto-delivery
The auto_delivery object — available on recurring create, update and
create-recurring — emails every generated invoice automatically.
| Field | Type | Notes |
|---|---|---|
send_automatically | boolean | Master switch. false disables sending. |
recipients | string[] | Primary recipients (email). |
cc | string[] | Carbon-copy recipients (email). |
subject | string | Custom subject (≤255). null uses the default. |
body | string | Custom body (≤5000). null uses the default. |
When send_automatically is true, each generated invoice is emailed to
recipients (with optional cc) using subject/body. Setting
send_automatically to false turns delivery off. An empty recipients list
with send_automatically: true is rejected with 422 — there is no one to send
to.
{
"auto_delivery": {
"send_automatically": true,
"recipients": ["billing@acme.example"],
"cc": ["copy@acme.example"],
"subject": "Your monthly invoice",
"body": "Hi, here is your invoice for this period."
}
}Preview the computed document
GET /v1/recurring_invoices/{recurring_invoice}/previewWithout expand, preview returns only the date forecast — the upcoming
run dates (use count to control how many).
Pass expand=document to also compute the next document as a dry-run: the
response adds a next_invoice block with the resolved lines and
totals (subtotal, tax, total), built from template_data without
persisting anything. Use it to show the customer exactly what the next invoice
will contain before it is issued.
curl -G https://api.factuarea.com/v1/recurring_invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b/preview \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
--data-urlencode "expand=document"{
"data": { "id": "01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b", "object": "recurring_invoice" },
"next_invoice": {
"lines": [
{ "description": "Monthly retainer", "quantity": 1, "unit_price": 500, "subtotal": 500 }
],
"totals": { "subtotal": 500, "tax": 105, "total": 605 }
}
}preview never creates an invoice. It is a pure read — the dry-run totals are
computed in memory from template_data.
Per-line fiscal fields
Each line of template_data accepts the fiscal fields VeriFactu and the Spanish
tax model need. They flow into every generated invoice.
| Field | Type | Notes |
|---|---|---|
exemption_reason | string | LIVA exemption / non-subjection cause. One of E1–E6, N1, N2. null if not informed. |
regime_key | string | VeriFactu regime key (ClaveRegimen, AEAT list L8.1). null if not informed. |
retention | number | IRPF withholding percentage (0–100). |
retention_rate_id | string (UUID v7) | Catalog tax applied as IRPF withholding. Opaque — does not change the taxes/total computation (the flat retention percentage does). |
surcharge | number | Equivalence surcharge percentage (0–100). |
surcharge_rate_id | string (UUID v7) | Catalog tax applied as equivalence surcharge. Opaque — the flat surcharge percentage drives the maths. |
The equivalence surcharge is tied to the line VAT by law. The only legal
tax_rate → surcharge pairs are:
VAT (tax_rate) | Surcharge (surcharge) |
|---|---|
21 | 5.2 |
10 | 1.4 |
4 | 0.5 |
Sending an exemption_reason, regime_key, retention_rate_id or
surcharge_rate_id outside its catalog responds 422 with an allowed_values
list in the error. An illegal VAT↔surcharge pair (e.g. 21 with 1.4) is also
rejected with 422.
{
"template_data": {
"lines": [
{
"description": "Consulting",
"quantity": 1,
"unit_price": 1000,
"tax_rate": 21,
"surcharge": 5.2,
"retention": 15,
"regime_key": "01",
"exemption_reason": null
}
]
}
}