Subscriptions
Charge a customer on a schedule: a plan, a subscription, renewal invoices and dunning handled by Watenga.
A plan sets the price and interval (daily, weekly, monthly, quarterly, semiannually, annually), with optional trial days, a setup fee, prices in several currencies, tiers or metered usage. A subscription puts a customer on a plan; each period Watenga issues the invoice and collects it (a saved card, or a payment link sent to the customer), retries failed payments and keeps a grace period.
Amounts are always computed by Watenga: preview the next invoice with upcomingInvoice before you change a subscription.
Keys and scopes
subscriptions scope.1. Create a plan
const plan = await watenga.plans.create({ name: 'Pro', amount: '15.00', currency: 'USD', interval: 'monthly', trial_days: 14 });2. Subscribe a customer
The answer is the subscription, with its first invoice and that invoice’s payment_url beside it: send the customer there to pay (and save a card for renewals).
const sub = await watenga.subscriptions.create({ plan_id: plan.id, customer_name: 'Ada Buyer', customer_email: 'ada@example.com' });
console.log(sub.payment_url);3. Pause, resume, cancel
Cancelling ends the subscription at the end of the paid period, or now with immediately.
await watenga.subscriptions.pause(sub.id);
await watenga.subscriptions.resume(sub.id);
await watenga.subscriptions.cancel(sub.id, { immediately: false, reason: 'customer_request' });4. Check what the customer may use
A feature is held while a subscription is active or trialing, or past due inside its grace period. Access ends the moment the subscription or its grace period ends, even before the lifecycle job runs; a plan feature set to false grants nothing.
const { active } = await watenga.billing.checkEntitlement('ada@example.com', 'exports');Test renewals with the test clock
With a test key, move your account’s test clock forward and run the jobs that fall due: renewals, trial ends, dunning, overdue invoices. Live data is never touched. Remove the clock to go back to real time.
curl -X POST https://api.watenga.africa/v1/developer/sandbox/clock/advance \
-H "Authorization: Bearer $WATENGA_SECRET_KEY" \
-H "Watenga-Version: 2026-10-29" \
-H "Content-Type: application/json" \
-d '{"delta_ms":2678400000}'
curl -X POST https://api.watenga.africa/v1/developer/sandbox/clock/tick \
-H "Authorization: Bearer $WATENGA_SECRET_KEY" \
-H "Watenga-Version: 2026-10-29"
curl -X DELETE https://api.watenga.africa/v1/developer/sandbox/clock \
-H "Authorization: Bearer $WATENGA_SECRET_KEY" \
-H "Watenga-Version: 2026-10-29"Webhook events
| Event | When |
|---|---|
billing.subscription.created | A subscription was created |
billing.subscription.activated | The first payment succeeded |
billing.subscription.payment-failed | A renewal payment failed (retries follow) |
billing.subscription.suspended | Unpaid after the grace period |
billing.subscription.updated | Plan, quantity or status changed |
billing.subscription.cancelled | Cancelled |
billing.subscription.expired | Ended |
Each event carries the object in data.object; verify the signature first (Webhooks).
Test it
Use a test secret key (sk_test_…): it never moves money. Pay with the test cards and wallet numbers, and receive the webhooks on your machine with watenga listen --forward-to http://localhost:3000/webhooks (CLI).
Related: Customers · Customer billing page