Every subsystem billing needs, built for the failure mode that costs a team real money. Composable behind a single, versioned interface.
Flat, tiered, volume, and stair-step pricing on one model. Upgrade, downgrade, pause, and resume mid-cycle with proration that reconciles.
subscription.update()proration: credit + debiteffective: now | period_end→ invoice.draft
Ingest raw events over the API, deduped on an idempotency key. Aggregate by sum, max, or unique count inside a locked period, then rate into invoices.
POST /api/v1/usage{ customer_id, records: [{ price_id, quantity, action }] }→ 201 deduped · period-locked→ usage.recorded
Every cent is a double-entry journal in minor units, so debits equal credits on every write. Settlements reconcile against the processor one to one.
journal: DR cash / CR ARreconcile == gatewayrecognize revenue→ ledger.posted
The entire payment edge sits behind adapters. Pick a gateway per tenant. Charge, clear 3DS, retry soft declines, normalize webhooks.
gateway → stripe | adyen | braintree | gopaycharge · 3ds · retrywebhook → normalized→ payment.succeeded
Scheduled payouts, gateway-neutral. Hold, release, and reverse with the same ledger discipline as inbound money.
payout.create(destination)hold → releasescreen → clear→ payout.paid
Configurable retry schedules, fixed or exponential, with a past-due state machine that stops charging when it should. Test and live never mix.
retry: fixed | exponentialper-strategy schedulepast_due → canceled→ recovered | churned