Skip to main content

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:

ParameterTypeRequiredDescription
phoneNumberstringYesRecipient phone number with country code (e.g., +1234567890)
messagestringYesSMS message content (min 1 character)
hashstringNo11-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 messageId that 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:

ParameterTypeRequiredDescription
phoneNumberstringYesPhone number to send OTP to
languagestringNoLanguage code: fr (default), en, or ar
channelstringNoCommunication 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:

ParameterTypeRequiredDescription
phoneNumberstringYesPhone number the OTP was sent to
otpstringYes6-digit OTP code to verify
channelstringNoCommunication 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

CodeDescription
200Success
400Bad Request - Validation error
401Unauthorized - Missing API key
403Forbidden - Invalid API key
404Not Found
429Too Many Requests - Rate limit exceeded
500Internal Server Error
502Bad 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 success field 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 messageId for 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


Need help? Contact Chinqit support or refer to the troubleshooting guide.