v0.11.0 — July 2026
- Outbound webhooks — register endpoints (
/v1/webhook-endpoints) and Plinth pushes signed, retried events to them. Per-endpointwhsec_secret (rotate anytime),Plinth-SignatureHMAC header, exponential-backoff retries (up to 8), a full delivery log, and manual resend. See Receiving webhooks. - Checkout-funded upgrades —
POST /v1/subscriptions/:id/change-checkoutupgrades a subscription with no card on file by collecting the proration via a Nomba checkout; the plan swaps when payment settles. - Cancel & reactivate —
POST /v1/subscriptions/:id/cancel(policy-driven: end-of-period keeps access until the period end, immediate cuts now) andPOST /v1/subscriptions/:id/reactivateto undo a pending cancel. Subscriptions now exposecancel_at_period_end,canceled_at,scheduled_change, andhas_card. - Dunning recovery via “Update payment” — generate a
checkout-linkfor apast_due/grace/delinquentsubscription to settle the outstanding invoice and recover toactive(emitssubscription.recovered). - One live subscription per plan-group (default) — creating a duplicate returns
409 customer_already_subscribedwith the existing id. Opt out withallow_multiple_subscriptions: true.
v0.10.0 — July 2026
- Plan
lookup_key(required) — every plan now carries a stable handle (e.g.pro_monthly) you reference instead of its UUID.GET /v1/plansreturns it; unique per tenant. Your app no longer hardcodes environment-specific plan ids. - Price immutability guardrail —
PATCH /v1/plans/:idnow rejectsamount_minor/ interval changes once a plan has subscribers (400 plan_immutable), preventing accidental silent re-pricing. Name, lookup_key, trial days, and archive status stay editable. - Archive-or-delete —
DELETE /v1/plans/:idarchives a plan that has subscribers (active: false— existing subscribers keep billing, history preserved) and hard-deletes one that was never subscribed. The response tells you which happened. - Active-only plan list —
GET /v1/plansreturns active plans by default; passinclude_archived=trueto include archived ones.
v0.9.0 — June 2026
- Arrears billing mode — set
billing_mode: "arrears"on a subscription to invoice at end of period instead of start. Useful for usage-based and enterprise contract billing. - Entitlements API —
GET /v1/customers/:id/entitlementsreturns a singlehas_accessboolean,tier, andsubscription_state. No more parsing state machines in your app. - Postpaid / Arrears preset — a new billing preset combining arrears mode, 14-day grace, and lenient dunning. Apply with
preset: "postpaid". - Debt cap (
max_debt_minor) — a new TenantPolicy knob that caps how much outstanding balance a customer can accumulate before access is cut, regardless of grace settings.
v0.8.0 — May 2026
- Virtual account provisioning —
POST /v1/customers/:id/virtual-accountgives each customer a dedicated NUBAN account number at Nomba MFB. - Inbound transfer reconciliation — exact match, partial payment, overpayment (surplus to balance), and suspense queue for unmatched transfers. Webhooks for each case:
transfer.matched,transfer.partial,transfer.suspense. - Dunning engine — built-in retry schedule (days +1, +3, +7, +14) with payday-aware adjustment. Hard decline codes skip straight to grace. Configurable via TenantPolicy.
- Five billing presets — SaaS-Standard, Lenient, Strict, Transfer-First, Postpaid. Apply with
POST /v1/tenant/apply-preset. - Plan change with proration —
POST /v1/subscriptions/:id/preview-changeshows the maths before you commit. Per-second kobo proration with half-up rounding. Immediate or deferred strategies. - Grace period tracking —
grace_expires_atfield on subscription status.subscription.graceevent fires when grace begins.