SMS & Templates
Send single messages, dispatch bulk campaigns, check delivery status, and manage reusable message templates.
POST /messages/send
Send a single SMS to one recipient.
| Param | Type | Required | Description |
|---|---|---|---|
| to | string | Yes | Recipient phone number (10-digit local or 13-digit with 977 country code, must start 97/98). |
| message | string | Yes | Message body. |
Example response
{
"message_id": 501,
"status": "queued"
}| Status | Error | When |
|---|---|---|
| 400 | to is required | `to` missing from body |
| 400 | message is required | `message` missing from body |
| 400 | Phone number must be 10 or 13 digits | invalid phone format |
| 401 | API key required | x-api-key header missing |
| 401 | Invalid or inactive API key | key does not match an active key |
curl -X POST 'https://api.grosms.com/api/messages/send' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"to":"9800000000","message":"Hello from GroSMS!"}'GET /messages/send/:id
Get the delivery status of a message you sent via the API.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Message ID returned by Send SMS. |
Example response
{
"message": {
"id": 501,
"recipient": "9800000000",
"body": "Hello from GroSMS!",
"status": "delivered",
"segments": 1,
"charset": "gsm",
"sent_at": "2026-07-11T09:00:00.000Z",
"delivered_at": "2026-07-11T09:00:03.000Z"
}
}| Status | Error | When |
|---|---|---|
| 404 | Message not found | id does not belong to this API key's account |
| 401 | API key required | x-api-key header missing |
| 401 | Invalid or inactive API key | key does not match an active key |
curl -X GET 'https://api.grosms.com/api/messages/send/501' \
-H 'x-api-key: YOUR_API_KEY'GET /messages
List sent messages with pagination and status filtering.
| Param | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number, default 1. |
| limit | number | No | Page size, default 50, max 100. |
| status | string | No | Filter: queued | sent | delivered | failed | rejected. |
Example response
{
"messages": [
{
"id": 501,
"recipient": "9800000000",
"body": "Hello!",
"status": "delivered"
}
],
"pagination": {
"total": 1,
"page": 1,
"limit": 50,
"pages": 1
}
}| Status | Error | When |
|---|---|---|
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/messages?page=1&limit=50&status=delivered' \
-H 'x-api-key: YOUR_API_KEY'GET /messages/:id
Get a single message by ID, including campaign and contact info.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Message ID. |
Example response
{
"message": {
"id": 501,
"recipient": "9800000000",
"body": "Hello!",
"status": "delivered",
"campaign": null,
"contact": null
}
}| Status | Error | When |
|---|---|---|
| 404 | Message not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/messages/501' \
-H 'x-api-key: YOUR_API_KEY'GET /campaigns
List all bulk SMS campaigns.
Example response
{
"campaigns": [
{
"id": 1,
"name": "Promo Blast",
"status": "draft",
"recipient_count": 120
}
]
}| Status | Error | When |
|---|---|---|
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/campaigns' \
-H 'x-api-key: YOUR_API_KEY'GET /campaigns/:id
Get a campaign with its recipient list.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Campaign ID. |
Example response
{
"campaign": {
"id": 1,
"name": "Promo Blast",
"message": "Hello!",
"status": "draft",
"campaignRecipients": []
}
}| Status | Error | When |
|---|---|---|
| 404 | Campaign not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/campaigns/1' \
-H 'x-api-key: YOUR_API_KEY'POST /campaigns
Create a draft campaign.
| Param | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Campaign name. |
| message | string | Yes | Message body sent to every recipient. |
| scheduled_at | string | No | ISO datetime to schedule for (not auto-sent yet). |
Example response
{
"campaign": {
"id": 1,
"name": "Promo Blast",
"status": "draft",
"recipient_count": 0
}
}| Status | Error | When |
|---|---|---|
| 400 | Name and message are required | missing name or message |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X POST 'https://api.grosms.com/api/campaigns' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"Promo Blast","message":"Big sale this weekend!","scheduled_at":"2026-08-01T09:00:00.000Z"}'PUT /campaigns/:id
Update a campaign's name, message, status, or schedule.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Campaign ID. |
| name | string | Yes | Campaign name. |
| message | string | Yes | Message body. |
| status | string | No | draft | scheduled | sent | cancelled. |
Example response
{
"campaign": {
"id": 1,
"name": "Promo Blast v2",
"status": "scheduled"
}
}| Status | Error | When |
|---|---|---|
| 404 | Campaign not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X PUT 'https://api.grosms.com/api/campaigns/1' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"Promo Blast v2","message":"Updated offer!","status":"scheduled"}'DELETE /campaigns/:id
Delete a campaign and its recipient links.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Campaign ID. |
Example response
{
"message": "Campaign deleted successfully"
}| Status | Error | When |
|---|---|---|
| 404 | Campaign not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X DELETE 'https://api.grosms.com/api/campaigns/1' \
-H 'x-api-key: YOUR_API_KEY'POST /campaigns/:id/recipients
Add a phone number to a campaign's audience (creates the contact if it doesn't exist).
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Campaign ID. |
| phone | string | Yes | Recipient phone number. |
Example response
{
"recipient": {
"id": 55,
"campaign_id": 1,
"contact_id": 10
},
"contact": {
"id": 10,
"phone": "9800000000"
},
"isNew": true
}| Status | Error | When |
|---|---|---|
| 404 | Campaign not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X POST 'https://api.grosms.com/api/campaigns/1/recipients' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"phone":"9800000000"}'POST /campaigns/:id/send
`{{name}}`/`{{phone}}` in the campaign's message are replaced with each recipient's own contact info. Debits credits for the sum of every recipient's message-segment count, then queues one personalized message per recipient. `total_cost` reflects the credit amount for metered accounts — accounts with no per-message rate configured are not actually charged even though this field is still populated.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Campaign ID (must be in draft status with at least one recipient). |
Example response
{
"campaign": {
"id": 1,
"name": "Promo Blast",
"status": "sent"
},
"sent_count": 120,
"total_cost": 137
}| Status | Error | When |
|---|---|---|
| 404 | Campaign not found | id does not belong to this API key's account |
| 400 | Campaign has already been sent or is not in draft status | status is not draft |
| 400 | Campaign has no recipients | no recipients added yet |
| 400 | Insufficient credits. Please load credits to continue. | balance can't cover the sum of every recipient's message-segment count |
| 401 | API key required | x-api-key header missing |
| 401 | Invalid or inactive API key | key does not match an active key |
curl -X POST 'https://api.grosms.com/api/campaigns/1/send' \
-H 'x-api-key: YOUR_API_KEY'GET /templates
List saved SMS templates.
Example response
{
"templates": [
{
"id": 1,
"name": "Welcome",
"body": "Hi {{name}}, welcome to GroSMS!"
}
]
}| Status | Error | When |
|---|---|---|
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/templates' \
-H 'x-api-key: YOUR_API_KEY'GET /templates/:id
Get a single template.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Template ID. |
Example response
{
"template": {
"id": 1,
"name": "Welcome",
"body": "Hi {{name}}, welcome to GroSMS!"
}
}| Status | Error | When |
|---|---|---|
| 404 | Template not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/templates/1' \
-H 'x-api-key: YOUR_API_KEY'POST /templates
Create a template. `{{name}}` placeholder syntax is stored as-is, not server-interpolated.
| Param | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Template name. |
| body | string | Yes | Template body. |
Example response
{
"template": {
"id": 1,
"name": "Welcome",
"body": "Hi {{name}}, welcome to GroSMS!"
}
}| Status | Error | When |
|---|---|---|
| 400 | Name and body are required | missing name or body |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X POST 'https://api.grosms.com/api/templates' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"Welcome","body":"Hi {{name}}, welcome to GroSMS!"}'PUT /templates/:id
Update a template.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Template ID. |
| name | string | Yes | Template name. |
| body | string | Yes | Template body. |
Example response
{
"template": {
"id": 1,
"name": "Welcome v2",
"body": "Hi {{name}}, thanks for joining!"
}
}| Status | Error | When |
|---|---|---|
| 404 | Template not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X PUT 'https://api.grosms.com/api/templates/1' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"Welcome v2","body":"Hi {{name}}, thanks for joining!"}'DELETE /templates/:id
Delete a template.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Template ID. |
Example response
{
"message": "Template deleted successfully"
}| Status | Error | When |
|---|---|---|
| 404 | Template not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X DELETE 'https://api.grosms.com/api/templates/1' \
-H 'x-api-key: YOUR_API_KEY'OTP
Generate and verify one-time passcodes for login, signup, or transaction confirmation. Requires an OTP template configured in your dashboard first.
POST /otp/generate
Generate and send an OTP using a template created in your GroSMS dashboard.
| Param | Type | Required | Description |
|---|---|---|---|
| templateId | number | Yes | OTP template ID from your dashboard (Settings → OTP Templates). |
| phone | string | Yes | Recipient phone number. |
| parameters | object | No | Values for any caller variables the template uses: first_name, last_name, email, user_id. |
Example response
{
"token": "9f1c2e...64hex",
"phone": "9800000000"
}| Status | Error | When |
|---|---|---|
| 400 | templateId and phone are required | missing required field |
| 404 | Template not found | templateId doesn't belong to this account |
| 400 | Missing required parameter(s): first_name | template needs a caller variable you didn't supply |
| 502 | Failed to send OTP SMS | SMS gateway send failed |
| 401 | API key required | x-api-key header missing |
| 401 | Invalid or inactive API key | key does not match an active key |
curl -X POST 'https://api.grosms.com/api/otp/generate' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"templateId":5,"phone":"9800000000","parameters":"{\"first_name\":\"Sita\"}"}'POST /otp/verify
Verify an OTP code against the token returned by Generate OTP.
| Param | Type | Required | Description |
|---|---|---|---|
| token | string | Yes | Token from Generate OTP. |
| code | string | Yes | 6-digit code the user received. |
Example response
{
"message": "OTP verified successfully",
"phone": "9800000000"
}| Status | Error | When |
|---|---|---|
| 400 | Invalid OTP token | token unknown or belongs to another account |
| 400 | OTP has expired | more than 5 minutes since generation |
| 400 | OTP already verified | token already used |
| 400 | Invalid OTP code | code does not match |
| 429 | Maximum OTP attempts exceeded | 5 wrong attempts made |
| 401 | API key required | x-api-key header missing |
| 401 | Invalid or inactive API key | key does not match an active key |
curl -X POST 'https://api.grosms.com/api/otp/verify' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"token":"9f1c2e...64hex","code":"384729"}'GET /otp/status
Check the verification status of an OTP request.
| Param | Type | Required | Description |
|---|---|---|---|
| token | string | Yes | Token from Generate OTP. |
Example response
{
"verified_at": null,
"attempts": 1,
"max_attempts": 5,
"expires_at": "2026-07-11T09:05:00.000Z",
"expired": false
}| Status | Error | When |
|---|---|---|
| 400 | Token is required | query param missing |
| 404 | OTP request not found | token unknown or belongs to another account |
| 401 | API key required | x-api-key header missing |
| 401 | Invalid or inactive API key | key does not match an active key |
curl -X GET 'https://api.grosms.com/api/otp/status?token=9f1c2e...64hex' \
-H 'x-api-key: YOUR_API_KEY'Contacts
Manage your recipient list and organize contacts into groups for targeted campaigns.
GET /contacts
List contacts, optionally filtered by group.
| Param | Type | Required | Description |
|---|---|---|---|
| group_id | number | No | Filter by contact group ID. |
Example response
{
"contacts": [
{
"id": 10,
"name": "Sita Rai",
"phone": "9800000000",
"group": {
"id": 3,
"name": "VIP"
}
}
]
}| Status | Error | When |
|---|---|---|
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/contacts?group_id=3' \
-H 'x-api-key: YOUR_API_KEY'GET /contacts/:id
Get a single contact.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Contact ID. |
Example response
{
"contact": {
"id": 10,
"name": "Sita Rai",
"phone": "9800000000",
"group": null
}
}| Status | Error | When |
|---|---|---|
| 404 | Contact not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/contacts/10' \
-H 'x-api-key: YOUR_API_KEY'POST /contacts
Create a contact.
| Param | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Contact name. |
| phone | string | Yes | Phone number. |
| group_id | number | No | Contact group ID. |
Example response
{
"contact": {
"id": 10,
"name": "Sita Rai",
"phone": "9800000000",
"group": null
}
}| Status | Error | When |
|---|---|---|
| 400 | Name and phone are required | missing name or phone |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X POST 'https://api.grosms.com/api/contacts' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"Sita Rai","phone":"9800000000","group_id":3}'PUT /contacts/:id
Update a contact.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Contact ID. |
| name | string | Yes | Contact name. |
| phone | string | Yes | Phone number. |
| group_id | number | No | Contact group ID. |
Example response
{
"contact": {
"id": 10,
"name": "Sita Rai Thapa",
"phone": "9800000000",
"group": null
}
}| Status | Error | When |
|---|---|---|
| 404 | Contact not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X PUT 'https://api.grosms.com/api/contacts/10' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"Sita Rai Thapa","phone":"9800000000","group_id":3}'DELETE /contacts/:id
Delete a contact.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Contact ID. |
Example response
{
"message": "Contact deleted successfully"
}| Status | Error | When |
|---|---|---|
| 404 | Contact not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X DELETE 'https://api.grosms.com/api/contacts/10' \
-H 'x-api-key: YOUR_API_KEY'GET /contact-groups
List contact groups with member counts.
Example response
{
"groups": [
{
"id": 3,
"name": "VIP",
"contact_count": 42
}
]
}| Status | Error | When |
|---|---|---|
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/contact-groups' \
-H 'x-api-key: YOUR_API_KEY'POST /contact-groups
Create a contact group.
| Param | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Group name. |
Example response
{
"group": {
"id": 3,
"name": "VIP",
"contact_count": 0
}
}| Status | Error | When |
|---|---|---|
| 400 | Group name is required | missing name |
| 409 | Group already exists | name already used by this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X POST 'https://api.grosms.com/api/contact-groups' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"VIP"}'PUT /contact-groups/:id
Rename a contact group.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Group ID. |
| name | string | Yes | New group name. |
Example response
{
"group": {
"id": 3,
"name": "Platinum"
}
}| Status | Error | When |
|---|---|---|
| 400 | Group name is required | missing name |
| 404 | Group not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X PUT 'https://api.grosms.com/api/contact-groups/3' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"Platinum"}'DELETE /contact-groups/:id
Delete a contact group. Members are kept, ungrouped.
| Param | Type | Required | Description |
|---|---|---|---|
| id | number | Yes | Group ID. |
Example response
{
"message": "Group deleted"
}| Status | Error | When |
|---|---|---|
| 404 | Group not found | id does not belong to this account |
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X DELETE 'https://api.grosms.com/api/contact-groups/3' \
-H 'x-api-key: YOUR_API_KEY'Credits
Check your available SMS credit balance and review your transaction history.
GET /credits
Check your available SMS credit balance.
Example response
{
"available": 5000,
"usable": 4800,
"hold": 200,
"rate": 0.85
}| Status | Error | When |
|---|---|---|
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/credits' \
-H 'x-api-key: YOUR_API_KEY'GET /credits/transactions
List your credit transaction history.
| Param | Type | Required | Description |
|---|---|---|---|
| page | number | No | Page number, default 1. |
| limit | number | No | Page size, default 50, max 100. |
Example response
{
"transactions": [
{
"id": 1,
"type": "campaign",
"amount": -120,
"description": "Campaign \"Promo Blast\" send (120 recipients)"
}
],
"pagination": {
"total": 1,
"page": 1,
"limit": 50,
"pages": 1
}
}| Status | Error | When |
|---|---|---|
| 401 | Authentication required | this endpoint still requires dashboard login (Bearer token), not an API key — see badge above |
curl -X GET 'https://api.grosms.com/api/credits/transactions?page=1&limit=50' \
-H 'x-api-key: YOUR_API_KEY'