Aller au contenu

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.

Votre serveur crée la facture, Wajub héberge la page sur laquelle elle est payée, puis le cycle recommence. Transmettre l'adresse au client reste de votre ressort.

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.

BesoinSolution
Facturer une fois un client et être payé en ligneFactures
Facturer le même client à intervalle fixeUne facture récurrente, avec la limite expliquée ci-dessous
Débiter automatiquement un portefeuille enregistré selon un calendrierAucune pour le moment, consultez Abonnements
Accepter un paiement lancé par votre propre checkoutPaiements, pas la facturation

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.

POSThttps://api.wajub.com/invoices
customer_namestringobligatoire
Le destinataire de la facture. Un nom suffit, aucun enregistrement client n'est obligatoire.
itemsarrayobligatoire
Au moins une ligne. Chacune contient name, quantity et unit_price.
invoice_datestring (date)obligatoire
La date imprimée sur le document. Elle est obligatoire et ne possède aucune valeur par défaut.
currencystringobligatoire
Code ISO 4217. Tous les montants de la facture utilisent cette devise.
customer_idstring (uuid)facultatif
Associe la facture à un [client](/payments/customers). Ses coordonnées sont copiées dans le document lors de la création.
customer_emailstringfacultatif
Adresse à laquelle le Dashboard envoie le PDF et valeur préremplie sur la page de paiement.
due_datestring (date)facultatif
Date égale ou postérieure à invoice_date. La tâche des factures en retard la compare à la date du jour.
payment_terms_daysintegerfacultatif
Définit due_date à ce nombre de jours après aujourd'hui, uniquement en l'absence de due_date.
items[].tax_ratenumberfacultatif
Pourcentage appliqué à cette ligne, de 0 à 100. Il est calculé par ligne, pas par facture.
items[].discount_typeenumfacultatif
percentage ou fixed, associé à items[].discount_value.
items[].discount_valuenumberfacultatif
Montant déduit de cette ligne. Les remises s'appliquent par ligne. L'API n'en définit aucune au niveau de la facture.
document_typeenumfacultatifdéfaut : invoice
invoice, quote ou estimate. L'API liste et récupère uniquement les factures.
is_recurringbooleanfacultatif
Marque le document comme récurrent. Lisez la section sur les factures récurrentes avant de vous y fier.
notesstringfacultatif
Texte libre sous les lignes, limité à 5 000 caractères. terms 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.

Réponse · 201 Created
{
"code": 201,
"status": "Created",
"message": "Invoice created",
"invoice": {
"id": "inv_LRQqYvlhrgUOE225KMKU",
"invoice_number": "INV-202609-0001",
"document_type": "invoice",
"status": "draft",
"customer_name": "Amina Traoré",
"customer_email": "amina@example.com",
"invoice_date": "2026-09-11",
"due_date": "2026-09-25",
"currency": "XAF",
"subtotal": 450000,
"discount_amount": 0,
"tax_amount": 0,
"total": 450000,
"amount_paid": 0,
"amount_due": 450000,
"is_recurring": false,
"sent_at": null,
"paid_at": null,
"created_at": "2026-09-11T14:00:00Z"
}
}

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

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.

POSThttps://api.wajub.com/invoices/{id}/send

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

URL du client
https://invoice.wajub.com/inv_LRQqYvlhrgUOE225KMKU

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

POSThttps://api.wajub.com/invoices/{id}/mark-paid

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

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énementDéclencheur
invoice.createdUne facture est créée avec draft
invoice.updatedUn champ ou un statut change via l'API, y compris viewed et un paiement
invoice.deletedUne 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.

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.

Que pensez-vous de ce contenu ?