Common Issues (FAQ)
Quick answers to the questions support hears most often. For a full code catalog see the Error Codes Reference; for step-by-step diagnosis see the Troubleshooting Guide.
Authentication
Q: I'm getting 401 INVALID_API_KEY but my key looks correct.
Check for trailing whitespace or a missing Bearer prefix. The header must be Authorization: Bearer $AFRIROUTE_API_KEY. Also confirm you're not using a sandbox key ($AFRIROUTE_API_KEY) against production.
Q: My key worked yesterday and now returns 401. The key was likely rotated or revoked. Generate a new one in the dashboard and update your environment variables.
Q: Can I use the same key for sandbox and production?
No. Sandbox uses $AFRIROUTE_API_KEY against sandbox.api.afriroute.ai; production uses $AFRIROUTE_API_KEY against api.afriroute.ai.
Messaging
Q: My SMS says delivered to AfriRoute but the recipient never got it.
Carriers report delivery to the handset, but some report optimistically. Use a registered sender ID and verify the number is active. Spoofed/unregistered sender IDs are commonly filtered.
Q: Why am I being charged for multiple segments on one message? Messages over 160 GSM-7 characters (or 70 with Unicode/emoji) split into multiple segments. Keep transactional messages short and ASCII where possible.
Q: UNSUPPORTED_COUNTRY — but the country is on your coverage list.
Coverage can differ per channel (SMS vs voice). Check the API Reference coverage table for the specific product.
Payments
Q: A charge is stuck in pending.
Mobile-money charges stay pending until the customer approves the USSD/app prompt. Don't poll aggressively — wait for the payment.completed webhook.
Q: I got DUPLICATE_TRANSACTION.
You reused a reference for a new charge, or retried a request that already succeeded. Query the original transaction by reference rather than creating a new one.
Webhooks
Q: Webhooks aren't arriving at all.
Most often the endpoint isn't publicly reachable over HTTPS, or you're returning a non-2xx. Check the dashboard Delivery Log and confirm the URL responds to an external curl.
Q: My signature check always fails.
You're almost certainly hashing parsed-then-reserialized JSON. Hash the raw request body with the input "{t}.{raw_body}". See Webhook Security.
Q: I received the same event twice.
That's expected — delivery is at-least-once. Make your handler idempotent using the event id. See Retry Logic.
Identity Verification
Q: Verification keeps returning IMAGE_QUALITY_LOW.
Capture in even lighting with no glare, hold the camera steady, and fill the frame with the document. Avoid screenshots and photocopies.
Q: Face match fails for the same person.
Use a frontal, recent selfie with one visible face and good lighting. Heavy backlighting or sunglasses commonly cause mismatches. Check face_quality in the response.
Q: REGISTRY_UNAVAILABLE for BVN / Fayda / Ghana Card.
The government registry is temporarily down. This is upstream of AfriRoute — retry after a short delay and don't fail the user permanently.
Rate Limits
Q: How do I avoid 429 RATE_LIMIT_EXCEEDED?
Read the X-RateLimit-* headers and pace requests, honor Retry-After, and add exponential backoff. Upgrade your plan if you regularly hit the ceiling.
Still Stuck?
- Reproduce in sandbox and capture the
request_id. - Email [email protected] with the
request_id, endpoint, and a minimal example. - Check the live status page at docs status page.
📚 Related Resources
Last Updated: May 2026 | Need help? [email protected]