Everything you need to integrate crypto payment infrastructure into your website.
Accepting crypto payments with RevionPay is completed in 3 steps:
Create an API Key
Go to the Settings page and create an API key. The key is shown only once — store it securely.
Create a Payment
Use your API key to send a request to the POST /api/v1/payments endpoint to create a payment.
Receive the Result via Webhook
Set up a webhook URL in Settings to receive instant payment status updates.
Base URL
https://www.revionpay.com/api/v1All payment API requests are authenticated using the x-api-key header. You can create your API key from the Settings page.
Important Security Notes
Example request:
curl -X POST https://www.revionpay.com/api/v1/payments \
-H "Content-Type: application/json" \
-H "x-api-key: pk_YOUR_API_KEY_HERE" \
-d '{"amount": "29.99", "network": "BTC", "fiatCurrency": "USD"}'RevionPay supports 12 cryptocurrencies across multiple blockchains. Use the network value when creating payments.
| Network Value | Coin | Blockchain | Type |
|---|---|---|---|
| BTC | Bitcoin | Bitcoin | Native |
| ETH | Ether | Ethereum | Native |
| LTC | Litecoin | Litecoin | Native |
| DOGE | Dogecoin | Dogecoin | Native |
| TRX | TRX | Tron | Native |
| BNB | BNB | BNB Chain | Native |
| USDT | Tether (USDT) | Tron | TRC-20 Token |
| USDC | USD Coin (USDC) | Tron | TRC-20 Token |
| ETH_USDT | Tether (USDT) | Ethereum | ERC-20 Token |
| ETH_USDC | USD Coin (USDC) | Ethereum | ERC-20 Token |
| BNB_USDT | Tether (USDT) | BNB Chain | BEP-20 Token |
| BNB_USDC | USD Coin (USDC) | BNB Chain | BEP-20 Token |
Stablecoins on Multiple Chains
/api/v1/paymentsCreate a new paymentRequest Body Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
| amount | string | Required * | Amount in fiat currency (e.g. "29.99") |
| network | string | Required * | Which network/coin to receive payment on. See the network table below. |
| currency | string | Optional | Display label for the coin (e.g. "BTC", "USDT"). Defaults to the network value. Only needed if you want a custom label. |
| fiatCurrency | string | Optional | Fiat currency code (default: "USD") |
| orderId | string | Optional | Your system's order ID |
| description | string | Optional | Payment description |
| metadata | object | Optional | Extra data (JSON object) |
How it works
network vs currency
The network field determines which blockchain and coin is used for the payment. The currency field is just a display label.
For example, to accept USDT on the Ethereum network, use network: "ETH_USDT". For USDT on Tron, use network: "USDT". See the full list in Supported Networks.
Example Request (Bitcoin):
{
"amount": "29.99",
"network": "BTC",
"fiatCurrency": "USD",
"orderId": "order-456",
"description": "Premium subscription - 1 month",
"metadata": {
"customerId": "cust_123",
"plan": "premium"
}
}Example Request (USDT on Tron):
{
"amount": "100.00",
"network": "USDT",
"fiatCurrency": "USD",
"orderId": "order-789"
}Example Request (USDC on Ethereum):
{
"amount": "500.00",
"network": "ETH_USDC",
"fiatCurrency": "USD",
"orderId": "order-101"
}Common Mistake
currency field to select which coin to receive. The network field is required and determines the coin and blockchain. If you omit network, the request will be rejected with a 400 error.Example Response:
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "PENDING",
"paymentUrl": "https://www.revionpay.com/pay/a1b2c3d4...",
"walletAddress": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"cryptoAmount": "0.00034521",
"exchangeRate": "86850.00",
"grossAmount": "0.00034521",
"feePercent": "1.0000",
"platformFee": "0.00000345",
"netAmount": "0.00034176",
"createdAt": "2026-03-07T18:00:00.000Z"
}Key Response Fields
paymentUrl — Redirect your customer to this URL to show wallet address and QR codewalletAddress — The crypto wallet address the customer pays tocryptoAmount — The exact amount to be paid in cryptoid — Save this ID for payment trackingplatformFee — Platform commission takennetAmount — Net amount you receive/api/v1/payments/:idGet payment details/api/v1/paymentsList payments (paginated)Query Parameters (for listing):
| Parameter | Type | Required | Description |
|---|---|---|---|
| page | number | Optional | Page number (default: 1) |
| limit | number | Optional | Items per page (default: 20, max: 100) |
| status | string | Optional | Filter by status |
| network | string | Optional | Filter by network |
Payment Statuses:
Payment detail example:
curl https://www.revionpay.com/api/v1/payments/PAYMENT_ID \
-H "x-api-key: pk_YOUR_API_KEY_HERE"Polling for Status Updates
GET /api/v1/payments/:id to check if a payment status has changed. This is useful if you don't have a webhook URL configured, or as a fallback alongside webhooks. We recommend polling every 10-30 seconds while a payment is in PENDING or PROCESSING state.When a payment status changes, an automatic notification is sent to your system. Configure your webhook URL from the Settings page. Webhooks are optional — you can also poll GET /api/v1/payments/:id to check payment status.
Setup:
https://yoursite.com/api/webhook)Webhook Payload Example:
{
"event": "payment.updated",
"paymentId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "SETTLED",
"grossAmount": "0.00100000",
"netAmount": "0.00099000",
"currency": "BTC",
"orderId": "order-456"
}HMAC Signature Verification:
Each webhook request includes an x-webhook-signature header. Use this to verify the webhook is genuinely from RevionPay.
// Node.js - Webhook verification example
const crypto = require('crypto');
function verifyWebhook(req) {
const signature = req.headers['x-webhook-signature'];
const body = JSON.stringify(req.body);
// webhookSecret is auto-generated when you create an API key
// You can view it on the Settings page
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(body)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
// Express.js example
app.post('/api/webhook', (req, res) => {
if (!verifyWebhook(req)) {
return res.status(401).send('Invalid signature');
}
const { event, paymentId, status, orderId } = req.body;
if (status === 'SETTLED') {
// Payment confirmed! Activate product/service
console.log('Payment settled:', paymentId, orderId);
}
// Must return 200, otherwise the webhook will be retried
res.status(200).send('OK');
});Retry Policy
If a webhook fails (non-200 response or timeout), it is retried up to 5 times:
30s → 2min → 10min → 1hr → 6hr
On error, the API returns a JSON response in this format:
{
"statusCode": 401,
"message": "Invalid API key",
"error": "Unauthorized"
}HTTP Status Codes:
| Code | Meaning | Solution |
|---|---|---|
| 400 | Bad Request | Check request body parameters |
| 401 | Unauthorized | Check your API key — it must be valid and active |
| 403 | Forbidden | Your account is not active — contact admin |
| 404 | Not Found | Endpoint or resource not found |
| 429 | Rate Limited | Too many requests — burst: 20/min per endpoint, overall: 100/min |
| 500 | Server Error | Server error — retry or contact support |
Rate Limiting
API requests are subject to two rate limits:
If you exceed either limit, you will receive a 429 Too Many Requests response. Wait and retry.
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
const REVIONPAY_URL = 'https://www.revionpay.com/api/v1';
const API_KEY = process.env.REVIONPAY_API_KEY;
const WEBHOOK_SECRET = process.env.REVIONPAY_WEBHOOK_SECRET;
// Create payment
app.post('/checkout', async (req, res) => {
// network comes from frontend: 'BTC', 'ETH', 'USDT', 'ETH_USDT', etc.
const { orderId, amount, network, description } = req.body;
const response = await fetch(REVIONPAY_URL + '/payments', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': API_KEY,
},
body: JSON.stringify({
amount: amount,
network: network, // Required! e.g. 'BTC', 'USDT', 'ETH_USDC'
fiatCurrency: 'USD',
orderId: orderId,
description: description,
}),
});
const payment = await response.json();
if (!response.ok) {
return res.status(400).json({ error: payment.message });
}
// Return payment URL to frontend — redirect customer there
res.json({
paymentId: payment.id,
paymentUrl: payment.paymentUrl,
});
});
// Webhook handler
app.post('/webhook/revionpay', (req, res) => {
// 1. Signature verification
const signature = req.headers['x-webhook-signature'];
const body = JSON.stringify(req.body);
const expected = 'sha256=' + crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(body)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
return res.status(401).send('Invalid signature');
}
// 2. Handle payment status
const { paymentId, status, orderId } = req.body;
switch (status) {
case 'SETTLED':
console.log('Payment completed!', orderId);
await db.orders.update({ where: { id: orderId }, data: { status: 'paid' } });
await sendConfirmationEmail(orderId);
break;
case 'EXPIRED':
console.log('Payment expired', orderId);
await db.orders.update({ where: { id: orderId }, data: { status: 'cancelled' } });
break;
case 'PROCESSING':
console.log('Partial payment received', orderId);
break;
}
res.status(200).send('OK');
});
app.listen(4000, () => console.log('Server running on :4000'));import requests
import hmac
import hashlib
from flask import Flask, request, jsonify
app = Flask(__name__)
REVIONPAY_URL = 'https://www.revionpay.com/api/v1'
API_KEY = 'pk_YOUR_API_KEY_HERE'
WEBHOOK_SECRET = 'whsec_YOUR_WEBHOOK_SECRET'
@app.route('/checkout', methods=['POST'])
def create_checkout():
data = request.json
response = requests.post(
f'{REVIONPAY_URL}/payments',
json={
'amount': data['amount'],
'network': data['network'], # Required! e.g. 'BTC', 'USDT', 'ETH_USDC'
'fiatCurrency': 'USD',
'orderId': data['orderId'],
'description': data.get('description', ''),
},
headers={
'Content-Type': 'application/json',
'x-api-key': API_KEY,
}
)
payment = response.json()
if response.status_code != 201:
return jsonify({'error': payment.get('message')}), 400
return jsonify({
'paymentId': payment['id'],
'paymentUrl': payment['paymentUrl'],
})
@app.route('/webhook/revionpay', methods=['POST'])
def handle_webhook():
# Signature verification
signature = request.headers.get('x-webhook-signature', '')
body = request.get_data(as_text=True)
expected = 'sha256=' + hmac.new(
WEBHOOK_SECRET.encode(),
body.encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
return 'Invalid signature', 401
data = request.json
status = data['status']
order_id = data.get('orderId')
if status == 'SETTLED':
print(f'Payment completed: {order_id}')
db.execute('UPDATE orders SET status = %s WHERE id = %s', ('paid', order_id))
return 'OK', 200
if __name__ == '__main__':
app.run(port=4000)<?php
// Create payment
function createPayment($orderId, $amount, $network, $description) {
$apiKey = getenv('REVIONPAY_API_KEY');
$url = 'https://www.revionpay.com/api/v1/payments';
$data = json_encode([
'amount' => $amount,
'network' => $network, // Required! e.g. 'BTC', 'USDT', 'ETH_USDC'
'fiatCurrency' => 'USD',
'orderId' => $orderId,
'description' => $description,
]);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $data,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'x-api-key: ' . $apiKey,
],
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
// Webhook handler (webhook.php)
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$body = file_get_contents('php://input');
$secret = getenv('REVIONPAY_WEBHOOK_SECRET');
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('Invalid signature');
}
$data = json_decode($body, true);
if ($data['status'] === 'SETTLED') {
$orderId = $data['orderId'];
$pdo->prepare('UPDATE orders SET status = ? WHERE id = ?')
->execute(['paid', $orderId]);
}
http_response_code(200);
echo 'OK';<!-- Checkout button example -->
<select id="coin-select">
<option value="BTC">Bitcoin</option>
<option value="ETH">Ethereum</option>
<option value="USDT">USDT (TRC-20)</option>
<option value="ETH_USDT">USDT (ERC-20)</option>
<option value="BNB_USDT">USDT (BEP-20)</option>
<option value="USDC">USDC (TRC-20)</option>
</select>
<button id="pay-btn" onclick="startPayment()">
Pay Now
</button>
<script>
async function startPayment() {
const btn = document.getElementById('pay-btn');
const network = document.getElementById('coin-select').value;
btn.disabled = true;
btn.textContent = 'Loading...';
try {
// Send request to YOUR backend (which calls RevionPay API)
const res = await fetch('/checkout', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderId: 'order-789',
amount: '49.99',
network: network, // Pass selected coin to your backend
description: 'Order #789',
}),
});
const data = await res.json();
if (data.paymentUrl) {
// Customer is redirected to the crypto payment page
window.location.href = data.paymentUrl;
} else {
alert('Error: ' + (data.error || 'Unknown error'));
}
} catch (err) {
alert('Connection error');
} finally {
btn.disabled = false;
btn.textContent = 'Pay with Bitcoin';
}
}
</script>Customer → Clicks "Pay with Crypto" on your site
↓
Your Backend → POST /api/v1/payments (with x-api-key)
↓
RevionPay → Generates wallet address, returns paymentUrl + walletAddress
↓
Your Backend → Returns paymentUrl to frontend
↓
Customer → Scans QR code or sends crypto to wallet address on payment page
↓
RevionPay → Detects payment, sends webhook
↓
Your Backend → Receives webhook, verifies signature, confirms order