Factures récurrentes
Ce que configure l'indicateur de récurrence, ce qui génère la facture suivante et ce qui ne le fait pas.
Une facture récurrente n'est pas un abonnement. C'est une facture classique marquée comme modèle : une tâche nocturne la copie dans un nouveau document à chaque cycle. Chaque copie doit encore être ouverte au paiement et réglée par le client. Rien n'est débité automatiquement, car aucune donnée réutilisable pour un débit n'est enregistrée.
Aucune deuxième facture n'est générée aujourd'hui
La tâche détermine l'échéance en lisant next_invoice_date. Or, seul son propre code renseigne ce
champ, sur la copie qu'elle vient de créer. La création ne le définit jamais, ni par l'API ni dans
le Dashboard. Il manque donc le premier maillon de la chaîne. Une facture récurrente est
enregistrée, marquée et répertoriée comme telle, mais aucune copie n'est jamais générée. Émettez
vous-même chaque nouvelle facture jusqu'à la résolution de ce problème. La suite décrit ce que
configure l'indicateur et ce que la tâche en fait.
Marquer une facture comme récurrente
Il n'existe ni endpoint distinct ni ressource d'abonnement. Deux champs de l'appel de création classique couvrent toute la fonctionnalité.
https://api.wajub.com/invoicesis_recurringbooleanfacultatifdéfaut : falserecurring_intervalenumfacultatifdaily, weekly, monthly, quarterly ou yearly. Intervalle entre les copies.recurring_frequencyenumfacultatifrecurring_interval, avec les cinq mêmes valeurs.customer_idstring (uuid)facultatifTout le reste de la facture, notamment les lignes, les totaux et les notes, fonctionne exactement comme sur une facture ponctuelle.
curl https://api.wajub.com/invoices \
-H "Authorization: sk.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "9d1f0c7a-4b2e-4f61-9d3a-7c8e5b21a940",
"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"
}'La réponse est la même que pour toute autre facture, avec 201 Created, status: "draft", les deux
champs de récurrence et rien de plus.
recurring_frequency est un autre nom, pas un multiplicateur
En interne, recurring_interval contient l'unité et recurring_frequency un nombre : le nombre
d'unités entre les copies. L'API n'expose pas ce nombre. Envoyer recurring_frequency: "monthly"
reporte cette valeur dans recurring_interval et fixe le multiplicateur à 1. Une fréquence de
deux mois n'est donc pas accessible par l'API. La mise à jour ignore aussi complètement l'alias.
Envoyez recurring_interval et considérez l'autre nom comme obsolète.
Ce que l'API ne peut pas définir
La récurrence possède quatre autres réglages dans la base de données. Aucun n'est disponible dans l'API.
| Réglage | Rôle | Emplacement |
|---|---|---|
recurring_end_type | never, date ou occurrences | Dashboard |
recurring_end_date | Arrête la génération après cette date | Dashboard |
recurring_occurrences | Arrête la génération après ce nombre de copies | Dashboard |
Un multiplicateur supérieur à 1 | Tous les deux mois, toutes les trois semaines | Nulle part |
Une facture créée par l'API ne possède donc aucune règle de fin. Ce point est plus important qu'il
n'y paraît. Lisez la section ci-dessous sur l'arrêt avant de définir is_recurring sur une facture.
Ce qui est renvoyé et ce qui ne l'est pas
is_recurring et recurring_interval sont les seuls champs de récurrence de l'objet facture. La
réponse ne contient ni next_invoice_date, ni recurring_parent_id, ni règle de fin.
Vous devez tenir compte de deux conséquences. L'API ne peut pas vous indiquer la date du prochain
document. Elle ne permet pas non plus de distinguer une copie générée de la facture qui lui a servi
de modèle, car leur lien n'est pas exposé. GET /invoices n'a pas non plus de filtre de récurrence,
contrairement à la liste du Dashboard. Conservez donc votre propre trace de la facture récurrente.
Déroulement d'un cycle
Une tâche nommée invoices:generate-recurring s'exécute chaque nuit à 02 h 00. Elle parcourt toutes
les factures marquées comme récurrentes, dont la prochaine date est passée et qui ne sont pas
annulées. Pour chacune, elle vérifie le plan, puis la règle de fin, avant de la copier.
| La copie hérite | La copie recalcule |
|---|---|
| Les lignes, avec leurs quantités, prix et taxes | Son propre invoice_number |
| La devise, les notes, les conditions et le pied de page | invoice_date, définie sur la date du cycle arrivé à échéance |
| L'intervalle et la règle de fin | due_date, trente jours plus tard |
| Le modèle et les réglages d'affichage | Le bloc client, relu depuis la fiche du client |
La prochaine date de la facture d'origine avance ensuite d'un intervalle, ce qui programme le cycle suivant.
Deux de ces points méritent votre attention. Le bloc client est repris depuis la fiche actuelle à
chaque cycle. Une adresse ou un nom d'entreprise corrigé sur la fiche apparaît donc dans le document
suivant sans modifier les précédents. Par ailleurs, due_date est toujours fixée à trente jours
après la date de la copie, quelles que soient les conditions de la facture d'origine. Le champ utilisé
pour ce calcul n'existe pas sur la facture.
Une copie est un brouillon, pas un débit
Chaque facture générée arrive au statut draft, avec amount_paid remis à zéro. Elle n'est ni
ouverte au paiement, ni envoyée par e-mail, ni payée. Quelqu'un doit encore appeler /send et
transmettre l'URL à chaque cycle, exactement comme pour une facture ponctuelle. La récurrence vous
évite seulement de rédiger le document.
Sans fiche client, aucune copie
La génération charge le client de la facture et abandonne s'il n'existe pas. Elle consigne alors
un avertissement et poursuit. Une facture adressée uniquement à un customer_name, ce qui est
parfaitement valide pour une facture ponctuelle, ne produit jamais de copie et ne signale rien.
Envoyez customer_id lorsque vous définissez is_recurring.
Arrêter une récurrence
Tant que la facture d'origine reste impayée, deux appels peuvent y mettre fin. L'annulation la retire définitivement du champ de la tâche. Une mise à jour qui désactive l'indicateur conserve le document, mais le rend inactif.
https://api.wajub.com/invoices/{id}/cancelcurl -X PUT https://api.wajub.com/invoices/inv_LRQqYvlhrgUOE225KMKU \
-H "Authorization: sk.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" \
-H "Content-Type: application/json" \
-d '{ "is_recurring": false }'Après son paiement, aucun des deux appels n'est accepté
Une facture payée, remboursée, annulée ou dont amount_paid est supérieur à zéro est figée. La
mise à jour répond 400 This invoice cannot be edited (paid, cancelled, or has payments). et
l'annulation répond 400 This invoice cannot be cancelled (already paid, cancelled, or refunded).
La récurrence, elle, n'est pas figée avec la facture. Décidez comment elle se termine avant le
règlement du premier cycle et définissez sa règle de fin dans le Dashboard, puisque l'API ne le
permet pas.
Coût selon le plan
La récurrence nécessite recurring_billing, disponible à partir de Growth. Cette condition est
appliquée à deux des trois endroits possibles.
Le Dashboard refuse d'enregistrer une facture récurrente sans cette fonctionnalité. La tâche la
vérifie à chaque exécution et ignore la facture si elle est absente. Elle consigne alors une
information et ne modifie pas le document. Après le passage à un plan inférieur, la génération
reprend donc automatiquement si le compte revient à un plan supérieur. POST /invoices ne vérifie
aucune de ces conditions. La création d'une facture récurrente par l'API réussit avec tous les plans,
mais ne génère simplement rien.