Skip to content
ZeroKYC Pay

Invoices API

Every merchant endpoint with examples: create, list, get, cancel, payment QR codes, plus events and payouts.

The complete tour of the merchant REST API. Interactive schema for every field: API Reference. All monetary values are decimal strings ("49.99"), all timestamps are ISO 8601 UTC.

Base URL: https://api.zerokyc-payments.com. Authenticate every call with your key:

Authorization: Bearer pk_live_...

pk_test_… keys work on both and operate strictly on sandbox invoices.

Create an invoice

curl -X POST https://api.zerokyc-payments.com/v1/invoices \
  -H "Authorization: Bearer pk_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-1042-create" \
  -d '{
    "amount": "49.99",
    "base_currency": "USD",
    "payment_currency": "any",
    "order_id": "order-1042",
    "description": "VPS Cloud Hosting 1 Month",
    "ttl_minutes": 360,
    "webhook_url": "https://api.merchant.com/zkp-webhook",
    "success_url": "https://merchant.com/orders/1042/success",
    "metadata": { "customer_id": "cust_8821" }
  }'
FieldTypeNotes
amountstring, requiredDecimal string > 0
base_currencystringUSD (default), EUR, RUB, or an asset id like BTC — invoice in crypto directly
payment_currencystringany (buyer chooses at checkout) or an asset id like USDT_TRON
order_idstring ≤ 255Your reference; echoed in webhooks
descriptionstring ≤ 500Customer-facing
ttl_minutesintDefault 360, range 10–4320
webhook_urlstring ≤ 2000Per-invoice override of the console endpoint
success_urlstring ≤ 2000Buyer redirect after confirmation
metadataobjectArbitrary key-value; echoed everywhere

The 201 response returns the full invoice (see below). The Idempotency-Key header (≤120 chars) makes retries safe — semantics.

The invoice object

{
  "id": "inv_live_9x8aL2mP0k1q",
  "order_id": "order-1042",
  "amount": "49.99",
  "base_currency": "USD",
  "payment_currency": "any",
  "status": "pending",
  "ttl_minutes": 360,
  "expires_at": "2026-09-13T19:00:00Z",
  "created_at": "2026-09-13T13:00:00Z",
  "checkout_url": "https://app.zerokyc-payments.com/pay/inv_live_9x8aL2mP0k1q",
  "options": [
    {
      "asset": "USDT",
      "network": "tron",
      "payment_address": "TYDzsYUEpvnYmQk4zGP9sWWcTEd2MiAtW6",
      "amount_crypto": "49.99",
      "rate": "1.0",
      "status": "open",
      "window_low": null,
      "window_high": null,
      "payment_url_extra": null,
      "confirmed_tx_hash": null
    }
  ],
  "observations": [],
  "paid_amount": null,
  "paid_asset": null,
  "metadata": { "customer_id": "cust_8821" }
}

Beyond the obvious fields: options[] (one per enabled asset — statuses and unique-amount windows explained in Invoice lifecycle), observations[] (raw on-chain sightings), and after confirmation paid_amount / paid_asset / each option's confirmed_tx_hash.

Get an invoice

curl https://api.zerokyc-payments.com/v1/invoices/inv_live_9x8aL2mP0k1q \
  -H "Authorization: Bearer pk_live_..."

Always authoritative — prefer it over webhook payloads when in doubt.

List invoices

curl "https://api.zerokyc-payments.com/v1/invoices?status=pending&limit=50" \
  -H "Authorization: Bearer pk_live_..."

Filters: order_id, status (pending | detecting | confirmed | underpaid | expired | canceled), created_after / created_before (ISO 8601), limit 1–100 (default 25).

Pagination is cursor-based and stable:

cursor = None
while True:
    query = f"limit=100{f'&cursor={cursor}' if cursor else ''}"
    page = get(f"/v1/invoices?{query}")
    process(page["data"])
    if not page["has_more"]:
        break
    cursor = page["next_cursor"]

Cancel an invoice

curl -X POST https://api.zerokyc-payments.com/v1/invoices/inv_live_9x8aL2mP0k1q/cancel \
  -H "Authorization: Bearer pk_live_..."

Allowed while pending and without detected payments; fires invoice.canceled. Already-confirmed invoices return 400 invalid_request.

Payment QR code

curl "https://api.zerokyc-payments.com/v1/invoices/inv_live_9x8aL2mP0k1q/qr?asset=USDT_TRON&format=svg" \
  -H "Authorization: Bearer pk_live_..." -o qr.svg

asset is the API asset id (USDT_TRON, TRX, USDT_ARBITRUM, BTC, LTC, DOGE, BCH, XRP, NEAR, SOL, USDT_SOL, USDC_SOL, TON, ETH, BNB, USDT_BSC, … — the full table is in Networks); format is png (default) or svg. The QR encodes the payment URI including TON memo where applicable.

Events

  • GET /v1/events — your event journal: filter by type (e.g. payment.confirmed) and created_after, same cursor pagination. Includes journal-only types like invoice.created. The webhook payloads are documented in Webhooks reference.

Platform endpoints (no auth)

  • GET /v1/ping — {"status": "ok", "service": "zerokyc-pay-api", "chain_mode": "..."} — use it for uptime checks.
  • GET /v1/plans — the storefront subscription plans.
  • GET /v1/site-config — public site configuration (contacts, socials, announcement banner).