Skip to main content

v0.11.0 — July 2026

  • Outbound webhooks — register endpoints (/v1/webhook-endpoints) and Plinth pushes signed, retried events to them. Per-endpoint whsec_ secret (rotate anytime), Plinth-Signature HMAC header, exponential-backoff retries (up to 8), a full delivery log, and manual resend. See Receiving webhooks.
  • Checkout-funded upgradesPOST /v1/subscriptions/:id/change-checkout upgrades a subscription with no card on file by collecting the proration via a Nomba checkout; the plan swaps when payment settles.
  • Cancel & reactivatePOST /v1/subscriptions/:id/cancel (policy-driven: end-of-period keeps access until the period end, immediate cuts now) and POST /v1/subscriptions/:id/reactivate to undo a pending cancel. Subscriptions now expose cancel_at_period_end, canceled_at, scheduled_change, and has_card.
  • Dunning recovery via “Update payment” — generate a checkout-link for a past_due/grace/delinquent subscription to settle the outstanding invoice and recover to active (emits subscription.recovered).
  • One live subscription per plan-group (default) — creating a duplicate returns 409 customer_already_subscribed with the existing id. Opt out with allow_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/plans returns it; unique per tenant. Your app no longer hardcodes environment-specific plan ids.
  • Price immutability guardrailPATCH /v1/plans/:id now rejects amount_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-deleteDELETE /v1/plans/:id archives 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 listGET /v1/plans returns active plans by default; pass include_archived=true to 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 APIGET /v1/customers/:id/entitlements returns a single has_access boolean, tier, and subscription_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 provisioningPOST /v1/customers/:id/virtual-account gives 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 prorationPOST /v1/subscriptions/:id/preview-change shows the maths before you commit. Per-second kobo proration with half-up rounding. Immediate or deferred strategies.
  • Grace period trackinggrace_expires_at field on subscription status. subscription.grace event fires when grace begins.