Stablecoins
USDC and EUR-backed stablecoin payments with fiat settlement.
VINR lets customers pay with regulated stablecoins — USDC and EURC — while you keep settling in plain fiat to your bank. You integrate stablecoins through the same payment object as cards; VINR handles the on-chain side, confirmation tracking, and the crypto-to-fiat conversion, so your accounting never has to touch a wallet.
Availability & currenciesAsk
Stablecoin acceptance is opt-in per account. Enable it under Settings → Payment methods in the Dashboard, or contact your account manager for higher-volume limits. Sandbox always has it enabled.
| Stablecoin | Symbol | Networks | Settles to |
|---|---|---|---|
| USD Coin | USDC | Ethereum, Base, Polygon | Your fiat balance (FX applied) |
| Euro Coin | EURC | Ethereum, Base | EUR balance (no FX) |
A customer pays in the stablecoin; you are credited in your account's settlement currency (default EUR). When a customer pays USDC against a EUR-priced payment, VINR converts at the rate quoted at confirmation time and shows both legs on the payment.
Amounts are always set in your pricing currency using minor units — 1000 is €10.00. You never quote prices in tokens. VINR derives the on-chain amount from the live rate and locks it for the duration of the payment window.
How the flow worksAsk
customer picks USDC → VINR quotes token amount + address → customer sends on-chain
→ VINR watches for N confirmations → payment.completed → converted to fiat balance- You create a
paymentas usual and send the customer to the hostedcheckoutUrl. - The customer selects a stablecoin and network. VINR shows a one-time deposit address, the exact token amount, and a countdown.
- The customer sends the funds from any wallet or exchange.
- VINR waits for the required network confirmations (the finality threshold), then converts to fiat and fires
payment.completed.
Unlike cards, there is no separate authorization and capture step — an on-chain payment is captured the moment it reaches finality.
Creating a paymentAsk
Stablecoins use the standard create call. Optionally restrict the offered methods so the checkout shows only what you want.
import { Vinr } from '@vinr/sdk';
const vinr = new Vinr({ secretKey: process.env.VINR_SECRET_KEY });
const payment = await vinr.payments.create({
amount: 5000, // €50.00 in minor units
currency: 'EUR',
description: 'Order #4471',
paymentMethods: ['stablecoin'],
stablecoin: {
accept: ['USDC', 'EURC'], // omit to accept all enabled tokens
networks: ['base', 'ethereum'],
},
returnUrl: 'https://yoursite.com/payment/complete',
metadata: { orderId: '4471' },
});
// payment.id → "pay_3Nf8x2a..."
// payment.status → "pending"
// payment.checkoutUrl → hosted page where the customer picks a token & networkWhile the payment is awaiting funds it stays pending. Once enough confirmations land, the status moves to completed and the conversion details appear under payment.stablecoin:
{
"id": "pay_3Nf8x2a...",
"status": "completed",
"amount": 5000,
"currency": "EUR",
"stablecoin": {
"token": "USDC",
"network": "base",
"tokenAmount": "54.12",
"txHash": "0xab12...e9",
"confirmations": 12,
"fxRate": "0.9239"
}
}Listen for the result with a webhook rather than polling — on-chain timing is variable.
export async function POST(req: Request) {
const payload = await req.text();
const signature = req.headers.get('x-vinr-signature')!;
const event = vinr.webhooks.verify(payload, signature);
if (event.type === 'payment.completed') {
fulfillOrder(event.data.metadata.orderId);
}
return new Response('ok', { status: 200 });
}Settlement & timingAsk
Confirmation time depends on the network: low-fee chains like Base and Polygon typically reach finality in under a minute, while Ethereum mainnet can take several minutes during congestion. VINR only marks a payment completed after the finality threshold, so funds are final — there are no chargebacks on a confirmed stablecoin payment.
After conversion, funds land in your VINR balance in your settlement currency and pay out on your normal settlement schedule alongside card and bank revenue. FX spread and network handling fees are netted and itemized in reconciliation.
Stablecoin payments have an expiry window (default 30 minutes). If the customer underpays, overpays, or sends after the window closes, the payment will not auto-complete — see Limitations below.
Refunds & reversalsAsk
Refunds work through the standard refunds API. Because the original payment was converted to fiat, the refund is calculated in your pricing currency and sent back as stablecoin to a destination address.
const refund = await vinr.refunds.create({
payment: 'pay_3Nf8x2a...',
amount: 5000, // full or partial, in minor units
stablecoin: { destinationAddress: '0xCustomerWallet...' },
});
// refund.id → "re_8Kd2..."
// refund.status → "pending" → "completed" once the on-chain transfer confirmsThe refunded token amount is recomputed at the rate in effect when the refund is issued, so it may differ slightly from the tokens originally received. A destinationAddress is required — VINR cannot reverse an on-chain transfer back to its source automatically.
LimitationsAsk
Next stepsAsk
How payments work
The shared object model behind every rail.
Refunds
Issue full and partial refunds across methods.
Settlement
When and how converted funds reach your bank.
Last updated on