Quick Start
1. Generate an API Key
Go to API Integration → API Token in the sidebar and click Add Token. Copy the key immediately — it will only be shown once.
2. Add the Key to Your Request
Include your API key using the X-API-Key header (recommended):
X-API-Key: nsms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx3. Send Your First SMS
Use the https://api.grosms.com/api/v1/sms/send endpoint:
curl -X POST "https://api.grosms.com/api/v1/sms/send" \
-H "X-API-Key: nsms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"to": "98XXXXXXX",
"message": "Your Content Here!"
}'4. Track with message_id or batch_id
Track delivery using message_id (single) or batch_id (bulk) with https://api.grosms.com/api/v1/sms/status/:id. The job_id is queue metadata, not the delivery-status lookup key.
Authentication
How to authenticate your API requests
Method 1: X-API-Key Header (Recommended)
Send your API key in the X-API-Key header. This is the recommended method for all API requests.
const response = await fetch('https://api.grosms.com/api/v1/sms/send', {
method: 'POST',
headers: {
'X-API-Key': 'nsms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
to: '98XXXXXXX',
message: 'Your Content Here!',
})
});
const result = await response.json();Method 2: Authorization Bearer Token
Alternatively, pass your API key as a Bearer token in the Authorization header.
const response = await fetch('https://api.grosms.com/api/v1/sms/send', {
method: 'POST',
headers: {
'Authorization': 'Bearer nsms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
to: '98XXXXXXX',
message: 'Your Content Here!'
})
});Python Example
import os
import requests
API_KEY = os.environ.get('API_KEY') # never hardcode
BASE_URL = 'https://api.grosms.com/api/v1/sms'
HEADERS = {
'X-API-Key': API_KEY,
'Content-Type': 'application/json'
}
response = requests.post(
f'{BASE_URL}/send',
headers=HEADERS,
json={
'to': '98XXXXXXX',
'message': 'Your Content Here!',
}
)
result = response.json()Security Warning
Never hardcode API keys in source code. Use environment variables. Never expose keys in client-side JavaScript or mobile apps.
SMS Endpoints
Send and manage SMS messages
/api/v1/sms/sendSend a single SMS or bulk SMS. Supports raw message flow and template-based flow (required for OTP).
Parameters
string | arrayRecipient number(s): single, array, or comma-separated string. Valid Nepali mobile formats only (98XXXXXXXX / 97XXXXXXXX, with optional +977).stringRaw message content. Required when template_id is not provided. Not allowed for OTP messages.string (UUID)Verified active template ID. Required for OTP flow and recommended for reusable messages.objectTemplate variables, e.g. { otp: '123456', app_name: 'AppName' }. For OTP templates, all declared variables are required and must be non-empty.stringSender ID to use. Defaults to your account's default sender IDstringEncoding type: 'text' | 'unicode' | 'flash'. Default: 'text'.stringBusiness type: 'promotional' | 'transactional' | 'otp'. Default: 'transactional'. If template_id is used, message_type must match template type (or be omitted).Example Request
// 1) Single transactional SMS (raw message)
const sendTransactionalSMS = async () => {
const response = await fetch('https://api.grosms.com/api/v1/sms/send', {
method: 'POST',
headers: {
'X-API-Key': 'nsms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
to: '98XXXXXXX',
message: 'Your Content Here!',
type: 'text',
message_type: 'transactional'
})
});
return await response.json();
};
// 2) OTP SMS (must use verified OTP template)
const sendOtpSMS = async () => {
const response = await fetch('https://api.grosms.com/api/v1/sms/send', {
method: 'POST',
headers: {
'X-API-Key': 'nsms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'Content-Type': 'application/json'
},
body: JSON.stringify({
to: '98XXXXXXX',
template_id: '550e8400-e29b-41d4-a716-446655440000',
message_type: 'otp',
variables: {
otp: '123456',
app_name: 'YourApp!'
}
})
});
return await response.json();
};/api/v1/sms/balanceGet your current wallet balance and usage statistics.
Example Request
const checkBalance = async () => {
const response = await fetch('https://api.grosms.com/api/v1/sms/balance', {
method: 'GET',
headers: {
'X-API-Key': 'nsms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}
});
return await response.json();
};/api/v1/sms/status/:idCheck status by message_id or batch_id. Returns single-message detail or batch summary with per-message statuses.
Parameters
string (UUID)A message_id or batch_id returned from send APIExample Request
const getStatus = async (id) => {
const response = await fetch(
'https://api.grosms.com/api/v1/sms/status/' + id,
{
method: 'GET',
headers: {
'X-API-Key': 'nsms_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
}
}
);
return await response.json();
};Template Usage
Create reusable message templates with dynamic variables for consistent, personalized communication.
1. Create a Template via API
Requires the sms:template permission on your API key. Variables are auto-detected — anything wrapped in {curly_braces} becomes a variable. New templates are created unverified. An admin must approve the template before its id can be used.
/api/v1/sms/templatesParameters
'Your OTP is {otp}'.2. Check Verification Status
List your templates or fetch one by ID to check whether it has been approved yet (is_verified: true).
/api/v1/sms/templates3. Send SMS Using the Template
Once the template is verified, pass the template_id and a variables object to the send endpoint.
Error Codes Reference
All error responses follow this shape: { "success": false, "error": "Human-readable message", "code": "ERROR_CODE" }
| Code | HTTP | Description | Fix |
|---|---|---|---|
| NO_API_KEY | 401 | No API key in request | Add X-API-Key header |
| INVALID_API_KEY | 401 | Key not found or malformed | Check your key value |
| API_KEY_EXPIRED | 401 | Key has passed its expiry date | Generate a new key |
| INSUFFICIENT_BALANCE | 400 | Wallet balance too low | Top up your wallet |
| RATE_LIMIT_EXCEEDED | 429 | Too many requests in the time window | Wait retry_after seconds |
Rate Limits
Limits are enforced per API key using per-second, per-minute, and per-hour windows.
- •Per minute: 60,000 requests (default key setting)
- •Per hour: 3,600,000 requests (default key setting)
{
"success": false,
"error": "Too many requests",
"code": "RATE_LIMIT_EXCEEDED",
"message": "API key rate limit exceeded: 1000 requests per minute.",
"retry_after": 60
}