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...
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 your store's webhookUrl whenever an invoice changes state. Configure the URL in your store settings on the dashboard.
Events
Payload
{
"event": "invoice.paid",
"invoiceId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"storeId": "9b2e1c3d-8f4a-4b2e-bc4a-1d2e3f4a5b6c",
"status": "Paid",
"amount": 25.00,
"fiatCurrency": "USD",
"externalOrderId": "order-42",
"createdAt": "2026-05-06T10:00:00Z",
"paidAt": "2026-05-06T10:12:44Z"
}
Handler example (Node.js / Express)
app.post('/webhook/payment', express.json(), (req, res) => {
const { event, invoiceId, externalOrderId, status } = req.body;
if (event === 'invoice.paid') {
fulfillOrder(externalOrderId); // release your product/service
}
res.sendStatus(200); // always return 200 to acknowledge
});
Always respond 200 OK quickly. Failed deliveries are retried automatically. The gateway sends these headers with every POST: X-Webhook-Event, X-Invoice-Id, X-Signature.
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"
}
}