API Integration Guide
VirtexGate Payment Gateway · REST API · v1
Overview
VirtexGate is a cloud-native crypto payment gateway. Integrate our API to create invoices from your server — VirtexGate calculates the crypto amount, assigns a unique payment address, verifies the payment, and notifies your endpoint via webhook the moment it's confirmed.
Base URL
https://<your-host>/api
Supported Coins
Integration Flow
API Key → Create Invoice → Buyer pays via Checkout → Webhook confirms
POST /invoicesinvoice.paidAuthentication
All integration endpoints use your store's API key. Set it as the X-Api-Key header on every request. Format: vgk_ + base64url(32 bytes). Keys are generated once and shown only once — store yours in an environment variable.
X-Api-Key: vgk_abc123...
Store ID
Every invoice creation request also requires your storeId — the UUID of the store the API key belongs to. This is a deliberate security check: the server validates that the key and the storeId match, preventing a leaked key from being used against a different store.
Where to find it: Gateway Dashboard → Store → the Store ID is displayed on the store overview page. Copy and store it alongside your API key in your environment variables.
Quick Start
Register & sign in
Create your account at the Gateway dashboard. Check your inbox for the verification email and click the confirmation link before logging in.
Create a store
A store holds your wallets, API key, and settings. You can have multiple stores (one per website or product line).
Fill in the store name and optionally set a default currency, invoice expiry, and webhook URL. Save — you'll be taken to the store overview.
Store ID
from the store overview page — you'll need it for API calls.
Add a wallet
A wallet tells VirtexGate which coin(s) you want to accept. Generate a secure wallet directly from the dashboard — one per coin type. Setup takes seconds.
Add one wallet per coin you wish to accept. You can add more later without re-generating the API key.
Generate your API key
The API key authorises your backend to create invoices for this store. It is shown once — copy it immediately into your server's environment variables.
Create an invoice server-side
Call POST /invoices from your backend when a customer checks out. Pass your storeId, amount, and currency.
POST /api/invoices → { id, checkoutUrl, expiresAt }
Redirect the buyer to checkout frontend
Send the buyer to the checkoutUrl returned in step 5. They select a coin, scan the QR code, and pay. Your webhook fires when payment is confirmed.
window.location = invoice.checkoutUrl
Minimal integration (curl)
# Create invoice from your server (steps 5-6)
curl -s -X POST https://your-host/api/invoices \
-H "X-Api-Key: vgk_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"storeId": "YOUR_STORE_ID",
"amount": 25.00,
"fiatCurrency": "USD",
"externalOrderId": "order-42",
"redirectUrl": "https://myshop.com/thank-you"
}'
# Returns:
# { "id": "3fa85f64...", "checkoutUrl": "https://your-host/checkout/3fa85f64...", "expiresAt": "..." }
# Redirect the buyer to checkoutUrl — they scan the QR and pay
Create Invoice
The single server-side call your backend makes. Requires X-Api-Key.
Idempotent retries
Add an Idempotency-Key header to prevent duplicate invoices on network retries. The same key + same body replays the original 201 response. A different body with the same key returns 409.
POST /api/invoices
X-Api-Key: vgk_YOUR_API_KEY
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
Keys are enforced for 24 hours. Omit the header to skip replay protection.
Payment Flow
After you create an invoice, the checkoutUrl in the response is a fully hosted payment page served by VirtexGate. Redirect the buyer there — VirtexGate handles everything: coin selection, QR code generation, confirmation countdown, and post-payment redirect.
What VirtexGate's checkout page handles for you
redirectUrlRedirect to checkout
// After POST /invoices, redirect the buyer:
const invoice = await createInvoice({ amount: 25.00, fiatCurrency: 'USD', ... });
// Option A – full-page redirect (recommended)
window.location.href = invoice.checkoutUrl;
// Option B – open in new tab
window.open(invoice.checkoutUrl, '_blank');
// Option C – embed in an iframe (same-origin only)
// <iframe src="{invoice.checkoutUrl}" width="480" height="620" />
If you need to verify payment status programmatically without waiting for a webhook (e.g. from a background job or an order management page), you can poll this endpoint from your server.
Webhooks
The gateway POSTs to every webhook URL registered under your store whenever an invoice changes state. Add endpoints in Store → Settings → Webhook Endpoints.
Events
Payload
{
"event": "invoice.paid",
"invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"storeId": "9b2e1c3d-8f4a-4b2e-bc4a-1d2e3f4a5b6c",
"status": "Paid",
"amount": 25.00,
"currency": "USD",
"externalOrderId": "order-42",
"orderId": "order-42",
"createdAt": "2026-05-16T10:00:00Z",
"timestamp": 1747390800
}
Signature Verification (required)
Every delivery includes an X-Signature header containing an HMAC-SHA256 of the raw request body. Always verify this before trusting the payload — reject any request whose signature does not match.
HMAC-SHA256
X-Signature: sha256=<lowercase hex>
"sha256=" + hex( HMAC‑SHA256(secret, rawBody) )
Webhook handler examples
const crypto = require('crypto');
const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET; // from Store Settings
// Use express.raw() — req.body must be a Buffer for signature verification
app.post('/webhook/payment', express.raw({ type: 'application/json' }), (req, res) => {
// 1. Verify signature (timing-safe comparison)
const sig = req.headers['x-signature'] ?? '';
const expected = 'sha256=' + crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(req.body)
.digest('hex');
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
return res.sendStatus(401); // reject — do not process
}
// 2. Parse and handle
const { event, invoiceId, externalOrderId } = JSON.parse(req.body);
if (event === 'invoice.paid') {
fulfillOrder(externalOrderId);
}
res.sendStatus(200);
});
crypto.timingSafeEqual, hash_equals, hmac.compare_digest, CryptographicOperations.FixedTimeEquals) — never a plain string equality check.
Always respond 200 OK quickly — the gateway retries up to 3 times with 5 s / 10 s backoff on any non-2xx response or timeout.
Error Reference
All errors follow: {"{ \"error\": \"description\" }"}
| Code | Meaning | Notes |
|---|---|---|
| 400 | Bad Request | Validation failure, malformed JSON |
| 401 | Unauthorized | Missing or invalid API key |
| 403 | Forbidden | Key is valid but not permitted for this store |
| 404 | Not Found | Invoice or resource does not exist |
| 409 | Conflict | Invoice already paid / expired / cancelled — or Idempotency-Key reused with a different payload |
| 422 | Unprocessable | Amount too small, missing field |
| 429 | Too Many Requests | Rate-limit hit. Returns { error, status, timestamp }. Back off and retry. |
| 500 | Server Error | Unexpected failure |
Status Codes
Invoice Status Flow
| Status | Meaning |
|---|---|
| New | Invoice created, no coin selected yet |
| Waiting | Coin selected, payment address shown — awaiting transaction |
| Processing | Transaction detected, waiting for required confirmations |
| Paid | Fully confirmed — fulfil the order |
| Expired | Timer elapsed before payment arrived |
| Underpaid | Less than the required amount was received |
| Overpaid | More than the required amount was received |
Payment (Transaction) Status
| Status | Meaning |
|---|---|
| Pending | Address generated, no transaction seen yet |
| Detected | Payment received, awaiting confirmation |
| Confirmed | Required confirmations reached |
| Expired | Invoice timer elapsed |
Status Response Shape
{
"status": "Processing",
"expiresAt": "2026-05-06T12:30:00Z",
"secondsRemaining": 1543,
"payment": {
"coinType": "BTC",
"amountDue": 0.00032541,
"amountPaid": 0.00032541,
"status": "Detected",
"txId": "4a5e1e4baab89f3a32518a88c31bc87f...",
"confirmations": 1,
"requiredConfirmations": 1,
"address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh"
}
}