Quick Start
Add two lines to your HTML. The widget handles wallet connection, chain selection, transaction signing, and cross-chain bridging automatically.
<script async src="https://checkout.fivo.finance/v1/fivo.js"></script>
<fivo-button
merchant-id="YOUR_MERCHANT_ID"
amount="29.99"
currency="USDC">
</fivo-button>Merchant ID
fivo_live_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxPayment Modes
Fixed Amount
For products, invoices, subscriptions. Set the attribute and the customer can only pay that exact price.amount
Variable Amount
For donations, tips, pay-what-you-want. Omit the attribute and the customer enters how much they want to pay.amount
Fixed Amount
Set the price and the system verifies the exact amount on blockchain. Amounts must be between 0.01 and 1,000,000.
<script async src="https://checkout.fivo.finance/v1/fivo.js"></script>
<!-- Product: $49.99 USDC -->
<fivo-button
merchant-id="YOUR_MERCHANT_ID"
amount="49.99"
currency="USDC">
</fivo-button>Use Cases
- E-commerce product checkout
- SaaS subscription payments
- Service invoices
- Event tickets
Variable Amount
Omit the attribute. The widget shows an input field where the customer types how much to pay.amount
<script async src="https://checkout.fivo.finance/v1/fivo.js"></script>
<!-- Donation: customer chooses amount -->
<fivo-button
merchant-id="YOUR_MERCHANT_ID"
currency="USDC">
</fivo-button>Amount Limits
Use Cases
- Donations and fundraising
- Tips for content creators
- Pay-what-you-want pricing
- Crowdfunding contributions
Attributes
The element accepts the following attributes:<fivo-button>
fivo-button Attributes
merchant-idstringRequiredYour Merchant ID (format: fivo_live_UUID)
amountstringOptionalFixed payment amount (0.01 - 1,000,000). Omit for variable mode.
currencystringOptional"USDC" or "EURC". Defaults to "USDC".
wallet-idstringOptionalSpecific wallet UUID for multi-wallet merchants. Omit to use your default wallet.
data-amount-fromstringOptionalCSS selector of element containing cart total. Amount is read at click time.
data-referencestringOptionalYour internal reference (order ID, invoice number, etc.). Max 255 chars.
data-descriptionstringOptionalPayment description shown in dashboard. Max 500 chars.
data-metadatastringOptionalJSON string with custom key-value pairs. Max 10KB.
| Name | Type | Required | Description |
|---|---|---|---|
merchant-id | string | Required | Your Merchant ID (format: fivo_live_UUID) |
amount | string | Optional | Fixed payment amount (0.01 - 1,000,000). Omit for variable mode. |
currency | string | Optional | "USDC" or "EURC". Defaults to "USDC". |
wallet-id | string | Optional | Specific wallet UUID for multi-wallet merchants. Omit to use your default wallet. |
data-amount-from | string | Optional | CSS selector of element containing cart total. Amount is read at click time. |
data-reference | string | Optional | Your internal reference (order ID, invoice number, etc.). Max 255 chars. |
data-description | string | Optional | Payment description shown in dashboard. Max 500 chars. |
data-metadata | string | Optional | JSON string with custom key-value pairs. Max 10KB. |
Dynamic Attributes
el.setAttribute('amount', '59.99')Events
The button dispatches custom DOM events you can listen to. All event data is available in .e.detail
fivo:payment-successData: txHash, amount, token, chainId
Payment confirmed on blockchain
fivo:payment-errorData: error
Payment failed or was rejected
fivo:payment-trackingData: paymentId, status, step
Cross-chain transfer progress update
| Event | Data | When |
|---|---|---|
fivo:payment-success | txHash, amount, token, chainId | Payment confirmed on blockchain |
fivo:payment-error | error | Payment failed or was rejected |
fivo:payment-tracking | paymentId, status, step | Cross-chain transfer progress update |
<fivo-button
id="pay-btn"
merchant-id="YOUR_MERCHANT_ID"
amount="25.00"
currency="USDC">
</fivo-button>
<script>
const btn = document.getElementById('pay-btn');
btn.addEventListener('fivo:payment-success', (e) => {
console.log('TX hash:', e.detail.txHash);
console.log('Amount:', e.detail.amount, e.detail.token);
console.log('Chain ID:', e.detail.chainId);
window.location.href = '/thank-you?tx=' + e.detail.txHash;
});
btn.addEventListener('fivo:payment-error', (e) => {
console.error('Payment failed:', e.detail.error);
});
btn.addEventListener('fivo:payment-tracking', (e) => {
// Only fires for cross-chain (CCTP) payments
console.log('Step:', e.detail.step, 'Status:', e.detail.status);
});
</script>Dynamic Cart
Paste this button inside your cart. It automatically reads the total from your page when the customer clicks. If it doesn't pick up the total, change to match your cart total element's ID.#cartTotal
<script async src="https://checkout.fivo.finance/v1/fivo.js"></script>
<!-- Replace #cartTotal with YOUR cart total element's ID -->
<fivo-button
merchant-id="YOUR_MERCHANT_ID"
data-amount-from="#cartTotal"
currency="USDC">
</fivo-button>Not picking up the total?
id="something"#somethingdata-amount-fromAdvanced: manual control
If you need full programmatic control (e.g. the total isn't visible on the page), you can update the amount attribute directly with JavaScript:
<fivo-button
id="checkout-btn"
merchant-id="YOUR_MERCHANT_ID"
currency="USDC">
</fivo-button>
<script>
// Update when cart changes
function updateCheckout(total) {
document.getElementById('checkout-btn')
.setAttribute('amount', total.toFixed(2));
}
// Redirect after payment
document.getElementById('checkout-btn')
.addEventListener('fivo:payment-success', (e) => {
window.location.href = '/thank-you?tx=' + e.detail.txHash;
});
</script>E-commerce with order management?
Multiple Products
Load the script once, then add as many buttons as you need. Each works independently.
<script async src="https://checkout.fivo.finance/v1/fivo.js"></script>
<!-- Product A -->
<fivo-button merchant-id="YOUR_MERCHANT_ID" amount="19.99" currency="USDC"></fivo-button>
<!-- Product B -->
<fivo-button merchant-id="YOUR_MERCHANT_ID" amount="49.99" currency="USDC"></fivo-button>
<!-- Donation (variable) -->
<fivo-button merchant-id="YOUR_MERCHANT_ID" currency="EURC"></fivo-button>Direct Checkout Link
You can also link directly to the checkout page without embedding the widget. Useful for email invoices, social media links, or QR codes.
https://checkout.fivo.finance?merchant=YOUR_MERCHANT_ID&amount=49.99¤cy=USDCURL Parameters
merchantstringRequiredYour Merchant ID
amountstringOptionalFixed amount. Omit for variable mode.
currencystringOptional"USDC" or "EURC". Defaults to "USDC".
walletIdstringOptionalSpecific wallet UUID for multi-wallet merchants.
referencestringOptionalYour internal reference (order ID, etc.).
descriptionstringOptionalPayment description.
metadatastringOptionalURL-encoded JSON string with custom data.
| Name | Type | Required | Description |
|---|---|---|---|
merchant | string | Required | Your Merchant ID |
amount | string | Optional | Fixed amount. Omit for variable mode. |
currency | string | Optional | "USDC" or "EURC". Defaults to "USDC". |
walletId | string | Optional | Specific wallet UUID for multi-wallet merchants. |
reference | string | Optional | Your internal reference (order ID, etc.). |
description | string | Optional | Payment description. |
metadata | string | Optional | URL-encoded JSON string with custom data. |
<a href="https://checkout.fivo.finance?merchant=YOUR_MERCHANT_ID&amount=150.00¤cy=USDC">
Pay Invoice #1234, $150.00 USDC
</a>Checkout Sessions (Redirect Mode)
For server-side integrations, you can create a checkout session via the API and redirect your customer to a Fivo-hosted payment page. After payment, the customer is redirected back to your site. This is similar to Stripe Checkout.
Server-Side Integration
How it works
Your server creates a session
Call POST /checkout/sessions with the amount, currency, and a return URL.
Redirect the customer
Use the returned URL to redirect your customer to the Fivo checkout page.
Customer pays
The customer connects their wallet and completes the payment on the hosted page.
Customer returns to your site
After payment, the customer is redirected to your return_url with the session ID.
Verify payment on your server
Call GET /checkout/sessions/:id to confirm the payment status before fulfilling the order.
1. Create a session (server-side)
const response = await fetch(`https://api.fivo.finance/checkout/sessions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.FIVO_API_KEY,
},
body: JSON.stringify({
amount: '49.99',
currency: 'USDC',
return_url: 'https://yoursite.com/success',
cancel_url: 'https://yoursite.com/cancel',
metadata: { order_id: 'order_123' },
expires_in: 1800, // 30 minutes (default)
}),
});
const { data } = await response.json();
// data.id → "cs_live_xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
// data.url → "https://checkout.fivo.finance?session=cs_live_..."
// data.expires_at → "2026-02-18T11:00:00.000Z"
// After payment, the customer is redirected to:
// https://yoursite.com/success?session_id=cs_live_...2. Redirect the customer
// Express.js example
app.post('/create-checkout', async (req, res) => {
const session = await createCheckoutSession(req.body);
res.redirect(303, session.url);
});3. Verify payment on return
// When the customer lands on your return_url
app.get('/success', async (req, res) => {
const sessionId = req.query.session_id;
const response = await fetch(
`https://api.fivo.finance/checkout/sessions/${sessionId}`,
{ headers: { 'X-API-Key': process.env.FIVO_API_KEY } }
);
const { data } = await response.json();
if (data.status === 'complete' && data.payment) {
// Payment confirmed: fulfill the order
console.log('Payment ID:', data.payment.id);
console.log('TX Hash:', data.payment.tx_hash);
console.log('Amount:', data.payment.amount, data.currency);
} else {
// Payment not yet confirmed: show a waiting state
console.log('Session status:', data.status);
}
});POST /checkout/sessions: Parameters
amountstring | numberOptionalPayment amount (0.01 - 1,000,000). Omit for variable amount.
currencystringOptional"USDC" or "EURC". Defaults to "USDC".
return_urlstringRequiredURL to redirect the customer after payment. Must be HTTPS in production.
cancel_urlstringOptionalURL to redirect if the customer cancels. Must be HTTPS in production.
metadataobjectOptionalUp to 5 key-value pairs for your internal reference (e.g. order ID).
expires_innumberOptionalSession lifetime in seconds (60 - 86400). Defaults to 1800 (30 min).
| Name | Type | Required | Description |
|---|---|---|---|
amount | string | number | Optional | Payment amount (0.01 - 1,000,000). Omit for variable amount. |
currency | string | Optional | "USDC" or "EURC". Defaults to "USDC". |
return_url | string | Required | URL to redirect the customer after payment. Must be HTTPS in production. |
cancel_url | string | Optional | URL to redirect if the customer cancels. Must be HTTPS in production. |
metadata | object | Optional | Up to 5 key-value pairs for your internal reference (e.g. order ID). |
expires_in | number | Optional | Session lifetime in seconds (60 - 86400). Defaults to 1800 (30 min). |
Supported Currencies & Chains
| Currency | Code | Chains |
|---|---|---|
| USD Coin | USDC | All 9 chains |
| Euro Coin | EURC | Ethereum, Avalanche, Base |
| Blockchain | Tokens |
|---|---|
| Ethereum | USDC, EURC |
| Polygon | USDC |
| Avalanche | USDC, EURC |
| Arbitrum | USDC |
| Base | USDC, EURC |
| Optimism | USDC |
| Linea | USDC |
| Unichain | USDC |
| Sonic | USDC |
Customers can pay from any chain. If their chain differs from your wallet's chain, USDC payments are automatically bridged via Circle CCTP (typically 1-2 minutes). EURC is same-chain only and does not support cross-chain transfers.
How It Works
Customer clicks the button
A checkout overlay opens on top of your page. Your site stays loaded underneath.
Customer connects wallet
Supports MetaMask, Coinbase Wallet, WalletConnect, and other popular wallets.
Customer selects chain and pays
The widget scans supported chains for USDC (9 chains) or EURC (3 chains) balances and shows available options.
You receive the funds
Same-chain payments are instant. Cross-chain USDC payments arrive in 1-2 minutes via CCTP. EURC is same-chain only.
Customer Email & Receipts
Every payment requires the customer to enter their email address before paying. The widget handles this automatically. A required email field is shown before the wallet connection step.
For customers
After payment, the customer receives a receipt email with their Payment ID, amount, merchant name, and blockchain transaction link.
For merchants
You can see customer emails in your Transactions page and search refunds by email instead of Payment ID.
Order Tracking
Use optional attributes to link payments to your internal systems. These are passed through to webhooks and visible in your dashboard.
<fivo-button
merchant-id="YOUR_MERCHANT_ID"
amount="49.99"
currency="USDC"
data-reference="ORD-2024-001"
data-description="Pro Plan - Monthly"
data-metadata='{"product_id": "plan_pro", "customer_name": "John"}'>
</fivo-button>Order Tracking Attributes
data-referencestringOptionalYour order/invoice ID. Visible in dashboard and webhooks. Max 255 chars.
data-descriptionstringOptionalPayment description. Visible in dashboard. Max 500 chars.
data-metadatastringOptionalJSON string with any custom data. Included in webhooks. Max 10KB.
| Name | Type | Required | Description |
|---|---|---|---|
data-reference | string | Optional | Your order/invoice ID. Visible in dashboard and webhooks. Max 255 chars. |
data-description | string | Optional | Payment description. Visible in dashboard. Max 500 chars. |
data-metadata | string | Optional | JSON string with any custom data. Included in webhooks. Max 10KB. |
These are optional
Good to Know
Lightweight
~7KB script, loads async. Won't slow your site.
Isolated styles
Uses Shadow DOM. Your CSS won't break it.
Fraud protection
Fixed amounts are verified on blockchain.
9 blockchains
USDC on all 9 chains with auto-bridging via CCTP. EURC on 3 chains (same-chain only).
Need more control?
Use for server-side redirect flows, or check out the API integration guide for webhooks and programmatic payment queries.Checkout Sessions