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.