SMSHorizon API
Send SMS messages, track delivery status, and manage your account through a simple REST API. Integrate in minutes with any language.
Authentication
All requests require a valid user and apikey. You can authenticate using either method below.
Method 1 — Bearer Token
Send your API key in the Authorization header and include your username in the request body.
Authorization: Bearer your_api_key_here
Recommended for production. Bearer Token keeps your API key out of URLs, server logs, and browser history. Always use HTTPS.
Method 2 — Request Parameters
Pass both user and apikey as POST body parameters. Supported for backward compatibility and quick testing.
All endpoints support both POST and GET methods. POST is recommended for production as parameters are sent in the request body rather than the URL, keeping your credentials secure.
Error Handling
All errors return a JSON object with an error field and an appropriate HTTP status code.
{
"error": "Description of what went wrong"
}
Status Codes
| 200 | Success — request processed |
| 400 | Bad Request — missing or invalid parameters |
| 401 | Unauthorized — invalid user or API key |
| 403 | Forbidden — IP not authorized |
| 404 | Not Found — resource not found |
| 405 | Method Not Allowed — only GET and POST accepted |
| 429 | Too Many Requests — temporarily blocked |
Response Format
All API responses are returned as JSON. By default, responses are minified — whitespace stripped to keep payload size small. Sample responses throughout this documentation are shown indented for readability.
Pretty-Printed Output
For debugging or manual cURL testing, append prettyprint=1 to any request to receive an indented response. The parameter works on both GET and POST requests and applies to success as well as error responses.
| Parameter | Type | Required | Description |
|---|---|---|---|
| prettyprint | string | Optional | Set to 1 to receive indented JSON. Any other value (or omitted) returns minified output. |
Example
# Minified (default) curl -X POST "https://smshorizon.co.in/api/v2/balance.php" \ -H "Authorization: Bearer your_api_key" \ -d "user=myuser" # → {"user":"myuser","balance":"5000"} # Pretty-printed curl -X POST "https://smshorizon.co.in/api/v2/balance.php" \ -H "Authorization: Bearer your_api_key" \ -d "user=myuser&prettyprint=1"
Production tip: Leave prettyprint off in production. Minified responses are 20–30% smaller, which matters for high-volume integrations. Use prettyprint=1 only when debugging from a terminal.
Send SMS
Send a single or bulk SMS message. Supports text (ASCII) and Unicode messages. Returns a message ID for single messages or a campaign ID for bulk sends.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| user | string | Required | Your account username |
| apikey | string | Required | Your API key (or use Bearer token header) |
| mobile | string | Required | Recipient mobile number(s). For bulk, separate with commas. Last 10 digits are used. |
| senderid | string | Required | Approved Sender ID (max 6 characters) |
| message | string | Required | Message content. Max 1530 characters for text, 441 for unicode. |
| tid | string | Required | DLT Template ID registered with your DLT operator. Must match the message content template. |
| type | string | Optional | txt for English/ASCII (default), uni for Unicode/regional languages. Defaults to txt if not specified. |
Success Response — Single Message
{
"msgid": "938471625",
"mobile": "8870522522",
"sender": "HORIZN",
"type": "txt",
"msg_count": "1",
"route": "airtel",
"balance_after": "4999"
}
Success Response — Bulk Message
{
"campid": "501",
"total_messages": "50",
"sender": "HORIZN",
"type": "txt",
"msg_count_each": "1",
"route": "airtel",
"balance_after": "4950"
}
Code Examples
# Single message curl -X POST "https://smshorizon.co.in/api/v2/sendsms.php" \ -H "Authorization: Bearer your_api_key" \ -d "user=myuser&mobile=8870522522&senderid=HORIZN&message=Hello from SMSHorizon&tid=1107160521253456789&type=txt" # Bulk message (comma-separated numbers) curl -X POST "https://smshorizon.co.in/api/v2/sendsms.php" \ -H "Authorization: Bearer your_api_key" \ -d "user=myuser&mobile=8870522522,9788522522&senderid=HORIZN&message=Hello from SMSHorizon&tid=1107160521253456789&type=txt"
<?php $url = "https://smshorizon.co.in/api/v2/sendsms.php"; $api_key = "your_api_key"; $post_data = [ 'user' => 'myuser', 'mobile' => '8870522522', 'senderid' => 'HORIZN', 'message' => 'Hello from SMSHorizon', 'tid' => '1107160521253456789', 'type' => 'txt' ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer " . $api_key ]); $response = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $data = json_decode($response, true); if ($http_code === 200) { echo "Message ID: " . $data['msgid'] . "\n"; echo "Balance: " . $data['balance_after'] . "\n"; } else { echo "Error: " . $data['error'] . "\n"; }
import requests url = "https://smshorizon.co.in/api/v2/sendsms.php" headers = {"Authorization": "Bearer your_api_key"} payload = { "user": "myuser", "mobile": "8870522522", "senderid": "HORIZN", "message": "Hello from SMSHorizon", "tid": "1107160521253456789", "type": "txt" } response = requests.post(url, headers=headers, data=payload) data = response.json() if response.status_code == 200: print(f"Message ID: {data['msgid']}") print(f"Balance: {data['balance_after']}") else: print(f"Error: {data['error']}")
const fetch = require('node-fetch'); async function sendSMS() { const params = new URLSearchParams({ user: "myuser", mobile: "8870522522", senderid: "HORIZN", message: "Hello from SMSHorizon", tid: "1107160521253456789", type: "txt" }); const response = await fetch("https://smshorizon.co.in/api/v2/sendsms.php", { method: "POST", headers: { "Authorization": "Bearer your_api_key", "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString() }); const data = await response.json(); if (response.ok) { console.log(`Message ID: ${data.msgid}`); console.log(`Balance: ${data.balance_after}`); } else { console.error(`Error: ${data.error}`); } } sendSMS();
import java.net.http.*; import java.net.URI; public class SendSMS { public static void main(String[] args) throws Exception { String url = "https://smshorizon.co.in/api/v2/sendsms.php"; String body = "user=myuser&mobile=8870522522&senderid=HORIZN&message=Hello from SMSHorizon&tid=1107160521253456789&type=txt"; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer your_api_key") .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Status: " + response.statusCode()); System.out.println("Body: " + response.body()); } }
using System.Net.Http; using System.Text.Json; var client = new HttpClient(); var url = "https://smshorizon.co.in/api/v2/sendsms.php"; client.DefaultRequestHeaders.Add( "Authorization", "Bearer your_api_key" ); var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("user", "myuser"), new KeyValuePair<string, string>("mobile", "8870522522"), new KeyValuePair<string, string>("senderid", "HORIZN"), new KeyValuePair<string, string>("message", "Hello from SMSHorizon"), new KeyValuePair<string, string>("tid", "1107160521253456789"), new KeyValuePair<string, string>("type", "txt") }); var response = await client.PostAsync(url, content); var body = await response.Content.ReadAsStringAsync(); var data = JsonSerializer.Deserialize<JsonElement>(body); if (response.IsSuccessStatusCode) { Console.WriteLine($"Message ID: {data.GetProperty("msgid")}"); Console.WriteLine($"Balance: {data.GetProperty("balance_after")}"); } else { Console.WriteLine($"Error: {data.GetProperty("error")}"); }
Get Message Status
Retrieve the delivery status of an SMS by message ID, or by campaign ID and mobile number.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| user | string | Required | Your account username |
| apikey | string | Required | Your API key (or use Bearer token header) |
| msgid | integer | Conditional | Message ID to look up. Required if campid is not provided. |
| campid | integer | Conditional | Campaign ID. Must be paired with mobile. |
| mobile | string | Conditional | 10-digit mobile number. Required when using campid. |
Success Response
{
"msgid": "938471625",
"status": "DELIVRD",
"mobile": "8870522522",
"sender": "HORIZN",
"msg_count": "1",
"type": "txt",
"route": "airtel",
"submit_time": "2026-05-03 10:30:00",
"done_time": "2026-05-03 10:30:05",
"error_code": "",
"error_desc": ""
}
Code Examples
# By message ID curl -X POST "https://smshorizon.co.in/api/v2/status.php" \ -H "Authorization: Bearer your_api_key" \ -d "user=myuser&msgid=938471625" # By campaign ID + mobile curl -X POST "https://smshorizon.co.in/api/v2/status.php" \ -H "Authorization: Bearer your_api_key" \ -d "user=myuser&campid=501&mobile=8870522522"
<?php $url = "https://smshorizon.co.in/api/v2/status.php"; $api_key = "your_api_key"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, "user=myuser&msgid=938471625"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer " . $api_key ]); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true); echo "Status: " . $data['status'] . "\n";
import requests url = "https://smshorizon.co.in/api/v2/status.php" headers = {"Authorization": "Bearer your_api_key"} payload = {"user": "myuser", "msgid": "938471625"} response = requests.post(url, headers=headers, data=payload) data = response.json() print(f"Status: {data['status']}")
const params = new URLSearchParams({ user: "myuser", msgid: "938471625" }); const response = await fetch("https://smshorizon.co.in/api/v2/status.php", { method: "POST", headers: { "Authorization": "Bearer your_api_key", "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString() }); const data = await response.json(); console.log(`Status: ${data.status}`);
import java.net.http.*; import java.net.URI; public class GetStatus { public static void main(String[] args) throws Exception { String url = "https://smshorizon.co.in/api/v2/status.php"; String body = "user=myuser&msgid=938471625"; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer your_api_key") .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Status: " + response.statusCode()); System.out.println("Body: " + response.body()); } }
using System.Net.Http; using System.Text.Json; var client = new HttpClient(); var url = "https://smshorizon.co.in/api/v2/status.php"; client.DefaultRequestHeaders.Add( "Authorization", "Bearer your_api_key" ); var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("user", "myuser"), new KeyValuePair<string, string>("msgid", "938471625") }); var response = await client.PostAsync(url, content); var body = await response.Content.ReadAsStringAsync(); var data = JsonSerializer.Deserialize<JsonElement>(body); Console.WriteLine($"Status: {data.GetProperty("status")}");
Get Account Info
Returns account details including SMS balance, route, DLT entity ID, registered sender ID and template counts, configured webhook URL, and whitelisted IP addresses for the API key in use.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| user | string | Required | Your account username |
| apikey | string | Required | Your API key (or use Bearer token header) |
Success Response
{
"user": "myuser",
"balance": "5000",
"route": "airtel",
"entity_id": "1101504390000025795",
"sender_ids": 2,
"templates_registered": 24,
"webhook": "",
"whitelisted_ip": ["203.0.113.10"]
}
Response Fields
| Field | Type | Description |
|---|---|---|
| balance | string | Current SMS credit balance. |
| route | string | SMS route configured for the account (e.g. airtel). |
| entity_id | string | DLT Principal Entity ID registered against the account. |
| sender_ids | integer | Number of approved Sender IDs on the account. |
| templates_registered | integer | Number of DLT templates registered against the account. |
| webhook | string | Configured webhook URL for delivery reports. Empty string when not set. |
| whitelisted_ip | array | IP addresses authorized for this API key. Empty array means no IP restriction is enforced. |
Code Examples
curl -X POST "https://smshorizon.co.in/api/v2/account.php" \ -H "Authorization: Bearer your_api_key" \ -d "user=myuser"
<?php $url = "https://smshorizon.co.in/api/v2/account.php"; $api_key = "your_api_key"; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, "user=myuser"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer " . $api_key ]); $response = curl_exec($ch); curl_close($ch); $data = json_decode($response, true); echo "Balance: " . $data['balance'] . "\n"; echo "Route: " . $data['route'] . "\n"; echo "Entity ID: " . $data['entity_id'] . "\n";
import requests url = "https://smshorizon.co.in/api/v2/account.php" headers = {"Authorization": "Bearer your_api_key"} payload = {"user": "myuser"} response = requests.post(url, headers=headers, data=payload) data = response.json() print(f"Balance: {data['balance']}") print(f"Route: {data['route']}") print(f"Entity ID: {data['entity_id']}")
const params = new URLSearchParams({ user: "myuser" }); const response = await fetch("https://smshorizon.co.in/api/v2/account.php", { method: "POST", headers: { "Authorization": "Bearer your_api_key", "Content-Type": "application/x-www-form-urlencoded" }, body: params.toString() }); const data = await response.json(); console.log(`Balance: ${data.balance}`); console.log(`Route: ${data.route}`); console.log(`Entity ID: ${data.entity_id}`);
import java.net.http.*; import java.net.URI; public class GetAccount { public static void main(String[] args) throws Exception { String url = "https://smshorizon.co.in/api/v2/account.php"; String body = "user=myuser"; HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(url)) .header("Authorization", "Bearer your_api_key") .header("Content-Type", "application/x-www-form-urlencoded") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString() ); System.out.println("Status: " + response.statusCode()); System.out.println("Body: " + response.body()); } }
using System.Net.Http; using System.Text.Json; var client = new HttpClient(); var url = "https://smshorizon.co.in/api/v2/account.php"; client.DefaultRequestHeaders.Add( "Authorization", "Bearer your_api_key" ); var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("user", "myuser") }); var response = await client.PostAsync(url, content); var body = await response.Content.ReadAsStringAsync(); var data = JsonSerializer.Deserialize<JsonElement>(body); Console.WriteLine($"Balance: {data.GetProperty("balance")}"); Console.WriteLine($"Route: {data.GetProperty("route")}"); Console.WriteLine($"Entity ID: {data.GetProperty("entity_id")}");
Webhooks — Delivery Reports
SMSHorizon can push delivery reports to your server in real time as messages are delivered, failed, or expired. This removes the need to call the Get Message Status endpoint for each message.
Configuration
Set your webhook URL inside the SMSHorizon control panel under SMS API → Webhook. Once saved, SMSHorizon will POST a JSON payload to that URL for every status update on messages sent from your account.
Your endpoint must be reachable over HTTPS, accept POST requests, and respond with HTTP 200 to acknowledge receipt.
Request
Payload
SMSHorizon sends a JSON body containing the same fields returned by the Get Message Status endpoint.
{
"msgid": "938471625",
"status": "DELIVRD",
"mobile": "8870522522",
"sender": "HORIZN",
"msg_count": "1",
"type": "txt",
"route": "airtel",
"submit_time": "2026-05-03 10:30:00",
"done_time": "2026-05-03 10:30:05",
"error_code": "",
"error_desc": ""
}
Receiver Examples
<?php // Read the JSON payload $payload = json_decode(file_get_contents("php://input"), true); if (!$payload) { http_response_code(400); exit; } $msgid = $payload['msgid']; $status = $payload['status']; $mobile = $payload['mobile']; $done_time = $payload['done_time']; // ... update your database ... // Acknowledge receipt http_response_code(200); echo "OK";
from flask import Flask, request app = Flask(__name__) @app.route("/sms-webhook", methods=["POST"]) def sms_webhook(): payload = request.get_json() if not payload: return "", 400 msgid = payload["msgid"] status = payload["status"] mobile = payload["mobile"] done_time = payload["done_time"] # ... update your database ... return "OK", 200
const express = require("express"); const app = express(); app.use(express.json()); app.post("/sms-webhook", (req, res) => { const payload = req.body; if (!payload) return res.sendStatus(400); const { msgid, status, mobile, done_time } = payload; // ... update your database ... res.sendStatus(200); }); app.listen(3000);
import org.springframework.web.bind.annotation.*; import org.springframework.http.ResponseEntity; import java.util.Map; @RestController public class SmsWebhookController { @PostMapping("/sms-webhook") public ResponseEntity<String> handle(@RequestBody Map<String, Object> payload) { if (payload == null) { return ResponseEntity.badRequest().build(); } String msgid = (String) payload.get("msgid"); String status = (String) payload.get("status"); String mobile = (String) payload.get("mobile"); String doneTime = (String) payload.get("done_time"); // ... update your database ... return ResponseEntity.ok("OK"); } }
using System.Text.Json; var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); app.MapPost("/sms-webhook", async (HttpRequest request) => { var payload = await JsonSerializer.DeserializeAsync<JsonElement>(request.Body); var msgid = payload.GetProperty("msgid").GetString(); var status = payload.GetProperty("status").GetString(); var mobile = payload.GetProperty("mobile").GetString(); var doneTime = payload.GetProperty("done_time").GetString(); // ... update your database ... return Results.Ok("OK"); }); app.Run();
Best practice: Respond with 200 immediately and process the payload asynchronously. Webhooks have a short timeout — slow handlers will be marked as failed and retried, which can lead to duplicate events. Always treat msgid as the Unique Identifier.
© 2026 SMSHorizon. All rights reserved.
Got queries? contact Support