Quickstart
Create a test invoice, send your customer to the hosted checkout, and fulfil the order from a signed webhook. Everything on this page runs in test mode: invoices are paid on test networks with tokens that have no value.
Before you start
- Sign up and verify your email address. Creating an API key is refused until the email is verified (
email_unverified). - Every request below goes to your Zenq Pay API host, shown here as
https://<api-host>. - Amounts are decimal strings such as
"75.00". Never send or store money as a floating-point number.
1. Create an API key
In the dashboard open Settings → API keys and create a key. The key is shown once; store it as a server-side secret. Keys carry their store's environment in the prefix: nxp_test_… for a test store, nxp_live_… for a live store.
Send the key as a bearer token from your server only, never from a browser:
Authorization: Bearer nxp_test_…A key can be limited to scopes. Reading invoices needs invoices:read; creating or cancelling them needs invoices:write. A key without the scope gets 403 insufficient_scope. A missing or wrong key gets 401 unauthorized; an expired key gets 401 api_key_expired.
2. Create an invoice
curl -X POST https://<api-host>/v1/invoices \
-H "Authorization: Bearer nxp_test_…" \
-H "Idempotency-Key: order-1001" \
-H "Content-Type: application/json" \
-d '{"amount":"75.00","currency":"USD","merchant_order_id":"1001","description":"Order 1001"}'| Field | Required | Notes |
|---|---|---|
amount | yes | USD, greater than zero, at most two decimal places |
currency | no | Only USD is accepted (the default) |
merchant_order_id | yes | Your order reference, 1–128 characters |
description | no | Up to 500 characters, shown on the checkout |
customer_reference | no | Up to 128 characters |
metadata | no | A JSON object returned to you in webhooks |
allowed_asset_ids | no | Limit which coin/network pairs the customer may choose |
success_url, cancel_url | no | Return links shown on the checkout; see Hosted checkout |
The response is 201 Created with the invoice. The fields you need first:
{
"id": "6f1c…",
"public_id": "chk_…",
"status": "pending",
"amount": "75.00",
"currency": "USD",
"environment": "test",
"checkout_url": "https://<checkout-host>/pay/chk_…",
"expires_at": "…"
}Idempotency-Key is optional on this endpoint but recommended. Repeating the request with the same key and the same body returns the original invoice with 200 OK instead of creating a second one. The same key with a different body is refused with 409 idempotency_conflict.
3. Send the customer to checkout
Redirect the customer to checkout_url. The hosted checkout lets them pick a coin and network, shows the exact amount and a deposit address, and follows the payment through confirmation. Details are in Hosted checkout.
You can read an invoice at any time with GET /v1/invoices/{id}, but do not fulfil from polling or from the customer returning to your site. Fulfil from the webhook.
4. Receive the webhook
Add an endpoint under Webhooks & API in the dashboard (or POST /v1/webhook-endpoints). The signing secret, whsec_…, is shown once. When the payment is confirmed on chain, Zenq Pay sends invoice.paid to your endpoint, signed with that secret.
Your receiver must:
- Verify the
X-NexusPay-Signatureheader over the raw request body. - Deduplicate on the event
id, in the same database transaction that marks the order paid. Deliveries are at-least-once, so you will see duplicates. - Answer with any
2xxstatus quickly. Anything else is retried.
The signature format, retry schedule and receiver code in Python, Node and PHP are in Webhooks.
5. Test the whole flow
Open the invoice in the dashboard (Payments) and press Simulate payment. The invoice becomes paid and invoice.paid is delivered to your endpoint exactly as for a real payment, without anything moving on chain. When that works, pay a test invoice with real test tokens. See Testing.
Fees
Zenq Pay charges a flat fee once per paid invoice, never a percentage. The amount depends on your plan and on the network the customer actually paid on, so the same plan can cost different amounts on different networks. Invoice webhooks report the fee charged as data.fee_cents (integer US cents) and data.fee_usd (the same amount as a two-decimal US dollar string). Current amounts are on the pricing page; Going live explains how the fee is taken from settlement.
Next steps
- Express invoices: one fixed coin and address at creation, fixed or open amount.
- Going live: live approval, payout wallets and what custodial collection means.
- Error codes: every
codethe API can return.