Crypto
One catalog method — usdc — lets customers pay from any crypto wallet in USDC, the dollar-pegged stablecoin, on their choice of supported network. You price in your normal currency, and by default you settle in fiat: the stablecoin leg lives entirely inside the flow.
USDC in the catalog
Why one method and one asset: USDC is dollar-pegged (no price risk inside a checkout window), natively issued on multiple networks (cheap, fast transfers), and redeemable 1:1 — which is what makes clean fiat settlement possible. You pass "payment_method": "usdc"; everything network-specific happens on the hosted page.
The customer picks the network there — supported networks include Ethereum, Solana, Polygon, and Base — and pays from whatever wallet they hold: self-custodied or an exchange account. You never see addresses, networks, or gas; the Payment object stays the same shape as an iDEAL payment.
The payment flow
Step by step:
-
Quote & address
The hosted page locks the USDC amount for your
amount/currencyand shows a one-time deposit address (with QR) on the customer's chosen network. One address per payment — that's what ties an incoming transfer topay_8Q2mX4nT1cVbwith no reference field to typo. -
Transfer
The customer sends the exact USDC amount from their wallet. The page watches the network and flips to "detected" when the transfer appears.
-
Finality
When the transfer is final on-chain, the payment moves to
succeededandpayment.succeededfires. Fulfill on the webhook, as always — not on "detected".
Creating a USDC payment
Nothing crypto-specific in the request — price it like any payment:
curl https://api.finscale.dev/v1/payments \
-H "Authorization: Bearer sk_test_51FinscaleDemo…" \
-H "Idempotency-Key: idem_ord_9f21_0716" \
-H "Content-Type: application/json" \
-d '{
"amount": 4900,
"currency": "EUR",
"payment_method": "usdc",
"reference": "ord_9f21_0716",
"customer": { "email": "anna@example.com" },
"return_url": "https://shop.example.com/checkout/return"
}'
{
"id": "pay_8Q2mX4nT1cVb",
"object": "payment",
"amount": 4900,
"currency": "EUR",
"status": "requires_action",
"payment_method": "usdc",
"reference": "ord_9f21_0716",
"next_action": {
"type": "redirect",
"url": "https://pay.finscale.dev/r/8Q2mX4nT"
},
"created_at": "2026-07-16T09:24:31Z",
"livemode": false
}
Networks & finality
- Finality is network-dependent — seconds on fast chains, minutes on others. Finscale marks the payment
succeededonly at finality; a transfer that appears and is then reorganized away never succeeds. - The address is single-use and network-bound. Funds sent to it on the wrong network, or a different token sent to it, are not credited to the payment — recovery is handled case by case from the dashboard.
- Exact-amount matching. The quote pins the USDC amount. Underpayments don't complete the payment: the page prompts for the remainder until the quote window lapses, after which the partial transfer is returned to the sending address.
Settlement: fiat or USDC
Two account-level options, set per merchant:
- Fiat settlement (default). At finality, the USDC converts to your settlement currency and the funds join your unified payout on the standard T+2 schedule — one settlement line, payment id attached, exactly like card volume. Conversion works as described in Multicurrency.
- USDC settlement. Accounts configured for stablecoin payouts keep the USDC leg: funds accumulate as USDC and pay out on-chain instead of by bank transfer. Reports and reconciliation are unchanged.
Refunds — no chargebacks
POST /v1/refunds works as everywhere: full or partial, by payment id. The refund is pushed as a USDC transfer back to the on-chain sending address, and stays pending until that transfer reaches finality — subscribe to refund.succeeded.
Error scenarios
| Scenario | What the API does |
|---|---|
| Quote window lapses unpaid | The payment moves to failed; payment.failed fires. A new checkout gets a fresh quote and address. |
| Underpayment, then lapse | The payment fails and the partial transfer is returned to the sending address automatically. |
| Overpayment | The payment succeeds at the quoted amount and the excess is returned to the sending address. |
| Wrong network or wrong token | Not credited — the transfer doesn't match the payment. Recovery is case-by-case from the dashboard; the hosted page states the network prominently to prevent this. |
| Transfer detected but never final | The payment stays requires_action and eventually fails — succeeded requires finality, full stop. |
Related
- Payment methods overview — families, payload shapes, full catalog
- Multicurrency — presentment vs settlement currency
- Settlement & payouts — where converted funds land
- Reconciliation — id chains across rails, on-chain included
- Method catalog on finscale.dev — regions and currencies