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

A secret key, or a restricted key with the subscriptions scope.

1. Create a plan

typescript
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).

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

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

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

bash
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

EventWhen
billing.subscription.createdA subscription was created
billing.subscription.activatedThe first payment succeeded
billing.subscription.payment-failedA renewal payment failed (retries follow)
billing.subscription.suspendedUnpaid after the grace period
billing.subscription.updatedPlan, quantity or status changed
billing.subscription.cancelledCancelled
billing.subscription.expiredEnded

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