NoHoldPay

API Keys

Create and manage API credentials. Test keys are sandboxed. Live keys accept real payments.

Every API call uses an API key. Each key belongs to one mode (test or live) and cannot be switched after creation. The mode is controlled by the Test mode switch at the bottom of the sidebar, not a form field.

PrefixModeReal funds
pk_test_TestNo
pk_live_LiveYes

A full key is 72 characters: the 8-character prefix plus 64 hex characters of random data. Keys are shown only once at creation, after which only the 16-character key prefix is visible.

Do not expose API keys in browser code, mobile apps, or public repositories. Store them server-side.

Business scope

An API key belongs to the business that created it. It cannot access wallets, payments, payment links, invoices, or webhooks from another business under the same login.

Create separate keys for every business and store the intended business's key in that integration's server configuration. Switching businesses in the dashboard does not change an existing key. See Multiple Businesses for the full isolation model.

Create a key

You need at least one active wallet in the current mode before you can create a key. The API Keys page shows an empty state directing you to add a wallet first.

Pick test or live with the Test mode switch in the sidebar footer.
Go to API Keys in the sidebar and click Create API key.
Enter a Label (shown in logs and on the API Keys list).

Review Accepted payment methods. The picker auto-selects every chain and token your current wallets cover. Deselect anything you want this key to block.

(Optional) Add a webhook URL plus the events to subscribe to. You can also add a webhook later from the key's expand panel.

Click Create key. The success panel shows the API key and (if you added one) the Webhook signing secret in full, each with a copy button. Both are shown only once. Copy them and click Done - I stored them.

A key is active immediately. You can have multiple keys per mode and revoke each one independently.

Allowed API caller IPs

Use Allowed API caller IPs when only your servers should be able to use a key. Enter each server's public outbound IPv4 or IPv6 address, or a CIDR range, separated by commas. Include your NAT gateway if it supplies your outbound address. A maximum of 100 entries is supported. A nonempty list rejects callers outside those ranges. Empty means no caller-IP restriction. A valid API key is still required in either case.

Set this when creating a key, or click Edit on an existing key. Saving takes effect on subsequent API requests, including requests using an already-verified key. Dashboard sign-in and key management remain available so you can correct a mistaken list. Each key has its own list, independent of other keys, its payment-method settings, and outgoing webhooks.

Cloudflare and other proxies

Cloudflare protecting your store's website does not normally proxy HTTP requests made by your backend to NoHoldPay. Use that backend's outbound IP, not the IP returned by a DNS lookup of your store. If your code runs in Workers, serverless hosting, a VPN, or an intermediary service, confirm the actual outbound addresses with that provider. Shared or changing egress addresses may not provide an effective "only my servers" boundary. Requests reaching NoHoldPay through the MCP server are checked against the address the agent connects from, which for a hosted agent is not your server and may change between runs. A third-party relay may instead present its own address. Restricting a key you use from an agent is often not practical. Do not allow a shared relay address just to bypass a rejection: everyone else using that relay would then pass the check too.

When NoHoldPay's API is behind Cloudflare, NoHoldPay resolves the caller through its configured trusted proxy chain. Caller-supplied forwarding headers alone are not trusted. An unresolved proxy address cannot satisfy a configured API caller list. Cloudflare Workers and Pseudo IPv4 header rewrites require particular care. See Cloudflare's header documentation.

Rejections, recovery, and notifications

A caller-IP rejection returns the same 401 UNAUTHORIZED response as other key authentication failures: Invalid or deactivated API key. This avoids disclosing key status to unauthenticated callers. No payment is created by a rejected request. Check the server's outbound IP and the saved list. Support can distinguish caller-IP rejections in server logs without seeing the full key.

Rejected API requests currently send no merchant email or dashboard notification. Webhook failures have a separate notification flow: when delivery becomes exhausted, NoHoldPay attempts an email and a dashboard notification, subject to the merchant's channel preferences under Settings > Notifications. These messages go to the merchant, not the person paying. Production email delivery also depends on the configured mail service.

Merchants should normally correct the list themselves. For a confirmed support request, an admin can clear the selected key's caller restrictions with a support reason. The action checks the current list and records the admin and removed entries in the audit log. Clearing sends no email.

Existing webhook IP settings

The older webhook IP field restricts destinations for outgoing webhooks. Its saved values are not copied into API caller restrictions. If an outbound server IP was mistakenly entered there, review and clear or correct it in the webhook settings, save, and send a test webhook. Configure Allowed API caller IPs separately. Intentional destination restrictions remain in effect.

Allowlists

The API key allowlist is the enforcement boundary for which coins you receive. The create form treats your wallets' chain and token coverage as the default allowlist. Restrict per key if you run partner integrations or want a key scoped to a single coin.

  • Accepted chains. The chains this key can create payments on. The picker auto-selects every chain you have a wallet for. Deselect to block.
  • Accepted tokens. The coin variants (e.g. USDT-TRC20, USDT-ERC20, USDC-SPL are independent pairs). Auto-selects every token on the accepted chains. The create form presents both as one combined Accepted payment methods picker.

A hosted checkout only ever offers coins inside this allowlist, and a checkout with no coin left inside it is rejected at creation. This is different from the per-request accepted_chains / accepted_coins / accepted_tokens fields, which by default only pick the checkout default coin and never widen or restrict what the key allows: a request that names a coin outside the allowlist is simply ignored (no default), not rejected. To make a single request's accepted set a hard restriction (a subset of the key allowlist) without minting a per-group key, send restrict_to_accepted: true on that create-payment call. The checkout then offers only that subset.

Webhooks per key

Each key has its own webhook endpoint and signing secret. A key without a webhook still creates payments. It just sends no notifications.

Add a webhook

Expand the key with the Webhook button on its row on the API Keys page.

Enter your endpoint URL. Test-mode keys may use http webhook URLs. Live-mode keys require https (an http URL is rejected with a validation error). In both modes, localhost and private-network addresses are not allowed.

Optionally restrict webhook destination IPs under the webhook settings. This is separate from Allowed API caller IPs.

Pick the events to receive.
Click Add webhook. Copy the webhook signing secret shown once in the dialog.

Use Send test on the webhook panel to fire a synthetic event and verify your endpoint is reachable.

Rotate the signing secret

Click Rotate secret on the webhook panel. The new secret is shown once in the dialog. After rotation there is a 24-hour grace window where deliveries are signed with both the new and the old secret (the X-Webhook-Signature header carries multiple v1= values), so update your verifier within 24 hours. After the window the old secret stops verifying.

See Webhooks for the full signature-verification flow.

Revoke a key

Click Revoke... on the key's row. The confirmation dialog reads Revoke "<label>"? with the action button Revoke key.

Revoked keys return 401 Unauthorized on every request immediately. There is no undo. Create a new key if you revoke one by mistake.

Rate limits

API endpoints authenticated by an API key are rate-limited to 2 requests per second per client IP with a burst of 10. Exceeding the limit returns 429 Too Many Requests. Use exponential backoff in your integration.

A few endpoints have tighter buckets (auth flows, invoice send/resend, public checkout SSE). See the response body and Retry-After if you hit one.

Test vs live

  • Test keys create payments on testnet chains only. Live keys create payments on mainnet chains only. The platform enforces this via the chain's is_testnet flag on every POST /api/v1/payments.
  • Test and live Prepaid Credit reserves are separate. Both modes deduct fees from their own reserve. Under the default platform configuration, the initial business is credited $100 in test and $50 in live at signup. Additional businesses receive no signup credit.
  • Switch your integration from test to live by replacing the test key with a live key in your configuration. The API calls are otherwise identical.

On this page