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

BTC ETH USDT/Tron USDT/Polygon

Integration Flow

API Key → Create Invoice → Buyer pays via Checkout → Webhook confirms

Your Server
POST /invoices
checkoutUrl
Buyer pays
Webhook invoice.paid

Authentication

X-Api-Key Store API Key

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...
Where to get it: Gateway Dashboard → Store → Settings → Rotate API Key. The previous key is immediately invalidated on rotation.

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

Phase 1 — Dashboard Setup Do this once in the Gateway UI
1

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.

Sign Up Verify email Log In
2

Create a store

A store holds your wallets, API key, and settings. You can have multiple stores (one per website or product line).

Sidebar → Stores + New Store

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.

After saving, copy the Store ID from the store overview page — you'll need it for API calls.
3

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.

Store → Wallets tab + Add Wallet Select coin type Save
BTC ETH USDT / Tron USDT / Polygon

Add one wallet per coin you wish to accept. You can add more later without re-generating the API key.

4

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.

Store → Settings tab Rotate API Key Copy key
The key is displayed only once. If you close the dialog without copying it, you must rotate again — the old key is immediately invalidated. Store it in an environment variable, never in source code.
VirtexGate_API_KEY=vgk_••••••••••••••••••••••••
Phase 2 — API Integration Add these two calls to your backend
5

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 }

6

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.

Your backend
POST /invoices
checkoutUrl
in response
Redirect buyer
your frontend
VirtexGate checkout UI
coin · QR · payment
Webhook fired
invoice.paid

What VirtexGate's checkout page handles for you

Coin selection (shows only the coins your store has wallets for)
QR code generation and payment address display
Fiat → crypto conversion and amount calculation
Real-time confirmation countdown and status updates
Post-payment redirect to your redirectUrl

Redirect 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" />
Optional Server-side status check

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

invoice.created invoice.waiting invoice.payment_received invoice.payment_settled invoice.processing invoice.paid invoice.overpaid invoice.partially_paid invoice.expired invoice.cancelled invoice.invalid

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.

Algorithm HMAC-SHA256
Header X-Signature: sha256=<lowercase hex>
Key The signing secret shown once when you add the webhook endpoint in the dashboard. If you left the field blank the gateway auto-generated one.
Input The raw UTF-8 request body — read the stream before parsing JSON.
Formula "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);
});
Timing attacks: always use a constant-time comparison function (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\" }"}

CodeMeaningNotes
400Bad RequestValidation failure, malformed JSON
401UnauthorizedMissing or invalid API key
403ForbiddenKey is valid but not permitted for this store
404Not FoundInvoice or resource does not exist
409ConflictInvoice already paid / expired / cancelled — or Idempotency-Key reused with a different payload
422UnprocessableAmount too small, missing field
429Too Many RequestsRate-limit hit. Returns { error, status, timestamp }. Back off and retry.
500Server ErrorUnexpected failure

Status Codes

Invoice Status Flow

New Waiting Processing Paid Expired Underpaid Overpaid Cancelled Invalid
StatusMeaning
NewInvoice created, no coin selected yet
WaitingCoin selected, payment address shown — awaiting transaction
ProcessingTransaction detected, waiting for required confirmations
PaidFully confirmed — fulfil the order
ExpiredTimer elapsed before payment arrived
UnderpaidLess than the required amount was received
OverpaidMore than the required amount was received

Payment (Transaction) Status

StatusMeaning
PendingAddress generated, no transaction seen yet
DetectedPayment received, awaiting confirmation
ConfirmedRequired confirmations reached
ExpiredInvoice 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"
  }
}