Two ways to get a token
The SDK behaves identically once a token exists. What differs is who calls POST /api/v1/checkout/init — and therefore where the merchant API key lives.
| Backend-minted | SDK-minted | |
|---|---|---|
| You pass | widgetToken | order + customerEmail |
Calls /checkout/init | Your server | The app |
| Merchant API key lives | On your server | In the app binary |
| Needs a backend | Yes | No |
| Fit for a public consumer app | Yes | No — see below |
The merchant API key is a merchant-wide credential. Anything holding it can mint tokens for any amount, create checkouts, and read every payment of the merchant — including other shoppers' payment history from their email alone, via
GET /api/v1/payments?customer_email=…. An app binary is not a secret store: it can be unzipped, and the header read off the wire on a device the reader controls. Compiling the key into a shipped app publishes it, and rotating it afterwards breaks every installed copy until users update.Choose SDK-minting for an internal or single-tenant app, a prototype, or a build whose key is restricted server-side. For a public consumer app, mint on a backend and pass
widgetToken.
Supply exactly one of widgetToken or order — the widget asserts on both or neither, and customerEmail is required with order because a mint without one is rejected. Only /checkout/init ever carries the credentials: the lookup, the checkout and the status poll are authenticated by the widget token and the payment client token, so the key never travels on them. RezolvePayCardPaymentController.activeWidgetToken reports whichever token the checkout is actually running on.
A widget token is single-use either way, and only one may be ACTIVE per merchant/order pair — so a retry needs a fresh order_id, not a repeat of the spent one.
Backend-minted
// Your server holds the merchant API key and mints the token.
// The app never sees a merchant credential.
RezolvePay.configure(baseUrl: 'https://pay.rezolve.com');
final String widgetToken = await fetchWidgetToken(orderId); // your endpoint
RezolvePayCardForm(
widgetToken: widgetToken,
customerEmail: email,
onSuccess: ..., onFailure: ...,
);SDK-minted
// No backend: the SDK calls /checkout/init itself.
//
// WARNING: merchantApiKey is a MERCHANT-WIDE credential and an app binary
// cannot keep it secret. Anyone who downloads the app can extract it and
// then mint tokens, create checkouts, and read every payment of this
// merchant - including other shoppers' history by email. Use this only
// for an internal/single-tenant app, a prototype, or a restricted key.
RezolvePay.configure(
baseUrl: 'https://pay.rezolve.com',
merchantId: 'acme',
merchantApiKey: '...',
);
RezolvePayCardForm(
// Instead of a token: the SDK mints one for this order on start().
order: const RezolvePayOrder(
amount: 1499, // minor units
currency: 'GBP',
orderId: 'ORD-4421', // fresh per attempt - a token is single use
),
// Required here: a mint without a shopper email is rejected.
customerEmail: email,
onSuccess: ..., onFailure: ...,
);Updated about 4 hours ago

