Facturation et abonnements
Les factures, leur paiement par un client et le fonctionnement actuel de la facturation récurrente.
Les paiements et la facturation demandent des fonds de deux façons différentes. Votre code lance un paiement : vous appelez l'API, le téléphone s'allume et le client confirme dans la minute. Une facture est un document que vous remettez au client. Il la règle quand il le décide.
Cette section traite du second cas.
Contenu de la section
Un produit est disponible : Factures. Il produit un document numéroté, héberge la page de paiement du client et suit les fonds encaissés pour cette facture. Un abonnement, au sens d'un plan auquel un client souscrit et d'un portefeuille débité chaque mois sans intervention, n'est pas encore disponible.
| Besoin | Solution |
|---|---|
| Facturer une fois un client et être payé en ligne | Factures |
| Facturer le même client à intervalle fixe | Une facture récurrente, avec la limite expliquée ci-dessous |
| Débiter automatiquement un portefeuille enregistré selon un calendrier | Aucune pour le moment, consultez Abonnements |
| Accepter un paiement lancé par votre propre checkout | Paiements, pas la facturation |
Mode live uniquement et accès selon le plan
Toutes les routes /invoices sont protégées par le mode live. Une clé sandbox renvoie donc 403
avec This feature is only available in live mode., y compris pour les appels GET. La
fonctionnalité s'appelle invoicing : 10 factures au total avec Pay as you go, et non dix par
mois, puis un nombre illimité à partir de Growth. Une fois ce plafond atteint, la création renvoie
un code 403 avec une invitation à changer de plan.
Une facture est un document, pas un débit
Créer une facture ne déplace aucun fonds et n'envoie aucune notification. L'opération enregistre un document numéroté avec ses lignes, ses totaux et un statut, puis s'arrête. L'envoi, le paiement et les relances constituent trois opérations distinctes effectuées ensuite.
https://api.wajub.com/invoicescustomer_namestringobligatoireitemsarrayobligatoirename, quantity et unit_price.invoice_datestring (date)obligatoirecurrencystringobligatoirecustomer_idstring (uuid)facultatifcustomer_emailstringfacultatifdue_datestring (date)facultatifinvoice_date. La tâche des factures en retard la compare à la date du jour.payment_terms_daysintegerfacultatifdue_date à ce nombre de jours après aujourd'hui, uniquement en l'absence de due_date.items[].tax_ratenumberfacultatifitems[].discount_typeenumfacultatifpercentage ou fixed, associé à items[].discount_value.items[].discount_valuenumberfacultatifdocument_typeenumfacultatifdéfaut : invoiceinvoice, quote ou estimate. L'API liste et récupère uniquement les factures.is_recurringbooleanfacultatifnotesstringfacultatifterms et footer se trouvent à côté.Les totaux sont calculés à partir des lignes. Vous n'envoyez donc jamais subtotal ou total.
Envoyez la facture avec une clé secrète live.
curl https://api.wajub.com/invoices -H "Authorization: sk.kZ3qP8mWvL2xR7tB5nY4hC6dF9jS1aG0eU3i…" -H "Content-Type: application/json" -H "Idempotency-Key: invoice-amina-september" -d '{
"customer_name": "Amina Traoré",
"customer_email": "amina@example.com",
"invoice_date": "2026-09-11",
"due_date": "2026-09-25",
"currency": "XAF",
"items": [
{ "name": "Consulting, September", "quantity": 3, "unit_price": 150000 }
]
}'La réponse est 201 Created. Tous les autres appels utilisent l'id. invoice_number est la
référence lisible imprimée sur le document : INV-, suivi de l'année et du mois, puis d'un compteur
qui redémarre à 0001 chaque mois pour chaque compte.
Cycle de vie d'une facture
La répétition sur ces flèches est volontaire. Il n'existe aucun événement invoice.sent,
invoice.paid ou invoice.overdue. Lorsqu'une transition produit une notification, elle arrive
toujours sous la forme invoice.updated. Le champ status du payload indique la transition.
Deux états changent automatiquement. viewed est écrit lors de la première ouverture de la page de
paiement par le client. Une tâche nocturne écrit overdue en comparant due_date à la date du jour.
Vous ne définissez aucun de ces deux états.
Envoyer une facture ne la transmet pas
POST /invoices/{id}/send ne livre rien
L'appel définit status sur sent et renseigne sent_at. Il ne fait rien d'autre. Il ne génère
aucun PDF et n'envoie aucun e-mail. Le bouton Send du Dashboard envoie un e-mail avec le PDF en
pièce jointe. Il utilise un autre chemin de code inaccessible par l'API.
L'appel rend toutefois la page de paiement accessible. Une facture draft renvoie 403 This invoice is not available for payment. à toute personne qui ouvre son URL. Seuls quatre statuts sont
payables : sent, viewed, overdue et partial.
https://api.wajub.com/invoices/{id}/sendUn parcours piloté par l'API comporte donc trois étapes au lieu de deux : créez la facture, marquez-la comme envoyée pour ouvrir sa page, puis transmettez vous-même l'URL par votre canal de communication habituel. Wajub n'envoie rien pour votre compte.
Page de paiement du client
La page de paiement possède son propre domaine et utilise l'id de la facture comme chemin complet.
https://invoice.wajub.com/inv_LRQqYvlhrgUOE225KMKUCette adresse ne figure pas dans la réponse de l'API. Construisez-la à partir de l'id reçu ou
copiez-la depuis le Dashboard. C'est aussi le seul endroit où elle peut changer : un marchand qui
héberge ses factures sur un domaine personnalisé vérifié utilise ce domaine au lieu de
invoice.wajub.com.
La page constitue un checkout ordinaire. Elle affiche votre marque, les lignes de la facture et les
opérateurs disponibles pour sa devise. Un paiement effectué sur cette page reste un paiement
ordinaire : il apparaît dans votre liste Payments, émet payment.succeeded, rejoint votre solde et
peut être remboursé comme les autres. Après sa réussite, la facture passe à paid. Elle passe à
partial si elle est divisée en plusieurs échéances et qu'une seule a été réglée.
Enregistrer des fonds encaissés ailleurs
De nombreuses factures sont payées en espèces ou par un virement bancaire extérieur à Wajub. Vous pouvez enregistrer ce paiement sur le document sans créer un faux paiement.
https://api.wajub.com/invoices/{id}/mark-paidOmettez amount pour régler intégralement la facture. Si vous le transmettez, il est ajouté à
amount_paid. La facture reste alors partial jusqu'au règlement du total. Une facture cancelled
ou refunded refuse l'appel avec un code 400. Un document fermé par son propre parcours ne peut
donc pas être réactivé.
État actuel des factures récurrentes
La création accepte is_recurring et recurring_interval. L'intervalle peut valoir daily,
weekly, monthly, quarterly ou yearly. Une tâche s'exécute chaque nuit à 02:00. Elle recherche
les factures récurrentes dont la prochaine occurrence est arrivée, puis copie chacune dans un
nouveau document avec de nouvelles dates et les coordonnées actuelles du client.
Rien ne démarre la chaîne
La tâche lit next_invoice_date. Seule cette même tâche écrit ce champ, sur la facture qu'elle
vient de générer. La création ne le définit jamais, ni via l'API ni via le Dashboard. Une facture
récurrente est donc marquée, listée et filtrable comme telle, mais ne produit jamais de second
document. Considérez pour le moment la récurrence comme une intention enregistrée et créez chaque
échéance vous-même.
Deux points resteront importants lorsque ce manque sera comblé, car ils définissent la récurrence
sur Wajub. Chaque facture générée est créée avec draft. Même une chaîne fonctionnelle produirait
donc des documents, et non des débits. Chaque document devrait encore être envoyé et payé. La
fonctionnalité s'appelle recurring_billing et commence avec Growth. Le générateur ignore les
comptes qui ne la possèdent pas et conserve la facture parente. Les renouvellements reprennent
automatiquement si un compte ayant changé pour un plan inférieur repasse ensuite au plan requis.
Cette condition est contrôlée par le Dashboard et le générateur, mais pas par POST /invoices. La
création d'une facture récurrente via l'API réussit avec tous les plans. Seule la génération serait
refusée.
Événements envoyés à votre webhook
Trois événements concernent le document, pas les fonds.
| Événement | Déclencheur |
|---|---|
invoice.created | Une facture est créée avec draft |
invoice.updated | Un champ ou un statut change via l'API, y compris viewed et un paiement |
invoice.deleted | Une facture draft est supprimée |
Les fonds produisent un événement distinct. Lorsqu'un client paie une facture en ligne, vous recevez
payment.succeeded pour le paiement et invoice.updated pour le document. Livrez la commande avec
le premier, car il contient le montant, le canal et la référence du prestataire.
Seule l'API émet ces événements
Les webhooks sont envoyés par l'API. Une modification effectuée dans le Dashboard n'atteint donc
aucun endpoint. L'envoi, le marquage comme payée ou l'annulation d'une facture depuis l'interface
restent silencieux. La tâche nocturne écrit les statuts overdue en masse, sans produire
d'événements. Utilisez le polling sur GET /invoices si vous devez les détecter.
Dans le Dashboard
Billing → Invoices fournit l'interface complète, plus large que l'API. Elle génère le PDF, l'envoie au client avec le lien de paiement, suit les relances et exporte la liste au format CSV.
Deux tâches planifiées fonctionnent en arrière-plan. Les statuts sont actualisés chaque nuit à
01:00, ce qui fait passer une facture impayée à overdue. Les relances sont envoyées toutes les
heures aux clients dont la facture reste ouverte.
Pages associées
- FacturesTous les champs, le calcul des totaux et les huit appels.
- Démarrage rapideÉmettez votre première facture et faites-la payer.
- ClientsAssociez une facture à un client enregistré plutôt qu'à un simple nom.
- WebhooksÉcoutez payment.succeeded et rapprochez la facture.
- Référence API des facturesTous les champs et les huit endpoints.