PayGate API

Base URL https://pay.clik.blog/api/v1. Authenticate with Authorization: Bearer pg_live_… (create keys in Dashboard → API keys). Requests and responses are JSON. Rate limit: per key per minute (HTTP 429 with Retry-After).

Create an invoice

POST /api/v1/invoices
Idempotency-Key: order-1001        (optional, recommended — retries return the same invoice)
{
  "amount": "25.00", "currency": "USD",       // USD, EUR, GBP
  "coin": "BTC",                              // BTC, LTC, ETH, USDT_ERC20, TRX, USDT_TRC20
  "order_id": "1001", "description": "Pro plan",
  "redirect_url": "https://shop.example.com/thanks",
  "ttl_minutes": 30, "metadata": {"customer": 42}
}

Response 201:

{ "id": "inv_…", "status": "new", "coin": "BTC", "address": "bc1q…",
  "amount": "0.0004123", "amount_received": "0", "amount_confirmed": "0",
  "fiat_amount": "25.00", "fiat_currency": "USD", "rate": "60634.12",
  "confirmations_required": 2, "checkout_url": "https://pay.clik.blog/pay/inv_…",
  "payment_uri": "bitcoin:bc1q…?amount=0.0004123", "expires_at": "2026-11-04T05:30:00+00:00", … }

Get / list

GET /api/v1/invoices/inv_…           → invoice + "payments": [{txid, index, amount, confirmations}]
GET /api/v1/invoices?status=paid&limit=20&starting_after=inv_…   → {"data": [...], "has_more": true}

Statuses

newWaiting for payment.
partialLess than the amount received; the customer can top up before expiry.
pendingFull amount seen, waiting for confirmations.
paidConfirmed. Check overpaid and late (paid after expiry, at the old rate).
underpaidExpired with only part of the amount. Still watched for the grace window.
expiredNothing received in time. Still watched for the grace window (late payments become paid with late: true).
cancelledCancelled by the merchant before any payment.

Webhooks

We POST events as JSON: {"id":"evt_…","type":"invoice.paid","created":1730000000,"data":{…invoice…}}. Respond with any 2xx within 10 s. Non-2xx responses are retried after 1m, 5m, 30m, 2h, 6h, 12h and 24h. Deduplicate by id.

Verify the PayGate-Signature: t=<unix>,v1=<hex> header: compute HMAC-SHA256(secret, t + "." + raw_body), compare in constant time, and reject timestamps older than 5 minutes.

// PHP
[$t, $sig] = sscanf($_SERVER['HTTP_PAYGATE_SIGNATURE'], 't=%d,v1=%s');
$ok = abs(time() - $t) < 300 && hash_equals(hash_hmac('sha256', $t . '.' . file_get_contents('php://input'), $secret), $sig);

// Node.js
const [t, sig] = req.get('PayGate-Signature').match(/t=(\d+),v1=([0-9a-f]+)/).slice(1);
const ok = Math.abs(Date.now()/1000 - t) < 300 && crypto.timingSafeEqual(
  Buffer.from(crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex')), Buffer.from(sig));

Always confirm the final state with GET /api/v1/invoices/{id} before shipping goods.

Exporting a watch-only key

After pasting, PayGate shows the first address it will use — confirm it matches the first receive address in your wallet before saving.