Virtex Gateway is a plain REST API. There is no SDK to adopt, no engine plugin to wait for, and nothing that touches your game client — everything happens between your backend and ours. If your server can make an HTTPS request and receive one, you can ship a crypto checkout in an afternoon.
Sign up at virtexgate.virtexpay.com. Registration takes under two minutes, there is no setup fee, and you can build the whole integration before you process a single real payment.
Create an API key in the dashboard and load it from configuration or a secret store on your backend. It authenticates every request you make.
Never put it in a game client. A key shipped inside a Unity, Unreal or mobile build is extractable within minutes, and anyone holding it can create invoices against your account. All gateway calls belong on your server; the client only ever talks to your own API.
The player taps Buy in your store. Your backend creates a pending order in your own database first, then creates a gateway invoice for the fiat amount, carrying your order reference so the webhook can be matched back later.
Send the player to the payment URL you get back. Set a return URL that lands them on a "we are confirming your payment" page in your store — not on a page that assumes success.
POST https://virtexgate.virtexpay.com/api/invoices
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"amount": 4.99,
"currency": "USD",
"order_id": "ord_8412_player_66231",
"description": "1200 Gems - Player 66231",
"return_url": "https://yourgame.com/store/confirming?order=ord_8412",
"callback_url": "https://api.yourgame.com/webhooks/virtexpay"
}
{
"invoice_id": "inv_01HZY6...",
"status": "pending",
"payment_url": "https://virtexgate.virtexpay.com/pay/inv_01HZY6...",
"expires_at": "2026-08-20T14:12:00Z"
}
When the payment confirms on-chain, the gateway POSTs to your
callback_url. This callback — not the browser redirect — is what
you act on. A player can close the tab, lose signal, or never return to your
store, and the payment still needs to be honoured.
POST /webhooks/virtexpay
X-Virtex-Signature: <hmac-sha256 of the raw body>
Content-Type: application/json
{
"invoice_id": "inv_01HZY6...",
"order_id": "ord_8412_player_66231",
"status": "confirmed",
"amount": 4.99,
"currency": "USD",
"paid_currency": "USDT",
"network": "TRC-20",
"tx_hash": "0x9f3c...",
"confirmed_at": "2026-08-20T13:58:41Z"
}
app.post('/webhooks/virtexpay',
express.raw({ type: 'application/json' }),
async (req, res) => {
// 1. Verify the signature against the RAW body, before parsing.
const expected = crypto
.createHmac('sha256', process.env.VIRTEX_WEBHOOK_SECRET)
.update(req.body)
.digest('hex');
const received = req.get('X-Virtex-Signature') || '';
const ok = expected.length === received.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
if (!ok) return res.sendStatus(401);
const event = JSON.parse(req.body);
if (event.status !== 'confirmed') return res.sendStatus(200);
// 2. Load YOUR order and check the amount you expected.
const order = await orders.findByRef(event.order_id);
if (!order || order.amountUsd !== event.amount) return res.sendStatus(409);
// 3. Idempotent grant - a redelivered webhook must not double-credit.
if (order.status === 'paid') return res.sendStatus(200);
await orders.markPaidAndGrant(order.id, event.invoice_id);
// 4. Acknowledge fast. Do heavy work on a queue.
res.sendStatus(200);
});
Four things that bite teams in production, in the order they usually bite:
Payments settle into your gateway balance. Keep them in crypto, or convert and withdraw to fiat from the Payouts section — add a verified bank account or debit card as a destination and request a withdrawal. Card payouts typically land in minutes, bank transfers within hours.
Full detail on off-ramp payouts, or the step-by-step in how to withdraw crypto to a bank account.
Players sometimes send slightly less because their wallet deducted the network fee from the amount, or slightly more by rounding. Decide up front what your store does: credit the difference to the account balance, hold the order for a top-up, or auto-refund. Do not leave it to whoever is on support that day.
A quoted rate is held for a window. If the player pays after it expires, the payment still arrives on-chain — so your handler needs a path for late funds rather than a dead order. Expire the invoice in your own database on the same schedule.
If your endpoint times out, the webhook is retried. Combined with a non-idempotent grant that is how accounts get double-credited. Store processed invoice IDs and short-circuit on a repeat.
Exercise the full loop end to end with a small real payment before opening it to players, including the underpayment and the redelivered-webhook paths. A crypto payment is final — there is no chargeback to undo a bad grant.
Create a free account, generate a key, and build against the API today.