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" }
}'
| Field | Type | Notes |
|---|---|---|
amount | string, required | Decimal string > 0 |
base_currency | string | USD (default), EUR, RUB, or an asset id like BTC — invoice in crypto directly |
payment_currency | string | any (buyer chooses at checkout) or an asset id like USDT_TRON |
order_id | string ≤ 255 | Your reference; echoed in webhooks |
description | string ≤ 500 | Customer-facing |
ttl_minutes | int | Default 360, range 10–4320 |
webhook_url | string ≤ 2000 | Per-invoice override of the console endpoint |
success_url | string ≤ 2000 | Buyer redirect after confirmation |
metadata | object | Arbitrary 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 bytype(e.g.payment.confirmed) andcreated_after, same cursor pagination. Includes journal-only types likeinvoice.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).