Known Pitfalls
Use this page when something isn't working. It covers the most common integration mistakes, quick fixes, and what to check before raising a support ticket.
Authentication
Problem: Getting 401 Unauthorized
The most common cause is using the wrong header format.
# ❌ Wrong — NadaPay does not use Bearer tokens
Authorization: Bearer npk_sandbox_xxxx
# ✅ Correct
x-api-key: npk_sandbox_xxxxOther causes:
- Key has been revoked — generate a new one in the dashboard
- Key has leading or trailing whitespace — copy it fresh
- Using a production key against the sandbox URL or vice versa
Problem: Getting 403 wrong_environment
You are using a sandbox key against the production URL, or a production key against the sandbox URL.
# Sandbox key must use sandbox URL
x-api-key: npk_sandbox_xxxx
--url https://sandbox.api.nadapay.com/v1/...
# Production key must use production URL
x-api-key: npk_live_xxxx
--url https://api.nadapay.com/v1/...Verification and compliance
Problem: Getting 403 organization_not_verified on transaction endpoints
Your organization has not completed KYC/KYB verification. Check status:
GET /v1/organization/verificationIn sandbox this should never happen — organizations are auto-verified. In production, ensure all required documents have been submitted and approved.
See Check Verification Status for the full status reference.
Problem: Verification status is stuck on under_review
Production review typically takes 1–3 business days. If it has been longer, contact your NadaPay account manager with your organization_id.
Idempotency
Problem: Getting 400 Bad Request with missing_idempotency_key
You are sending a POST create request without an Idempotency-Key header. This is required on all create endpoints.
# Always include this on POST requests
--header 'x-idempotency-key: a1b2c3d4-e5f6-7890-abcd-ef1234567890'Problem: Getting 409 Conflict
You reused an Idempotency-Key with a different request body or a different endpoint. Each unique logical action needs its own unique key.
- Generate a fresh UUID per action
- Never reuse a key with a modified payload
- Persist the key before sending so retries use the same key
Beneficiaries
Problem: Beneficiary account validation fails immediately
Common causes:
- Incorrect account number — double-check digit count and format for the country
- Wrong bank code — use Get Provider Networks to confirm valid codes
- Account is closed or inactive at the destination bank
- Destination institution is temporarily unavailable — retry after a short delay
Always run Resolve Bank Account before adding a beneficiary account.
Problem: Beneficiary account status is expired
Validated beneficiary accounts can expire. Re-validate before initiating a new transaction:
PATCH /v1/beneficiaries/{id}/accounts/{account_id}Resubmit the account details to trigger re-validation.
Quotes
Problem: Getting quote_expired when executing a transaction
Quotes expire after approximately 5 minutes. If the user took too long to confirm, fetch a fresh quote and present it again before executing.
# Fetch a new quote immediately before execution
POST /v1/pricing/quoteDo not store and reuse quote IDs between sessions.
Problem: Quote amount does not match expected
Exchange rates are live. Rates fluctuate between quote requests. Always show users the quoted rate and destination amount before they confirm, and fetch a fresh quote if they navigate away and return.
Transactions
Problem: Getting insufficient_funds on transaction execution
Check available_balance — not balance — on the source wallet. The available_balance excludes amounts held for pending transactions.
GET /v1/wallets/{wallet_id}
# Check: available_balance >= quote.total_debitProblem: Transaction is stuck in processing for a long time
Processing times vary by corridor and payout method. Check the expected settlement time for the corridor using Supported Corridors and Currencies.
If the transaction has been processing beyond the expected settlement window, check the NadaPay status page at status.nadapay.com for any active incidents, then contact support with the transaction_id.
Problem: Transaction failed with no obvious reason
Check the failure_reason field on the transaction object:
GET /v1/transactions/{transaction_id}
# Check: failure_reasonCommon failure reasons:
| Reason | Fix |
|---|---|
beneficiary_account_invalid | Re-validate the beneficiary account |
quote_expired | Fetch a new quote and retry |
insufficient_funds | Top up the wallet |
limit_exceeded | Check transaction limits for the corridor |
corridor_unavailable | Temporary — retry after a delay |
compliance_hold | Contact your NadaPay account manager |
Webhooks
Problem: Webhooks are not arriving
- Confirm your endpoint is publicly accessible over HTTPS
- Confirm it returns
200 OKwithin 5 seconds - Check the Webhooks → Event Log in the dashboard for delivery status
- Confirm the endpoint URL is correctly registered in Settings → Webhooks
Problem: Receiving duplicate webhook events
NadaPay retries events on delivery failure. Your endpoint must be idempotent — check the event_id before processing and skip events you have already handled:
if (await db.eventAlreadyProcessed(event.id)) return res.sendStatus(200);
await processEvent(event);
await db.markEventProcessed(event.id);
res.sendStatus(200);Problem: Webhook signature verification is failing
- Confirm you are using the correct signing secret for the environment (sandbox and production have different secrets)
- Verify the raw request body before any JSON parsing — parsing and re-stringifying can alter byte ordering
- Confirm you are comparing the full hex digest
See Handling Webhooks for the full signature verification implementation.
When in doubt
- Check the
request_idin the error response — include it in any support ticket - Check
status.nadapay.comfor active platform incidents - Re-read the relevant How To guide for the operation you are attempting
- Contact support via the dashboard with your
organization_id,request_id, and a description of the issue
Updated about 2 hours ago