Factures recurrents
Omet un cicle, crea una recurrència des d'una factura, tria si cada execució emet o envia la factura, fixa o segueix la plantilla PDF, genera una factura ara, configura l'enviament automàtic, previsualitza el pròxim document i defineix camps fiscals per línia.
Una factura recurrent és una plantilla més una cadència: Factuarea genera una factura real a cada execució programada. Aquesta guia cobreix els controls que van més enllà del create/update bàsic — ometre un cicle, arrencar una recurrència a partir d'una factura existent, l'enviament automàtic per correu, la previsualització del document calculat i els camps fiscals per línia que exigeix VeriFactu.
Tots els endpoints de sota viuen sota https://api.factuarea.com/v1 i usen el
mateix embolcall d'error, paginació per
cursor i scopes que la
resta de l'API. Pengen de /v1/companies/{company}/…: {company} és l'id
(UUID v7) del NIF amb què operes, i als exemples curl és $COMPANY_ID.
Arribar a un NIF explica com resoldre'l.
Ometre la pròxima generació
POST /v1/companies/{company}/recurring-invoices/{recurring_invoice}/skipAvança next_run_at exactament un període sense generar cap factura per al
cicle actual. L'ocurrència omesa no compta per a max_occurrences — el
comptador de factures generades no es mou. Fes-lo servir per saltar-te un període
de facturació (festius, un client en pausa) mantenint intacte el calendari.
Requereix l'scope recurring_invoices:write. Retorna 200 amb el recurs de la
factura recurrent (fixa't en el next_run_at avançat). Una recurrència
cancel·lada o completada respon 422; una factura recurrent que pertany a una
altra empresa respon 404.
curl -X POST https://api.factuarea.com/v1/companies/$COMPANY_ID/recurring-invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b/skip \
-H "Authorization: Bearer $FACTUAREA_API_KEY"Ometre registra una entrada skipped a l'activitat de la factura recurrent —
l'historial mostra que el cicle es va ometre expressament, no que es va perdre.
Crear una recurrència des d'una factura existent
POST /v1/companies/{company}/invoices/{invoice}/create-recurringCopia les línies, el client i la sèrie d'una factura origen en una factura
recurrent nova (amb el seu propi UUID v7) i aplica la cadència indicada al cos.
La factura origen queda intacta. Requereix l'scope recurring_invoices:write.
| Camp | Tipus | Obligatori | Notes |
|---|---|---|---|
frequency | string | sí | daily, weekly, biweekly, monthly, quarterly, semiannual, yearly. |
start_on | string (YYYY-MM-DD) | sí | Primera execució programada. |
end_on | string (YYYY-MM-DD) | no | Última execució permesa. |
name | string | no | Etiqueta de la recurrència (≤255). |
description | string | no | |
notes | string | no | |
metadata | object | no | Els teus parells clau/valor. |
holiday_handling | string | no | Com desplaçar una execució que cau en festiu. |
days_before_due | integer | no | Desfasament de venciment de cada factura generada. |
max_occurrences | integer | no | Aturar després de N factures generades. |
auto_delivery | object | no | Vegeu Enviament automàtic. |
generation_mode | string | no | draft, issue o issue_and_send. Vegeu Mode de generació. |
presentation_policy | objecte | no | Quina plantilla PDF fa servir cada execució. Vegeu Política de presentació. |
payment_terms_template | array | no | Terminis relatius per a cada factura generada. Vegeu Plantilla de calendari de pagaments. |
Retorna 201 amb la nova factura recurrent i una capçalera Location que hi
apunta. Una factura origen que pertany a una altra empresa respon 404.
curl -X POST https://api.factuarea.com/v1/companies/$COMPANY_ID/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,
"generation_mode": "issue_and_send",
"auto_delivery": {
"recipients": ["billing@acme.example"]
}
}'Mode de generació
generation_mode decideix què fa cada execució amb la factura que genera. Està
disponible a POST /v1/companies/{company}/recurring-invoices,
PATCH /v1/companies/{company}/recurring-invoices/{recurring_invoice} i
POST /v1/companies/{company}/invoices/{invoice}/create-recurring, a totes les versions de l'API, i
totes les respostes de factures recurrents el retornen.
generation_mode | Cada execució | Enviament |
|---|---|---|
draft | Deixa la factura en esborrany, sense número definitiu. | Cap. |
issue | Emet la factura: número definitiu, registre VeriFactu, moviments d'stock. | Cap: la factura queda amb is_sent: false. |
issue_and_send | Emet la factura i l'envia per correu als destinataris de l'enviament automàtic. | Es marca com a enviada quan el servidor de correu accepta l'email. |
A issue_and_send, un lliurament fallit no desfà l'execució: la factura queda
emesa i sense enviar, i la pots enviar després amb
POST /v1/companies/{company}/invoices/{invoice}/send. Qualsevol altre valor respon 422. A PATCH,
ometre generation_mode conserva el mode actual.
send_automatically es manté com a camp de compatibilitat derivat del mode:
true només amb issue_and_send. Sense generation_mode, true continua
seleccionant issue_and_send i false selecciona draft; enviar tots dos amb
valors contradictoris respon 422. Les factures recurrents creades abans que
existís el mode conserven el seu comportament: les que enviaven les factures per
correu són issue_and_send i la resta draft.
Política de presentació
Cada factura que genera una recurrència necessita una plantilla PDF. La política de
presentació diu quina. Està disponible a POST /v1/companies/{company}/recurring-invoices,
PATCH /v1/companies/{company}/recurring-invoices/{recurring_invoice} i
POST /v1/companies/{company}/invoices/{invoice}/create-recurring, i el recurs de factura recurrent retorna
presentation_policy, presentation_policy_version i presentation_pause_reason.
La política és un objecte amb exactament cinc claus, totes obligatòries:
| Clau | latest | pinned |
|---|---|---|
mode | "latest" | "pinned" |
template_id | L'UUID d'una plantilla, o null per seguir la selecció que rebria normalment cada document (sèrie, client, empresa). | Obligatòria. |
revision_id | null | Obligatòria: la revisió exacta de la plantilla. |
commercial_identity_id, commercial_identity_revision_id | null | Totes dues informades, o totes dues null quan la plantilla no té marca. |
latestsegueix la plantilla: cada execució fa servir la revisió publicada en aquell moment, així que editar la plantilla canvia les factures següents.pinnedla fixa: cada execució fa servir exactament aquella revisió (i la revisió de marca), per molt que la plantilla canviï després. Un pin que ja no es pot usar mai no degrada alatest.
curl -X PATCH https://api.factuarea.com/v1/companies/$COMPANY_ID/recurring-invoices/0197c6a0-5e14-7b29-8d73-4a1f9c2e6b35 \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"presentation_policy": {
"mode": "pinned",
"template_id": "0197c4a1-02aa-7c31-9e5b-6d2f8a4c1b73",
"revision_id": "0197c4a1-02ab-7e08-8a14-3b7c9d5e2f40",
"commercial_identity_id": null,
"commercial_identity_revision_id": null
},
"expected_presentation_policy_version": 1
}'En actualitzar, ometre presentation_policy conserva l'actual i null la restableix a
una política latest que segueix la selecció habitual. {}, les claus de més i les
combinacions parcials es rebutgen amb 422 invalid_recurring_presentation_policy
(error.param assenyala la clau afectada); per exemple, una revisió de marca fixada
sense la seva marca.
Versió. La política té el seu propi comptador, presentation_policy_version, que en
una recurrència nova comença a 1. Per editar una recurrència existent has d'enviar
expected_presentation_policy_version (un enter d'1 o més) sempre que la petició porti
la política, la plantilla de calendari de pagaments, el client o la sèrie, fins i tot si
el valor és null o no canvia. Sense ell:
428 recurring_presentation_policy_precondition_required. Amb un d'obsolet:
409 recurring_presentation_policy_version_conflict, i no s'escriu res. Torna a
llegir la recurrència i reintenta sobre la versió nova. Canviar només etiquetes no el
necessita, una recurrència nova no l'accepta i desar mai no reactiva una recurrència
pausada.
Si la presentació amb revisions no està activa per a la teva empresa, presentation_policy,
payment_terms_template i expected_presentation_policy_version s'ignoren
(fins i tot com a null): la petició es comporta com abans i mai no respon
pdf_presentation_not_ready per aquests camps. Quan és activa es validen.
Quan la plantilla deixa d'estar disponible
Entre execucions, una plantilla pot arxivar-se, perdre compatibilitat o deixar d'estar inclosa al teu pla. El que passa depèn del mode:
latest: l'execució es desfà (no es crea cap factura), la recurrència passa apausedipresentation_pause_reasondiu per què:template_archived,template_blocked,template_incompatible,commercial_identity_archived,commercial_identity_blocked,entitlement_unavailableoconfiguration_invalid. L'empresa rep un únic avís que demana una plantilla disponible.pinned: la recurrència no es pausa ni es modifica. L'execució fallida queda anotada als registres i el pin continua apuntant a la seva revisió.
Restaurar la plantilla o editar la recurrència no la reprèn. Reprèn-la de manera
explícita amb POST /v1/companies/{company}/recurring-invoices/{id}/resume: torna a comprovar la política i,
si la plantilla continua sense estar disponible, respon
422 recurring_presentation_unavailable i deixa el motiu de pausa. Els errors que no
són visuals (transport, dades fiscals, dades bancàries) mai no es converteixen en una
pausa.
Plantilla de calendari de pagaments
payment_terms_template dona a cada factura generada el seu calendari de pagaments, amb
desplaçaments en lloc de dates. Cada fila té offset_days (un enter de 0 o més, no
decreixent al llarg de la llista), amount (un string amb exactament dos decimals,
diferent de zero, amb el mateix signe a totes les files), payment_means ("01" a
"19") i account (un objecte { "iban", "bic" } o null; només per a 02 i 04). En
actualitzar, ometre-la conserva la plantilla, null vol dir desconegut i [] vol dir
«sense terminis».
{
"payment_terms_template": [
{ "offset_days": 0, "amount": "50.00", "payment_means": "01", "account": null },
{ "offset_days": 30, "amount": "50.00", "payment_means": "01", "account": null }
]
}La data de venciment de cada termini és la data d'aquella factura més el seu
desplaçament, i cada factura rep les seves pròpies identitats de termini. Els imports han
de sumar el total a pagar de la factura generada: si no, aquella execució falla amb
l'error de la factura (consulta
Dades de negoci de la factura), no amb una
pausa visual. Una fila incorrecta respon 422 invalid_recurring_payment_terms_template.
Generar una factura ara
POST /v1/companies/{company}/recurring-invoices/{recurring_invoice}/generateForça la generació de la factura d'avui fora del cicle
(referència,
scope recurring_invoices:write). Segueix les mateixes regles que una execució
programada: el mode de generació decideix si la factura es queda en
esborrany, s'emet o s'envia per correu, i la política de presentació
decideix la plantilla. Respon 200:
{
"data": {
"object": "recurring_invoice.generate_result",
"invoice_id": "0197c6b3-2a48-7d15-9e60-5c8b1f3a7d92",
"invoice_number": "F-2026-0048"
}
}Una recurrència genera una factura per dia: repetir la crida el mateix dia retorna la
factura ja generada. Una recurrència que no es pot executar en el seu estat actual respon
422 recurring_invoice_cannot_run, i una política latest amb la plantilla no
disponible respon 422 recurring_presentation_unavailable. El servidor MCP ofereix la
mateixa operació com a eina generate_recurring_invoice.
Si l'empresa activa o desactiva el seu sistema de presentació dues vegades seguides mentre es genera la factura, la crida respon un 409 reintentable recurring_presentation_activation_changed. No s'ha escrit res: repeteix la petició, i la mateixa Idempotency-Key no duplica la factura.
Enviament automàtic
L'objecte auto_delivery — disponible en crear i actualitzar una recurrent i a
create-recurring — envia per correu cada factura generada de manera automàtica.
| Camp | Tipus | Notes |
|---|---|---|
send_automatically | boolean | Derivat de generation_mode: true només amb issue_and_send. És preferible enviar el mode. |
recipients | string[] | Destinataris principals (email). |
cc | string[] | Destinataris en còpia (email). |
subject | string | Assumpte personalitzat (≤255). null usa el predeterminat. |
body | string | Cos personalitzat (≤5000). null usa el predeterminat. |
Amb generation_mode: "issue_and_send", cada factura generada s'envia per
correu a recipients (amb cc opcional) usant subject/body. draft i
issue no envien res. Amb issue_and_send, un objecte auto_delivery necessita
almenys un destinatari: una llista recipients buida respon
422 auto_delivery_recipients_required — no hi ha a qui enviar.
{
"generation_mode": "issue_and_send",
"auto_delivery": {
"recipients": ["billing@acme.example"],
"cc": ["copy@acme.example"],
"subject": "La teva factura mensual",
"body": "Hola, aquí tens la teva factura d'aquest període."
}
}Previsualitzar el document calculat
GET /v1/companies/{company}/recurring-invoices/{recurring_invoice}/previewSense expand, preview retorna només la previsió de dates — les pròximes
dates d'execució (usa count per controlar quantes).
Passa expand=document per calcular a més el pròxim document en sec: la
resposta afegeix un bloc next_invoice amb les lines resoltes i els totals
(subtotal, tax, total), construïts des de template_data sense persistir
res. Fes-lo servir per mostrar al client què contindrà exactament la pròxima
factura abans d'emetre-la.
curl -G https://api.factuarea.com/v1/companies/$COMPANY_ID/recurring-invoices/01931b3e-7c4a-7f2e-9a8b-3c5d6e7f8a0b/preview \
-H "Authorization: Bearer $FACTUAREA_API_KEY" \
--data-urlencode "expand=document" \
--data-urlencode "count=2"{
"data": [
{
"date": "2026-04-01",
"due_date": "2026-05-01",
"occurrence_number": 4,
"estimated_total": 242,
"will_be_sent": true
},
{
"date": "2026-05-01",
"due_date": "2026-05-31",
"occurrence_number": 5,
"estimated_total": 242,
"will_be_sent": true
}
],
"next_invoice": {
"lines": [
{
"description": "Cuota soporte mensual",
"quantity": 1,
"unit_price": 200,
"tax_rate": 21,
"retention_rate": 0,
"surcharge_rate": 0,
"commercial_quantity": 1,
"commercial_unit_code": "MON",
"base_unit_code": "MON",
"conversion_factor": "1.000000",
"base_quantity": "1.0000",
"price_list_uuid": null,
"price_list_name": null,
"price_source": "manual",
"price_unit_code": "MON",
"configuration_uuid": null,
"configuration_name": null,
"configuration_signature": null,
"option_labels": [],
"price_semantics": "per_commercial_unit",
"price_adjustment_total": "0.0000",
"option_adjustments_absorbed": false,
"subtotal": 200,
"tax": 42,
"line_total": 242
}
],
"totals": {
"subtotal": 200,
"tax": 42,
"total": 242
}
}
}preview mai crea cap factura. És una lectura pura — els totals en sec es
calculen en memòria des de template_data.
Camps fiscals per línia
Cada línia de template_data accepta els camps fiscals que necessiten VeriFactu i
el model tributari espanyol. Es traslladen a cada factura generada.
| Camp | Tipus | Notes |
|---|---|---|
exemption_reason | string | Causa d'exempció / no subjecció segons LIVA. Un de E1–E6, N1, N2. null si no s'informa. |
regime_key | string | Clau de règim VeriFactu (ClaveRegimen, llista L8.1 de l'AEAT). null si no s'informa. |
retention | number | Percentatge de retenció IRPF (0–100). |
retention_rate_id | string (UUID v7) | Impost del catàleg aplicat com a retenció IRPF. Opac — no canvia el càlcul de taxes/total (ho fa el percentatge pla retention). |
surcharge | number | Percentatge de recàrrec d'equivalència (0–100). |
surcharge_rate_id | string (UUID v7) | Impost del catàleg aplicat com a recàrrec d'equivalència. Opac — el percentatge pla surcharge governa el càlcul. |
El recàrrec d'equivalència va lligat per llei a l'IVA de la línia. Els únics
parells legals tax_rate → surcharge són:
IVA (tax_rate) | Recàrrec (surcharge) |
|---|---|
21 | 5.2 |
10 | 1.4 |
4 | 0.5 |
Enviar un exemption_reason, regime_key, retention_rate_id o
surcharge_rate_id fora del seu catàleg respon 422 amb una llista
allowed_values a l'error. Un parell IVA↔recàrrec il·legal (p.ex. 21 amb
1.4) també es rebutja amb 422.
{
"template_data": {
"lines": [
{
"description": "Consultoria",
"quantity": 1,
"unit_price": 1000,
"tax_rate": 21,
"surcharge": 5.2,
"retention": 15,
"regime_key": "01",
"exemption_reason": null
}
]
}
}Snapshots de catàleg i tarifa
Les plantilles recurrents admeten price_list_id i reprice_strategy, igual que
un esborrany de venda. Les línies de catàleg a template_data.lines poden desar
product_id, variant_id, presentation_id, confirmed_base_quantity i els
camps resolts de snapshot (item_kind, unitats, factor, quantitat base,
price_source, id/nom de tarifa i unitat de preu). Les factures generades
hereten aquest snapshot; editar després el catàleg no reescriu la plantilla. Usa
existing_catalog_lines per recalcular línies de catàleg o future_lines_only
per conservar-les. Els preus manuals, d'oferta o de pack mai es repricien
silenciosament. Consulta Tarifes.
Previsions, registres i estimacions mensuals
preview retorna un array de dates previstes a data; count admet fins a 36. expand=document afegeix el document següent calculat. Els registres d’execució fan servir limit (fins a 100) i cursor. estimated_revenue_this_month estima els imports de les plantilles que queden programades des d’avui fins a final de mes. No representa ingressos emesos, cobraments ni efectiu garantit. Les plantilles conserven additional_description per línia.