Skip to content

SMS API

Complete reference for the SMS messaging endpoint.

Send SMS

Send SMS messages to one or more recipients.

Endpoint

POST https://api.msgine.net/api/v1/developers/sms

Request

bash
curl -X POST https://api.msgine.net/api/v1/developers/sms \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+256701521269",
    "message": "Hello from MsGine!",
    "from": "MyApp"
  }'

Parameters

ParameterTypeRequiredDescription
tostringYesRecipient number, or several separated by commas
messagestringYesMessage content (max 1000 characters)
fromstringNoSender ID, max 11 characters (default: MsGine)
scheduledForstringNoISO 8601 time to send at
idempotencyKeystringNoMax 64 characters; see below

Ugandan numbers are accepted as +256701521269, 256701521269, 0701521269 or 701521269, and normalised to E.164. Invalid numbers are skipped and reported in metadata.invalidNumbersSkipped; if none remain, the request returns 400.

Message length is billed in 160-character units.

Response

Status Code: 200 OK

json
{
  "id": "9c2d5040-a8c2-4569-a55b-03b7d99d69f5",
  "sid": null,
  "channel": "sms",
  "to": ["+256701521269"],
  "from": "MyApp",
  "content": "Hello from MsGine!",
  "status": "pending",
  "cost": 30,
  "currency": "UGX",
  "sandbox": false,
  "createdAt": "2026-02-17T10:30:00.000Z",
  "metadata": {
    "recipientsProcessed": 1,
    "invalidNumbersSkipped": 0,
    "duplicatesRemoved": 0,
    "smsCount": 1,
    "messageLength": 18,
    "costPerSms": 30
  }
}

status is pending until the carrier accepts the message; sid is populated by the provider at that point. Track the outcome with the sms.sent and sms.failed webhooks, or by polling the message by id.

For a sandbox key, sandbox is true, cost is 0 and status is sent immediately — nothing is queued or charged.

Send to Multiple Recipients

Send the same message to multiple recipients:

bash
curl -X POST https://api.msgine.net/api/v1/developers/sms \
  -H "X-Api-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+256701521269,+256701234567,+256709876543",
    "message": "Batch message to all recipients"
  }'

Response:

json
{
  "id": "msg_1234567890",
  "sid": "SM1234567890abcdef",
  "channel": "sms",
  "to": ["+256701521269", "+256701234567", "+256709876543"],
  "from": "MsGine",
  "content": "Batch message to all recipients",
  "status": "pending",
  "cost": 90,
  "currency": "UGX",
  "createdAt": "2024-01-15T10:30:00Z"
}

Get Message History

Retrieve a paginated list of sent messages.

Endpoint

GET https://api.msgine.net/api/v1/developers/sms/history

Request

bash
curl "https://api.msgine.net/api/v1/developers/sms/history?page=1&limit=20" \
  -H "X-Api-Key: YOUR_API_KEY"

Query Parameters

ParameterTypeRequiredDescription
pagenumberNoPage number (default: 1)
limitnumberNoItems per page (default: 20, max: 100)

Response

Status Code: 200 OK

json
{
  "data": [
    {
      "id": "msg_1234567890",
      "status": "delivered",
      "to": ["+256701521269"],
      "content": "Hello from MsGine!",
      "cost": 30,
      "currency": "UGX",
      "createdAt": "2024-01-15T10:30:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 247,
    "pages": 13
  }
}

Message Status

Messages can have the following statuses:

StatusDescription
pendingMessage is queued for delivery
sentMessage has been sent to the carrier
deliveredMessage was successfully delivered
failedMessage delivery failed

Phone Number Format

All phone numbers must be in E.164 format:

+[country code][number]

Examples:

  • +256701521269 (Uganda)
  • +14155552671 (United States)
  • +447911123456 (United Kingdom)
  • 0701521269 (missing country code)
  • 256701521269 (missing + prefix)

Sender ID

The from parameter sets the sender ID displayed to recipients:

Alphanumeric Sender ID

json
{
  "from": "MyApp",
  "to": "+256701521269",
  "message": "Hello!"
}

Rules:

  • Max 11 characters
  • Alphanumeric only (A-Z, 0-9)
  • No spaces or special characters
  • May not be supported in all countries

Message Length

Single SMS

  • Standard (GSM-7): 160 characters
  • Unicode: 70 characters

Concatenated SMS

Messages longer than a single SMS are split into multiple parts:

  • Standard (GSM-7): 153 characters per part
  • Unicode: 67 characters per part
  • Maximum: 1000 characters

Pricing

SMS pricing in Uganda is 30 UGX per message. Costs are shown in the response:

json
{
  "cost": 30,
  "currency": "UGX"
}

For messages to multiple recipients, the cost is multiplied by the number of recipients.

Error Responses

400 Bad Request

Invalid request parameters:

json
{
  "error": {
    "code": "invalid_phone_number",
    "message": "The phone number must be in E.164 format",
    "details": {
      "field": "to",
      "value": "0701234567"
    }
  }
}

401 Unauthorized

Invalid or missing API key:

json
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key"
  }
}

402 Payment Required

Insufficient account balance:

json
{
  "error": {
    "code": "insufficient_balance",
    "message": "Insufficient account balance",
    "details": {
      "balance": 20,
      "required": 90,
      "currency": "UGX"
    }
  }
}

429 Too Many Requests

Rate limit exceeded:

json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Please try again later.",
    "retryAfter": 60
  }
}

Webhooks

Webhooks are registered once per account and apply to every message; there is no per-message callback field. Register one for sms.sent and sms.failed, and MsGine posts to it as each message resolves:

json
{
  "event": "sms.sent",
  "channel": "sms",
  "messageId": "9c2d5040-a8c2-4569-a55b-03b7d99d69f5",
  "timestamp": "2026-02-17T10:30:15.663Z",
  "data": {
    "to": "+256701521269",
    "from": "MyApp",
    "message": "Your verification code is 123456",
    "sid": "SM1234567890abcdef"
  }
}

See Webhooks for registration, signature verification and retry behaviour.

Next Steps

Released under the MIT License.