SMSHorizon
Developer Documentation

SMSHorizon API

Send SMS messages, track delivery status, and manage your account through a simple REST API. Integrate in minutes with any language.

Base URL https://smshorizon.co.in/api/v2

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.

Request Header
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 Response Format
{
    "error": "Description of what went wrong"
}

Status Codes

200Success — request processed
400Bad Request — missing or invalid parameters
401Unauthorized — invalid user or API key
403Forbidden — IP not authorized
404Not Found — resource not found
405Method Not Allowed — only GET and POST accepted
429Too 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.

ParameterTypeRequiredDescription
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.

POST /sendsms.php

Parameters

ParameterTypeRequiredDescription
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

200 OK
{
    "msgid":         "938471625",
    "mobile":        "8870522522",
    "sender":        "HORIZN",
    "type":          "txt",
    "msg_count":     "1",
    "route":         "airtel",
    "balance_after": "4999"
}

Success Response — Bulk Message

200 OK
{
    "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.

POST /status.php

Parameters

ParameterTypeRequiredDescription
userstringRequiredYour account username
apikeystringRequiredYour API key (or use Bearer token header)
msgidintegerConditionalMessage ID to look up. Required if campid is not provided.
campidintegerConditionalCampaign ID. Must be paired with mobile.
mobilestringConditional10-digit mobile number. Required when using campid.

Success Response

200 OK
{
    "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.

POST /account.php

Parameters

ParameterTypeRequiredDescription
userstringRequiredYour account username
apikeystringRequiredYour API key (or use Bearer token header)

Success Response

200 OK
{
    "user":                 "myuser",
    "balance":              "5000",
    "route":                "airtel",
    "entity_id":            "1101504390000025795",
    "sender_ids":           2,
    "templates_registered": 24,
    "webhook":              "",
    "whitelisted_ip":       ["203.0.113.10"]
}

Response Fields

FieldTypeDescription
balancestringCurrent SMS credit balance.
routestringSMS route configured for the account (e.g. airtel).
entity_idstringDLT Principal Entity ID registered against the account.
sender_idsintegerNumber of approved Sender IDs on the account.
templates_registeredintegerNumber of DLT templates registered against the account.
webhookstringConfigured webhook URL for delivery reports. Empty string when not set.
whitelisted_iparrayIP 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

POST https://your-server.com/your-webhook-handler

Payload

SMSHorizon sends a JSON body containing the same fields returned by the Get Message Status endpoint.

Sample Payload
{
    "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