SMS Gateway API Documentation
Send SMS messages and OTP codes using the Chinqit SMS Gateway REST API.
Quick Start
Send your first SMS in 2 steps:
Step 1: Send a message
curl -X POST https://sms.chinqit.com/messages/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+1234567890",
"message": "Hello from SMS Gateway!"
}'
Step 2: Send and verify an OTP
# Send OTP
curl -X POST https://sms.chinqit.com/otp/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+1234567890",
"language": "en"
}'
# Verify OTP
curl -X POST https://sms.chinqit.com/otp/verify \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+1234567890",
"otp": "123456"
}'
Authentication
All API requests require authentication using your API key provided by Chinqit.
Using the API Key
Include your API key in the request header:
X-API-Key: YOUR_API_KEY
Example
curl -X POST https://sms.chinqit.com/messages/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"phoneNumber": "+1234567890", "message": "Hello"}'
Base URL
All API requests should be made to:
- Production:
https://sms.chinqit.com
Endpoints
Send SMS
Send an SMS message to a phone number.
Endpoint: POST /messages/send
Request:
{
"phoneNumber": "+1234567890",
"message": "Your message text here",
"hash": "ABC123XYZ45"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
phoneNumber | string | Yes | Recipient phone number with country code (e.g., +1234567890) |
message | string | Yes | SMS message content (min 1 character) |
hash | string | No | 11-character SMS Retriever hash for automatic SMS consumption. When provided, the hash will be appended to the message. See SMS Retriever Guide for implementation details. |
Response:
{
"success": true,
"messageId": "550e8400-e29b-41d4-a716-446655440000",
"queued": true
}
Example:
curl -X POST https://sms.chinqit.com/messages/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+1234567890",
"message": "Hello from SMS Gateway!"
}'
JavaScript:
const response = await fetch("https://sms.chinqit.com/messages/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "YOUR_API_KEY",
},
body: JSON.stringify({
phoneNumber: "+1234567890",
message: "Hello from SMS Gateway!",
}),
});
const data = await response.json();
console.log("Message ID:", data.messageId);
Python:
import requests
response = requests.post(
'https://sms.chinqit.com/messages/send',
headers={
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'phoneNumber': '+1234567890',
'message': 'Hello from SMS Gateway!'
}
)
data = response.json()
print(f"Message ID: {data['messageId']}")
PHP:
<?php
$ch = curl_init('https://sms.chinqit.com/messages/send');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'X-API-Key: YOUR_API_KEY',
'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode([
'phoneNumber' => '+1234567890',
'message' => 'Hello from SMS Gateway!'
]));
$response = curl_exec($ch);
$data = json_decode($response, true);
echo "Message ID: " . $data['messageId'];
curl_close($ch);
?>
Note: Messages are queued and processed asynchronously. The API returns immediately with a
messageIdthat you can use to track your message.
SMS Retriever Hash Example:
To enable automatic SMS consumption using Android's SMS Retriever API, include an 11-character hash in your request. The hash will be appended to your message:
const response = await fetch("https://sms.chinqit.com/messages/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "YOUR_API_KEY",
},
body: JSON.stringify({
phoneNumber: "+1234567890",
message: "Your verification code is: 123456",
hash: "ABC123XYZ45", // 11-character hash
}),
});
The resulting SMS will be:
Your verification code is: 123456
ABC123XYZ45
For details on generating and using SMS Retriever hashes in Flutter, React Native, or Kotlin, see the SMS Retriever Guide.
Send OTP
Send a one-time password (OTP) code via SMS or WhatsApp.
Endpoint: POST /otp/send
Request:
{
"phoneNumber": "+1234567890",
"language": "en",
"channel": "sms"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
phoneNumber | string | Yes | Phone number to send OTP to |
language | string | No | Language code: fr (default), en, or ar |
channel | string | No | Communication channel: sms (default) or whatsapp |
Response:
{
"success": true,
"messageId": "550e8400-e29b-41d4-a716-446655440000",
"expiresIn": 600
}
SMS Channel Example:
curl -X POST https://sms.chinqit.com/otp/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+1234567890",
"language": "en",
"channel": "sms"
}'
WhatsApp Channel Example:
curl -X POST https://sms.chinqit.com/otp/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+1234567890",
"language": "en",
"channel": "whatsapp"
}'
JavaScript:
// Send OTP via SMS
const smsResponse = await fetch("https://sms.chinqit.com/otp/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "YOUR_API_KEY",
},
body: JSON.stringify({
phoneNumber: "+1234567890",
language: "en",
channel: "sms",
}),
});
// Send OTP via WhatsApp
const whatsappResponse = await fetch("https://sms.chinqit.com/otp/send", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "YOUR_API_KEY",
},
body: JSON.stringify({
phoneNumber: "+1234567890",
language: "en",
channel: "whatsapp",
}),
});
const data = await whatsappResponse.json();
console.log("OTP expires in:", data.expiresIn, "seconds");
Python:
import requests
# Send OTP via SMS
sms_response = requests.post(
'https://sms.chinqit.com/otp/send',
headers={
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'phoneNumber': '+1234567890',
'language': 'en',
'channel': 'sms'
}
)
# Send OTP via WhatsApp
whatsapp_response = requests.post(
'https://sms.chinqit.com/otp/send',
headers={
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
'phoneNumber': '+1234567890',
'language': 'en',
'channel': 'whatsapp'
}
)
data = whatsapp_response.json()
print(f"OTP expires in: {data['expiresIn']} seconds")
OTP Details:
- 6-digit numeric code
- Valid for 10 minutes
- Maximum 3 verification attempts
- Available via SMS or WhatsApp
Verify OTP
Verify an OTP code that was sent to a phone number.
Endpoint: POST /otp/verify
Request:
{
"phoneNumber": "+1234567890",
"otp": "123456",
"channel": "sms"
}
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
phoneNumber | string | Yes | Phone number the OTP was sent to |
otp | string | Yes | 6-digit OTP code to verify |
channel | string | No | Communication channel used: sms (default) or whatsapp |
Response (Success):
{
"success": true,
"message": "OTP verified successfully",
"verified": true
}
Response (Invalid):
{
"success": false,
"message": "Invalid OTP",
"retriesLeft": 2
}
Example:
curl -X POST https://sms.chinqit.com/otp/verify \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phoneNumber": "+1234567890",
"otp": "123456",
"channel": "sms"
}'
JavaScript:
const response = await fetch("https://sms.chinqit.com/otp/verify", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "YOUR_API_KEY",
},
body: JSON.stringify({
phoneNumber: "+1234567890",
otp: "123456",
channel: "sms",
}),
});
const data = await response.json();
if (data.verified) {
console.log("OTP verified successfully");
} else {
console.log("Invalid OTP. Retries left:", data.retriesLeft);
}
Error Handling
Error Response Format
All errors follow this format:
{
"success": false,
"message": "Error description",
"errors": [] // Optional: Validation errors
}
HTTP Status Codes
| Code | Description |
|---|---|
| 200 | Success |
| 400 | Bad Request - Validation error |
| 401 | Unauthorized - Missing API key |
| 403 | Forbidden - Invalid API key |
| 404 | Not Found |
| 429 | Too Many Requests - Rate limit exceeded |
| 500 | Internal Server Error |
| 502 | Bad Gateway - Provider error (WhatsApp channel) |
Common Errors
Validation Error (400):
{
"success": false,
"message": "Validation failed",
"errors": [
{
"path": ["message"],
"message": "String must contain at least 1 character(s)"
}
]
}
Rate Limit Exceeded (429):
{
"success": false,
"message": "Rate limit exceeded. Please try again later."
}
WhatsApp Provider Error (502):
{
"success": false,
"message": "WhatsApp OTP send failed",
"error": "Error details from WhatsApp API"
}
Rate Limits
OTP Sending
Per phone number per API key:
- 3 requests per minute
- 10 requests per hour
- 20 requests per day
Code Examples
Complete JavaScript Example
class SMSGateway {
constructor(apiKey, baseUrl = "https://sms.chinqit.com") {
this.apiKey = apiKey;
this.baseUrl = baseUrl;
}
async request(endpoint, options = {}) {
const url = `${this.baseUrl}${endpoint}`;
const response = await fetch(url, {
...options,
headers: {
"Content-Type": "application/json",
"X-API-Key": this.apiKey,
...options.headers,
},
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.message || "API request failed");
}
return response.json();
}
async sendMessage(phoneNumber, message) {
return this.request("/messages/send", {
method: "POST",
body: JSON.stringify({
phoneNumber,
message,
}),
});
}
async sendOTP(phoneNumber, language = "fr", channel = "sms") {
return this.request("/otp/send", {
method: "POST",
body: JSON.stringify({
phoneNumber,
language,
channel,
}),
});
}
async verifyOTP(phoneNumber, otp, channel = "sms") {
const response = await this.request("/otp/verify", {
method: "POST",
body: JSON.stringify({ phoneNumber, otp, channel }),
});
return response.verified === true;
}
}
// Usage
const client = new SMSGateway("YOUR_API_KEY");
// Send a message
const result = await client.sendMessage("+1234567890", "Hello!");
console.log("Message ID:", result.messageId);
// Send and verify OTP via SMS
const smsOtpResult = await client.sendOTP("+1234567890", "en", "sms");
const smsVerified = await client.verifyOTP("+1234567890", "123456", "sms");
console.log("SMS OTP verified:", smsVerified);
// Send and verify OTP via WhatsApp
const whatsappOtpResult = await client.sendOTP("+1234567890", "en", "whatsapp");
const whatsappVerified = await client.verifyOTP(
"+1234567890",
"123456",
"whatsapp"
);
console.log("WhatsApp OTP verified:", whatsappVerified);
Complete Python Example
import requests
from typing import Optional, Dict
class SMSGateway:
def __init__(self, api_key: str, base_url: str = 'https://sms.chinqit.com'):
self.api_key = api_key
self.base_url = base_url
self.headers = {
'Content-Type': 'application/json',
'X-API-Key': api_key
}
def _request(self, method: str, endpoint: str, data: Optional[Dict] = None):
url = f'{self.base_url}{endpoint}'
response = requests.request(method, url, json=data, headers=self.headers)
response.raise_for_status()
return response.json()
def send_message(self, phone_number: str, message: str):
return self._request('POST', '/messages/send', {
'phoneNumber': phone_number,
'message': message
})
def send_otp(self, phone_number: str, language: str = 'fr', channel: str = 'sms'):
return self._request('POST', '/otp/send', {
'phoneNumber': phone_number,
'language': language,
'channel': channel
})
def verify_otp(self, phone_number: str, otp: str, channel: str = 'sms'):
response = self._request('POST', '/otp/verify', {
'phoneNumber': phone_number,
'otp': otp,
'channel': channel
})
return response.get('verified', False)
# Usage
client = SMSGateway('YOUR_API_KEY')
# Send a message
result = client.send_message('+1234567890', 'Hello!')
print(f"Message ID: {result['messageId']}")
# Send and verify OTP via SMS
sms_otp_result = client.send_otp('+1234567890', 'en', 'sms')
sms_verified = client.verify_otp('+1234567890', '123456', 'sms')
print(f"SMS OTP verified: {sms_verified}")
# Send and verify OTP via WhatsApp
whatsapp_otp_result = client.send_otp('+1234567890', 'en', 'whatsapp')
whatsapp_verified = client.verify_otp('+1234567890', '123456', 'whatsapp')
print(f"WhatsApp OTP verified: {whatsapp_verified}")
Common Use Cases
User Registration with OTP
// Step 1: Send OTP via SMS
const smsOtpResult = await client.sendOTP("+1234567890", "en", "sms");
// Step 2: User enters OTP (from your UI)
const userOTP = "123456"; // Get from user input
// Step 3: Verify OTP
try {
const verified = await client.verifyOTP("+1234567890", userOTP, "sms");
if (verified) {
// Proceed with registration
console.log("OTP verified, user can register");
}
} catch (error) {
// Handle invalid/expired OTP
console.error("OTP verification failed:", error.message);
}
User Registration with WhatsApp OTP
// Step 1: Send OTP via WhatsApp
const whatsappOtpResult = await client.sendOTP("+1234567890", "en", "whatsapp");
// Step 2: User enters OTP (from your UI)
const userOTP = "123456"; // Get from user input
// Step 3: Verify OTP
try {
const verified = await client.verifyOTP("+1234567890", userOTP, "whatsapp");
if (verified) {
// Proceed with registration
console.log("WhatsApp OTP verified, user can register");
}
} catch (error) {
// Handle invalid/expired OTP or provider errors
console.error("WhatsApp OTP verification failed:", error.message);
}
Bulk Messaging
async function sendBulkMessages(recipients, message) {
const results = [];
for (const phoneNumber of recipients) {
try {
// Add delay to respect rate limits
if (results.length > 0) {
await new Promise((resolve) => setTimeout(resolve, 5000));
}
const result = await client.sendMessage(phoneNumber, message);
results.push({
phoneNumber,
messageId: result.messageId,
status: "queued",
});
} catch (error) {
results.push({ phoneNumber, error: error.message, status: "failed" });
}
}
return results;
}
// Usage
const recipients = ["+1234567890", "+0987654321", "+1122334455"];
const results = await sendBulkMessages(recipients, "Bulk message");
console.log(results);
Best Practices
Security
- ✅ Never commit API keys to version control
- ✅ Use environment variables or secure secret management
- ✅ Rotate API keys periodically
- ✅ Use HTTPS for all API requests
Error Handling
- ✅ Always check the
successfield in responses - ✅ Implement retry logic with exponential backoff for transient errors (429, 500, 502)
- ✅ Handle rate limits gracefully
- ✅ Log errors for debugging and monitoring
Performance
- ✅ Store
messageIdfor tracking purposes - ✅ Use async/await or promises for non-blocking calls
- ✅ Implement proper timeout handling
- ✅ Don't send duplicate messages
OTP Best Practices
- ✅ Always verify OTPs server-side
- ✅ Don't expose OTP codes in logs
- ✅ Handle rate limits gracefully
- ✅ Choose appropriate channel (SMS or WhatsApp) based on user preference
- ✅ Handle WhatsApp provider errors (502) with fallback to SMS if needed
Support
- API Reference: See API Reference for complete technical documentation
- Troubleshooting: Check Troubleshooting Guide for common issues
Need help? Contact Chinqit support or refer to the troubleshooting guide.