Authentication
Authenticate every payments-API request with your project's API key in the x-api-key header.
curl https://api.duckypay.co/v1/invoices \
-H "x-api-key: dp_test_9f2c…" \
-H "content-type: application/json" \
-d '{ "chainId": 80002, "amount": "5000000" }'
# Authorization: Bearer <key> is accepted as an alternative header.API keys#
Keys are created per project in the dashboard and come in two modes:
| Prefix | Mode | Chains allowed | Visibility |
|---|---|---|---|
dp_test_… | Test | Testnets only | Re-viewable in the dashboard |
dp_live_… | Live | Mainnets only | Shown once at creation |
DuckyPay stores only a hash of each key. A missing or unknown key returns 401:
{ "success": false, "data": null, "error": "invalid API key" }Test vs live gating#
The key’s mode is enforced against the charge’s chainId: a test key creating a mainnet charge (or vice versa) is rejected with 400 before anything is signed. Webhook endpoints are scoped the same way — see Go-live checklist for the full separation table.
Rate limits#
Charge creation is limited per minute by your account plan; exceeding it returns 429 with meta.retryAfterMs (see Errors & envelope).
| Plan | Charge creations | Monthly charge quota |
|---|---|---|
| Free | 30 req/min | 8,000 |
| Pro | 60 req/min | Unlimited |
| Scale | 120 req/min | Unlimited |
Handling your keys#
- Server-side only. The browser never needs your key — it only needs the
checkoutUrl(orinvoiceIdfor the React components). - Store keys in environment variables or a secret manager, never in source control.
- Rotate a key immediately if it may have leaked — create a new one in the dashboard, deploy it, then revoke the old one. A leaked key can create charges that pay you; it can never move funds out of your wallet.