API documentation

Non-custodial crypto payments: your customer pays straight into your own wallet, the gateway watches the chain and tells your app. Base URL: https://biggypay.com

Authentication

Every /api/v1/* call needs your API key in the x-api-key header — get it from Dashboard → Developers. Keep it server-side; never ship it in an app or web page.

Create a payment

POST /api/v1/payments — price it in NGN/USD/EUR/GBP or any supported crypto; the customer pays in pay_currency at the live rate. Supply a unique Idempotency-Key for every logical order and safely reuse it when retrying the identical request.

curl -X POST https://biggypay.com/api/v1/payments \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Idempotency-Key: order-1042-attempt-1" \
  -H "content-type: application/json" \
  -d '{
    "price_amount": 150000,
    "price_currency": "ngn",
    "pay_currency": "usdt",
    "order_id": "ORDER-1042",
    "order_description": "Ticket bundle",
    "ipn_callback_url": "https://yourapp.com/ipn",
    "success_url": "https://yourapp.com/thanks",
    "expires_in_minutes": 60
  }'

Response:

{
  "payment_id": "9224c8c5-7818-4f13-8f98-74ff172cce83",
  "payment_status": "waiting",
  "pay_address": "TYourWalletAddress…",
  "pay_currency": "usdttrc20",
  "pay_amount": "110.3291",
  "price_amount": "150000",
  "price_currency": "ngn",
  "invoice_url": "https://biggypay.com/pay/9224c8c5-…",
  "expires_at": "2026-08-13T19:13:38.993Z",
  "fee_percent": "1",
  ...
}

Send the customer to invoice_url — a hosted page with QR, address, countdown and live status. Works well as a WhatsApp message: https://wa.me/?text=Pay here: {invoice_url}

Read payments

GET /api/v1/payments/:id — one payment (yours only).

GET /api/v1/payments?status=finished&limit=50 — list, newest first.

GET /api/v1/currencies — currencies you can accept right now (needs a payout wallet on that chain).

GET /api/v1/estimate?amount=150000&from=ngn&to=usdt — rate preview without creating anything.

Currencies

codeAssetChain
btc Bitcoin btc native coin
eth Ethereum eth native coin
usdterc20 USDT (ERC-20) eth token
usdcerc20 USDC (ERC-20) eth token
usdtbep20 USDT (BEP-20) bsc token
bnb BNB bsc native coin
usdtsol USDT (Solana) sol token
trx Tron tron native coin
usdttrc20 USDT (TRC-20) tron token

Aliases: usdt → USDT (TRC-20) · usdt-bep20, usdtbsc → BEP-20 · usdt-sol, usdtspl → Solana · usdc → ERC-20.

Payment lifecycle

waiting          nothing received yet
confirming       payment seen, waiting for confirmations
finished         confirmed amount ≥ expected (minus 0.5% tolerance)  ✓ fulfil the order
partially_paid   expired with some money received
expired          expired with nothing received

Confirmations: BTC 1 · ETH 3 blocks · BSC 6 blocks · Tron solidified (~1 min) · Solana finalized (~seconds). Overpayments still finish — actually_paid holds the real amount. Invoices are watched 24h past expiry so late funds keep statuses truthful.

Webhooks (IPN)

On every status change we POST the payment JSON to your ipn_callback_url (per payment, or the default from Dashboard → Developers). The x-gateway-sig header is HMAC-SHA512 of the sorted-key JSON using your IPN secret. Retries with backoff: 1m → 5m → 15m → 1h → 6h.

const crypto = require('crypto');

function sortKeys(v) {
  if (Array.isArray(v)) return v.map(sortKeys);
  if (v && typeof v === 'object')
    return Object.fromEntries(Object.keys(v).sort().map((k) => [k, sortKeys(v[k])]));
  return v;
}

app.post('/ipn', express.json(), (req, res) => {
  const expected = crypto
    .createHmac('sha512', process.env.IPN_SECRET)   // from Dashboard → Developers
    .update(JSON.stringify(sortKeys(req.body)))
    .digest('hex');
  if (req.headers['x-gateway-sig'] !== expected) return res.status(401).end();

  const { payment_status, order_id, actually_paid } = req.body;
  if (payment_status === 'finished') {
    // credit the order — actually_paid is the confirmed on-chain amount
  }
  res.status(200).end();   // reply 200 fast, work async
});

Payout wallets — the custody model

hd (xpub) — you paste an account-level xpub; every invoice gets a fresh address derived from it. Best tracking, appears in your wallet app automatically. BTC is xpub-only; ETH/BSC/Tron support it too.

static (address) — one receiving address per chain; concurrent invoices are told apart by unique invoice amounts (a dust-step surcharge of at most 0.05 USDT). The customer must send the exact amount shown. Solana is static-only.

Either way the gateway holds public keys only — it cannot spend, sweep or freeze anything. The platform fee is a ledger entry on finished payments, settled outside the payment flow.

Errors

400 validation (message says what's wrong) · 401 bad/missing API key · 404 not yours / doesn't exist · 502 rate source unavailable · 503 too many concurrent static invoices. Errors are JSON: {"statusCode":400,"message":"…"}