Clients, plans, abonnements

Un abonnement relie un client à un plan. Ce guide parcourt les trois objets, puis la vie d’un abonnement. Les exemples utilisent une clé qb_test_sk_….

Clients

curl -X POST https://api.qbill.dev/v1/customers \
  -H "x-api-key: qb_test_sk_…" \
  -H "content-type: application/json" \
  -d '{"name":"Boutique Awa","email":"awa@example.com","country":"CI"}'

Champs : name, email, et en option phone, locale, tax_exempt, country. Le country (code pays à deux lettres) fait choisir le taux de TVA du pays ; tax_exempt: true dispense le client de TVA.

Plans

curl -X POST https://api.qbill.dev/v1/plans \
  -H "x-api-key: qb_test_sk_…" \
  -H "content-type: application/json" \
  -d '{"name":"Pro","pricing_model":"flat_rate","amount_monthly":6000,"trial_days":7}'

Champs : name, pricing_model, et en option description, amount_monthly, amount_annual, trial_days, installment_count, features, limits. Les montants sont en XOF ; il n’y a pas de champ devise.

pricing_model En une ligne
flat_rate Un montant fixe par période.
per_seat Un montant par siège ; le nombre de sièges est la quantity déclarée sur l’abonnement.
hybrid Un montant de base plus une part variable.
metered Facturé selon l’usage déclaré.
tiered Par métrique d’usage : chaque palier d’usage est facturé à son propre prix unitaire, selon les paliers du plan.
volume Par métrique d’usage : le prix du palier atteint par le total s’applique à toutes les unités.
stairstep Par métrique d’usage : un prix forfaitaire par tranche de consommation.
credit Un portefeuille prépayé : le client le recharge (par une facture payée sur Wave), et chaque usage déclaré le débite. Rien n’est facturé à chaque période ; le portail client montre solde et historique.
one_time Un paiement unique.
installment Un paiement en plusieurs fois : une échéance par période, installment_count échéances.

trial_days donne la durée d’essai des abonnements à ce plan. Add-ons. Ce sont des modules payants optionnels, pris dans le catalogue de l’app (/v1/addons) et ajoutés à un abonnement avec une quantité (/v1/subscriptions/:id/addons). Ajout, changement de quantité et retrait sont proratisés comme un changement de plan, et les add-ons comptent dans le MRR. Ils sont refusés sur les plans prépayés, ponctuels et en échéances.

Dépassement. Un composant tarifaire peut inclure un nombre d’unités gratuites (free_units) : l’usage au-delà est facturé au tarif unitaire du composant. Cela vaut pour les plans flat_rate, per_seat, hybrid et metered. L’usage se déclare comme décrit dans Usage.

Abonnements

curl -X POST https://api.qbill.dev/v1/subscriptions \
  -H "x-api-key: qb_test_sk_…" \
  -H "content-type: application/json" \
  -d '{"customer":"<id du client>","plan":"<id du plan>","billing_interval":"monthly","quantity":1}'

Corps : customer, plan, et en option payment_method, billing_interval (monthly ou annual), quantity. Si le plan a des trial_days, l’abonnement démarre en statut trialing.

Statuts : trialing, active, past_due, paused, cancelled.

Changer de plan

curl -X POST https://api.qbill.dev/v1/subscriptions/<id>/change-plan \
  -H "x-api-key: qb_test_sk_…" \
  -H "content-type: application/json" \
  -d '{"plan":"<id du nouveau plan>","effective":"period_end"}'

Corps : plan et/ou quantity, et effective (immediately ou period_end). period_end ne reporte que les baisses de plan. Un changement en cours de période est réglé par un ajustement de prorata, sauf pour les plans installment, one_time et credit, qui ne sont pas proratisés. Pour annuler un changement programmé : DELETE /v1/subscriptions/<id>/pending-change.

Pause, reprise, résiliation

  • POST …/pause avec { "resume_at": "…" } (facultatif) suspend la facturation sans terminer l’abonnement.
  • POST …/resume la reprend.
  • POST …/cancel avec { "reason": "…" } (facultatif) résilie, immédiatement.

Avec le SDK

Le paquet @qbill/node arrive bientôt sur npm ; les appels ci-dessus s’y écrivent :

const sub = await qbill.subscriptions.create({ customer, plan, billing_interval: 'monthly' });
await qbill.subscriptions.changePlan(sub.id, { plan: otherPlan, effective: 'period_end' });
await qbill.subscriptions.pause(sub.id);
await qbill.subscriptions.resume(sub.id);
await qbill.subscriptions.cancel(sub.id, { reason: 'customer_request' });

Pour facturer ensuite, voir Factures et paiements.