Factuarea APIDevelopers

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}/skip

Avanç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-recurring

Copia 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.

CampTipusObligatoriNotes
frequencystringsídaily, weekly, biweekly, monthly, quarterly, semiannual, yearly.
start_onstring (YYYY-MM-DD)síPrimera execució programada.
end_onstring (YYYY-MM-DD)noÚltima execució permesa.
namestringnoEtiqueta de la recurrència (≤255).
descriptionstringno
notesstringno
metadataobjectnoEls teus parells clau/valor.
holiday_handlingstringnoCom desplaçar una execució que cau en festiu.
days_before_dueintegernoDesfasament de venciment de cada factura generada.
max_occurrencesintegernoAturar després de N factures generades.
auto_deliveryobjectnoVegeu Enviament automàtic.
generation_modestringnodraft, issue o issue_and_send. Vegeu Mode de generació.
presentation_policyobjectenoQuina plantilla PDF fa servir cada execució. Vegeu Política de presentació.
payment_terms_templatearraynoTerminis 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_modeCada execucióEnviament
draftDeixa la factura en esborrany, sense número definitiu.Cap.
issueEmet la factura: número definitiu, registre VeriFactu, moviments d'stock.Cap: la factura queda amb is_sent: false.
issue_and_sendEmet 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:

Claulatestpinned
mode"latest""pinned"
template_idL'UUID d'una plantilla, o null per seguir la selecció que rebria normalment cada document (sèrie, client, empresa).Obligatòria.
revision_idnullObligatòria: la revisió exacta de la plantilla.
commercial_identity_id, commercial_identity_revision_idnullTotes dues informades, o totes dues null quan la plantilla no té marca.
  • latest segueix la plantilla: cada execució fa servir la revisió publicada en aquell moment, així que editar la plantilla canvia les factures següents.
  • pinned la 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 a latest.
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 a paused i presentation_pause_reason diu per què: template_archived, template_blocked, template_incompatible, commercial_identity_archived, commercial_identity_blocked, entitlement_unavailable o configuration_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}/generate

Forç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.

CampTipusNotes
send_automaticallybooleanDerivat de generation_mode: true només amb issue_and_send. És preferible enviar el mode.
recipientsstring[]Destinataris principals (email).
ccstring[]Destinataris en còpia (email).
subjectstringAssumpte personalitzat (≤255). null usa el predeterminat.
bodystringCos 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}/preview

Sense 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.

CampTipusNotes
exemption_reasonstringCausa d'exempció / no subjecció segons LIVA. Un de E1–E6, N1, N2. null si no s'informa.
regime_keystringClau de règim VeriFactu (ClaveRegimen, llista L8.1 de l'AEAT). null si no s'informa.
retentionnumberPercentatge de retenció IRPF (0–100).
retention_rate_idstring (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).
surchargenumberPercentatge de recàrrec d'equivalència (0–100).
surcharge_rate_idstring (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)
215.2
101.4
40.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.

En aquesta pàgina

Et donem un cop de mà?Contactar amb suport