Patterns
A cookbook of the flows this library exists for — Pix and subscriptions per gateway, where business logic lives, metered billing, marketplace splits, recovery, chargebacks, and reading the billing data without the bundled console.
Each page below is a complete flow you can adapt, with the gateway differences shown side by side rather than averaged into a generic example — because the differences are the part that costs you an afternoon.
The two habits every pattern assumes
Set externalReference on everything. It is the string the gateway echoes back, and it is the
only thing tying a confirmation to your own row. A charge created without one produces a webhook your
handler cannot route, and the failure is a silent return. See
The payment lifecycle.
Put business logic in a handler, not next to the charge() call. The charge returns PENDING;
nothing has been paid. Granting anything there gives the product away to whoever starts a checkout
and walks off. See Reacting to payments.
Every example is integer cents
1990 is R$ 19,90. Never a float, never a decimal — see Money.
The patterns
Pix
A one-off Pix charge through Asaas, Woovi or AbacatePay — what each one needs, and what comes back.
Card
A card charge without the number ever reaching your server — tokenize in the browser, then what Stripe and Asaas each do with the token.
Subscriptions
Recurring billing per gateway — trials, tokenized cards, Pix Automático, upgrades and cancellation.
Reacting to payments
The four homes for business logic — the folder, the config, diagnostics, and a durable workflow — and how to choose.
Metered billing
Record usage as it happens, price the period, charge the overage exactly once.
Marketplace splits
Share a charge across wallets with Asaas splits or Woovi subaccounts.
Recovering
Dunning a failed payment, refunding, and reconciling after an outage.
Disputes
The three moments of a chargeback, the deadline that decides it, submitting evidence — and why the decision to fight or refund stays in your code.
Building your own dashboard
The headless data layer behind the console — billingOverview and the store's read API.
Picking a gateway per flow
The routing table is where these decisions land. A common Brazilian setup splits by what each gateway is actually best at:
export default defineConfig({
default: 'asaas',
providers: {
woovi: payments.woovi({ appId: env.get('WOOVI_APP_ID') }),
stripe: payments.stripe({ apiKey: env.get('STRIPE_KEY'), currency: 'brl' }),
asaas: payments.asaas({ apiKey: env.get('ASAAS_API_KEY') }),
},
methods: {
pix: 'woovi', // best Pix rates
credit_card: 'stripe', // best card tooling
boleto: 'asaas',
debit_card: 'asaas',
undefined: 'asaas',
},
})Your services then name the method, never the gateway — so moving Pix from Woovi to Asaas is one line of config. See Routing.
Troubleshooting
The symptoms that actually happen — webhooks returning 400 or 500, handlers that never run, double grants, routing errors, missing invoices, a schema that upgraded halfway — and how to tell the causes apart quickly.
Pix
A one-off Pix charge end to end — the shared shape, then exactly what Asaas, Woovi and AbacatePay each require, what each returns, and the errors each one throws when something is missing.