Concepts
The four ideas the library is built on — money is an integer, the gateway is behind one contract, a charge is a promise until the webhook, and the ledger is what makes trusting the webhook safe.
Four ideas carry the whole library. Everything else in these docs is a consequence of one of them.
Money is an integer, in the smallest unit
1990 is R$ 19,90. Never 19.90, never a float, never a string parsed at the boundary. The
PaymentsDriver contract, the billing tables and every diagnostics payload speak the currency's
smallest unit, and the conversion some gateway APIs demand — Asaas and AbacatePay want decimal
reais — lives in exactly one place, inside those drivers. A gateway that already speaks minor units
(Woovi does) converts nothing. See Money.
One contract, many gateways
Eighteen gateways — Stripe, Adyen and PayPal, Mercado Pago and Pagar.me, Pix-native Woovi and
AbacatePay, Razorpay, Mollie and the rest — normalize onto the same PaymentsDriver — charge, refund,
createSubscription, parseWebhook — and onto the same domain types. Your services never see a
gateway SDK, which is what makes adding a gateway a config entry and swapping one a routing change.
A driver also declares what it supports, so sending a card to a Pix-only gateway fails at the
manager with a clear message rather than as an opaque error from someone else's API. See
Routing.
A charge is a promise; the webhook is the money
charge() returns a PENDING payment. Nothing has been paid: the customer still has to scan the QR
code or approve the card. The only thing that turns that promise into revenue is the gateway calling
your endpoint. Granting access on the response from charge() is the single most expensive mistake
in this domain, and the library's shape exists to make the correct path the easy one. See
The payment lifecycle.
The ledger is what makes trusting the webhook safe
"Trust only the webhook" is only workable if a webhook is safe to receive twice — and gateways redeliver constantly: on a timeout, on a non-2xx, from a dashboard replay, from an ops script. Every event is written to an idempotency ledger before any work runs, so a redelivery stops at the door instead of double-granting. That ordering, not the handler, is the guarantee. See Idempotency.
Getting started
Install @adonis-agora/payments, configure a gateway, register webhooks and make your first charge in about five minutes — with no migration to run.
Money
Why every amount is an integer of the smallest currency unit, where the decimal conversion lives, how currency is resolved, and the arithmetic rules that keep a bill from being off by a cent.