Troubleshooting Guide
Fixes for common problems when integrating the ChinqIT Verify API.
Common issues and solutions when integrating with the ChinqIT Verify API.
Note: Prefer the API v2 endpoints (POST /api/v2/notify, POST /api/v2/code, POST /api/v2/check, GET /api/v2/notify/:messageId). The legacy v1 endpoints are deprecated and include a deprecation object and Deprecation: true header in responses.
🔍 General Troubleshooting Steps
- Verify API Key: Ensure your API key is correct and active
- Check Request Format: Verify your request body matches the API specification
- Review Error Messages: Check the error response for specific details
- Test Connectivity: Ensure your application can reach
https://sms.chinqit.com(v2:https://sms.chinqit.com/api/v2/notifyfor send)
🔐 Authentication Issues
401 Unauthorized - Missing API Key
Symptoms:
- 401 status code
- "API key is required" error message
Solutions:
-
Verify Header Name
# Must be exactly: X-API-Key (case-sensitive) curl -H "X-API-Key: your-key" https://sms.chinqit.com/api/v2/notify -
Check Header Format
// Correct headers: { 'X-API-Key': 'your-api-key' } // Incorrect - missing hyphen headers: { 'X_API_Key': 'your-api-key' } -
Verify API Key is Included
- Check that your API key is being sent in every request
- Ensure no middleware is stripping the header
403 Forbidden - Invalid API Key
Symptoms:
- 403 status code
- "Invalid API key" error message
Solutions:
-
Verify API Key
- Open API keys in the dashboard and check that the key is active; choose Activate if it was deactivated
- Check for typos or extra spaces in your API key
- Ensure you're using the correct API key for your environment
-
Check API Key Format
# Ensure no extra spaces or characters # Correct: "abc123xyz" # Incorrect: " abc123xyz " or "abc123xyz\n" -
Regenerate API Key
- If your API key has been compromised, choose Regenerate key on it under API keys in the dashboard (the old key stops working immediately), or create a new key there
📝 Validation Errors
400 Bad Request - Validation Error
Symptoms:
- 400 status code
- "Validation failed" message with error details
Common Validation Errors:
Missing Required Field:
{
"success": false,
"message": "Validation failed",
"errors": [
{
"path": ["phoneNumber"],
"message": "Required"
}
]
}Invalid Phone Number Format:
{
"success": false,
"message": "Validation failed",
"errors": [
{
"path": ["phoneNumber"],
"message": "Invalid phone number format"
}
]
}Solutions:
-
Verify Request Body
// Correct format for sending SMS { "phoneNumber": "+1234567890", "message": "Your message here" } // Correct format for sending OTP { "phoneNumber": "+1234567890", "language": "en", "channel": "sms" } -
Check Phone Number Format
- Must include country code with
+prefix - Examples:
+1234567890,+33123456789 - No spaces or special characters except
+
- Must include country code with
-
Verify Message Content
- Message must be at least 1 character
- OTP must be exactly 6 digits
-
Check Channel Value
- For OTP:
channelmust be"sms"or"whatsapp"(lowercase) - Defaults to
"sms"if omitted
- For OTP:
📊 Rate Limiting
429 Too Many Requests
Symptoms:
- 429 status code
- "Rate limit exceeded" error message
Rate Limits:
- OTP sending: the per-minute, per-hour and per-day limits ChinqIT sets on each API key (per recipient). Without a custom limit, the maximum applies: 60 per minute, 1,000 per hour, 5,000 per day.
Solutions:
-
Implement Exponential Backoff
async function sendOTPWithRetry( phoneNumber, language, channel, maxRetries = 3, ) { for (let i = 0; i < maxRetries; i++) { try { return await client.sendOTP(phoneNumber, language, channel); } catch (error) { if (error.status === 429 && i < maxRetries - 1) { // Wait with exponential backoff const waitTime = Math.pow(2, i) * 1000; // 1s, 2s, 4s await new Promise((resolve) => setTimeout(resolve, waitTime)); continue; } throw error; } } } -
Respect Rate Limits
- Track your request frequency
- Implement client-side rate limiting
- Wait before retrying after 429 errors
-
Use Different Phone Numbers
- Rate limits are per phone number
- If testing, use different phone numbers to avoid hitting limits
💳 Insufficient Balance
402 Payment Required
Symptoms:
- HTTP 402 status code
- Error message
"Insufficient balance" messageIdfield present in the response
Only WhatsApp, email and broadcast requests return 402. An SMS your balance cannot cover is not sent, not charged, and shows failed.
Solutions:
-
Check your account balance
- Log in to the ChinqIT Verify dashboard
- Open Wallet in the menu to review your balance and transaction history
-
Top up your account
- Open Wallet and select Top up, then enter the amount (50 to 100,000 MRU)
- Pay in the Bankily app with the merchant code and the amount shown on the checkout; the guide shows each screen
- Back in the dashboard, enter your Bankily phone number and the B-Pay passcode Bankily shows, then confirm
- If an earlier top-up is still in progress, the checkout says so first: Resume verification continues that same payment, and Start over (offered only while it is unpaid) cancels it so you can enter a new amount
- If Bankily confirms the payment later, use Recheck on the top-up's row in the Wallet transactions (or Recheck with bank in its details) to credit it
- If Bankily never took the money, open the failed top-up and choose Try again to start a new top-up; its details show the bank's status as Success, Failed or Pending
-
Retry after top-up
- API keys are reactivated automatically after a successful BPAY payment or admin balance credit (not after referral rewards or SMS refunds)
- Only the keys switched off because the balance ran out come back on. On the API keys page they show Paused · no balance, and their menu offers Top up to resume. A key you deactivated yourself shows Inactive and stays off until you activate it, and so does a key switched off with a disabled account
- If you still receive 403
"Invalid or inactive API key", wait up to 60 seconds for cache propagation (ensure the dashboard shares Redis with the SMS gateway) or contact support
-
Contact support
- If the issue persists after a top-up, contact ChinqIT Verify support
- Provide your account identifier and transaction details
Free trial
- 403
TOP_UP_REQUIRED: new accounts send OTPs only until their first top-up. Top up once to send other messages. - 429
TRIAL_LIMIT: free trial limit reached. Top up to send more. - 403
TRIAL_PAUSED: free trial sending is paused. Top up to continue.
503 Service Unavailable - Sending temporarily unavailable
Symptoms:
- HTTP 503 status code on a send (SMS, OTP, WhatsApp OTP or bulk)
errorCodefield set toPRICING_NOT_CONFIGURED- Message
"Sending is temporarily unavailable. Please try again later or contact support."
What it means: ChinqIT Verify refused the message before sending it, because the price for that message type is temporarily unavailable. Nothing was sent and nothing was charged.
Solutions:
- Retry after a few minutes; our team is alerted automatically.
- If it continues, contact ChinqIT Verify support with the time of the request.
Finding a message in the Message log
The Message log opens on the last 7 days. To search or export older messages, choose All time in the period control (or set Custom dates). Clear all removes every filter and returns the log to the last 7 days. Export CSV includes every message that matches the current filters and period. Click a row to open its details: the origin (API or Broadcast), the cost, and a timeline of what happened to the message.
A failed message says why in one sentence and what to do next: for example, that the operator refused the number and you should check it with your customer, or that your balance was too low, with a Top up button. Quote the message ID shown at the top of the details when you contact support.
BPay top-up still processing
A submitted top-up stays locked while its bank outcome is uncertain. Keep the top-up dialog open for automatic checks, or use Recheck. These checks do not submit another payment. If they stop without a conclusive result, contact support with the operation ID; do not pay a second time for the same attempt.
Only bank confirmation can authorize automated wallet credit. A timeout or screenshot is not that confirmation. Only an unsubmitted draft can be cancelled: it does not yet have a Bankily phone number, and cancellation is not a bank failure. A payment held for manual review must be investigated by support.
Rejected and failed messages
A rejected message reached the operator, which refused it — most often because the recipient number is not a valid destination. The operator bills us for every submission it receives, so a rejected message is charged. Its cost appears normally in the dashboard and in the CSV export.
A failed message never reached the operator. Our gateway could not submit it, or your balance
was insufficient. It is not charged; any charge already taken is refunded, shown as a
struck-through cost with a Refunded badge, and exported as Refunded=Yes.
If you see a run of rejected messages, check the recipient numbers. A high rejection rate is almost always a stale contact list rather than a platform fault.
Invalid recipients are not refunded
Invalid-destination rejections (ESME_RINVDSTADR) are billed rather than refunded, like any
other rejection: the operator charges us for every submission it receives, including the ones it
rejects, so we pass that cost on. These messages show status: rejected with Refunded set to
No.
If the same number is rejected again within the hour, the message is not resubmitted and not charged — you pay at most once per hour for a dead number. Verification codes (OTP) are always submitted and never suppressed.
📱 WhatsApp Channel Issues
502 Bad Gateway - WhatsApp Provider Error
Symptoms:
- 502 status code
- "WhatsApp OTP send failed" error message
errorCode:WHATSAPP_SEND_FAILED
Solutions:
-
Check Phone Number Format
- WhatsApp requires phone numbers in E.164 format with country code
- Example:
+1234567890(not1234567890)
-
Implement Fallback to SMS
async function sendOTPWithFallback(phoneNumber, language) { try { // Try WhatsApp first return await client.sendOTP(phoneNumber, language, "whatsapp"); } catch (error) { if (error.status === 502) { // Fallback to SMS if WhatsApp fails console.log("WhatsApp failed, falling back to SMS"); return await client.sendOTP(phoneNumber, language, "sms"); } throw error; } } -
Handle Provider Errors Gracefully
- WhatsApp provider errors are temporary
- Implement retry logic with SMS fallback
- Log errors for monitoring
-
Verify WhatsApp Service Availability
- Contact ChinqIT Verify support if WhatsApp channel is consistently failing
- Check if WhatsApp service is temporarily unavailable
🔄 Common Integration Issues
Messages Not Being Sent
Symptoms:
- Request succeeds but message not received
- No error but no delivery confirmation
Solutions:
-
Verify Phone Number
- Ensure phone number is correct and active
- Check country code is correct
- Verify recipient can receive SMS
-
Check Message Content
- Ensure message is not empty
- Verify special characters are properly encoded
- Check message length (standard SMS limits apply)
-
Handle Asynchronous Processing
- Messages are queued and processed asynchronously
- API returns immediately after queuing
- Delivery may take a few seconds to minutes
OTP Verification Failing
Symptoms:
- OTP sent successfully but verification fails
- "Invalid OTP" or "OTP not found" errors
Solutions:
-
Check OTP Expiration
- OTPs expire after 10 minutes
- Ensure user enters OTP promptly
- Request new OTP if expired
-
Verify OTP Format
- OTP must be exactly 6 digits
- No spaces or special characters
- Example:
"123456"(not"123 456"or"123-456")
-
Check Retry Limit
- Maximum 3 verification attempts per OTP
- After 3 failed attempts, OTP is invalidated
- Request new OTP if retry limit exceeded
-
Match Channel
- If OTP was sent via WhatsApp, verify with
channel: "whatsapp" - If OTP was sent via SMS, verify with
channel: "sms"(or omit, defaults to SMS)
- If OTP was sent via WhatsApp, verify with
-
Handle Case Sensitivity
- Phone number must match exactly (including
+prefix) - Ensure phone number format is consistent between send and verify
- Phone number must match exactly (including
🌐 Network Issues
Connection Timeout
Symptoms:
- Request times out
- Network errors
Solutions:
-
Check Internet Connection
- Verify your application has internet access
- Test connectivity to
https://sms.chinqit.com
-
Implement Timeout Handling
const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout try { const response = await fetch("https://sms.chinqit.com/api/v2/notify", { signal: controller.signal, // ... other options }); clearTimeout(timeoutId); } catch (error) { if (error.name === "AbortError") { console.error("Request timeout"); } } -
Retry Logic
- Implement retry logic for transient network errors
- Use exponential backoff
- Don't retry on 4xx errors (client errors)
SSL/TLS Errors
Symptoms:
- SSL certificate errors
- TLS handshake failures
Solutions:
-
Verify HTTPS
- Always use
https://sms.chinqit.com(nothttp://) - Ensure your environment supports TLS 1.2+
- Always use
-
Check Certificate
- Ensure system clock is correct
- Update CA certificates if needed
- Contact ChinqIT Verify if certificate issues persist
🐛 Debugging Tips
Enable Request Logging
JavaScript:
async function sendMessage(phoneNumber, message) {
console.log("Sending message:", { phoneNumber, message });
try {
const response = await fetch("https://sms.chinqit.com/api/v2/notify", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": process.env.API_KEY,
},
body: JSON.stringify({ phoneNumber, message }),
});
console.log("Response status:", response.status);
const data = await response.json();
console.log("Response data:", data);
return data;
} catch (error) {
console.error("Error:", error);
throw error;
}
}Python:
import requests
import logging
logging.basicConfig(level=logging.DEBUG)
def send_message(phone_number, message):
url = 'https://sms.chinqit.com/api/v2/notify'
headers = {
'Content-Type': 'application/json',
'X-API-Key': os.getenv('API_KEY')
}
data = {
'phoneNumber': phone_number,
'message': message
}
logging.debug(f'Sending request: {data}')
response = requests.post(url, json=data, headers=headers)
logging.debug(f'Response status: {response.status_code}')
logging.debug(f'Response data: {response.json()}')
return response.json()Test API Connectivity
# Test basic connectivity
curl -X POST https://sms.chinqit.com/api/v2/notify \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+1234567890", "message": "Test"}'🆘 Still Having Issues?
-
Check Documentation:
- API Reference - Current API | API v1 Reference (Deprecated) - Legacy endpoints
- API Usage Guide - Code samples and examples
-
Review Error Responses:
- Check the
messagefield for specific error details - Review
errorsarray for validation issues - Note the HTTP status code
- Check the
-
Common Solutions:
- Verify API key is correct and active
- Check request format matches API specification
- Ensure phone numbers are in E.164 format
- Implement proper error handling and retry logic
- Contact ChinqIT Verify support for persistent issues
Need more help? Contact ChinqIT Verify support with:
- Your API key (masked)
- Error message and status code
- Request details (without sensitive data)
- Steps to reproduce the issue