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_xxxx

Other 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/verification

In 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/quote

Do 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_debit

Problem: 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_reason

Common failure reasons:

ReasonFix
beneficiary_account_invalidRe-validate the beneficiary account
quote_expiredFetch a new quote and retry
insufficient_fundsTop up the wallet
limit_exceededCheck transaction limits for the corridor
corridor_unavailableTemporary — retry after a delay
compliance_holdContact your NadaPay account manager

Webhooks

Problem: Webhooks are not arriving

  1. Confirm your endpoint is publicly accessible over HTTPS
  2. Confirm it returns 200 OK within 5 seconds
  3. Check the Webhooks → Event Log in the dashboard for delivery status
  4. 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

  1. Check the request_id in the error response — include it in any support ticket
  2. Check status.nadapay.com for active platform incidents
  3. Re-read the relevant How To guide for the operation you are attempting
  4. Contact support via the dashboard with your organization_id, request_id, and a description of the issue