Mobile Message API Documentation

The base URL for the API is https://api.mobilemessage.com.au/. This documentation will help you understand how to send and receive SMS messages, set up webhooks for real-time notifications, and track message delivery statuses.

The Mobile Message API allows up to 5 simultaneous requests per account. If you exceed this limit, you'll receive an HTTP 429 error with the message: "Too many concurrent requests. Please wait." Simply wait for an existing request to complete before trying again.

Authentication

Use Basic Authentication with your API username and password to access the endpoints. Follow these steps:

  1. Combine your username:password.
  2. Encode the resulting string in Base64.
  3. Add this string to the Authorization header as: Authorization: Basic {base64_encoded_credentials}.

Code Examples

curl -u user123:mypassword -X GET https://api.mobilemessage.com.au/v1/messages
import requests
from requests.auth import HTTPBasicAuth

response = requests.get('https://api.mobilemessage.com.au/v1/messages', 
                        auth=HTTPBasicAuth('user123', 'mypassword'))
print(response.json())
const username = 'user123';
const password = 'mypassword';

fetch('https://api.mobilemessage.com.au/v1/messages', {
  headers: {
    'Authorization': 'Basic ' + btoa(`${username}:${password}`)
  }
})
.then(response => response.json())
.then(data => console.log(data));
<?php
$ch = curl_init('https://api.mobilemessage.com.au/v1/messages');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "user123:mypassword");
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;

public class APIRequest {
    public static void main(String[] args) throws Exception {
        String credentials = Base64.getEncoder().encodeToString("user123:mypassword".getBytes());
        URL url = new URL("https://api.mobilemessage.com.au/v1/messages");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setRequestProperty("Authorization", "Basic " + credentials);
        connection.setRequestMethod("GET");
        // Process the response...
    }
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

class Program {
    static async Task Main() {
        var client = new HttpClient();
        var byteArray = Encoding.ASCII.GetBytes("user123:mypassword");
        client.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
        var response = await client.GetAsync("https://api.mobilemessage.com.au/v1/messages");
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}

Send SMS Messages

POST /v1/messages

This endpoint allows you to send one or more SMS messages. You can include up to 100 messages in a single request.

Top-level parameters

Parameter Type Description
messages Array of Objects One or more message objects.
enable_unicode (optional) Boolean When true, messages that require UCS-2 (for example emojis or non-GSM characters) are sent using UCS-2. Defaults to false. Each message can still set unicode individually.
max_parts (optional) Integer Maximum SMS parts (credits) per message, applied to all messages in the batch. Messages exceeding this limit are skipped with status error. Default 10, range 1–99.
ignore_unsubscribes (optional) Boolean Set to true to bypass unsubscribe blocking for this send request. If omitted or set to false, normal unsubscribe blocking applies. Use with caution, as bypassing your unsubscribe list could result in spam complaints.

Message object fields

Field Type Description
to String The recipient's phone number, which can be in local Australian format or international format.
message String The message content. Up to 10 parts are supported:
• GSM-7: up to 1530 characters (10 × 153)
• UCS-2: up to 670 characters (10 × 67)
If Unicode is not enabled, non-GSM characters are stripped.

Supports placeholders: {first_name}, {last_name}, {company}, {other}, and {optout}. The contact placeholders are filled from the recipient's saved contact record (if one exists). See below for details.
sender String The mobile number or business name the message will come from. Must be a Sender ID registered in your account — use GET /v1/senders to list your available senders.
custom_ref (optional) String A custom reference to help track the message.
unicode (optional) Boolean Overrides the top-level enable_unicode for this message. When true, the message will be sent using UCS-2 if required.
scheduled_for (optional) String UTC datetime to send this message (ISO 8601, e.g. 2026-04-01T09:00:00). Must be at least 1 minute in the future. If omitted, the message is sent immediately. Scheduled messages can be cancelled via DELETE /v1/messages.

Code examples

curl -u user123:mypassword -X POST https://api.mobilemessage.com.au/v1/messages \
-H "Content-Type: application/json" \
-d '{
  "enable_unicode": true,
  "messages": [
    {
      "to": "0412345678",
      "message": "Hello, this is a test message",
      "sender": "CompanyABC",
      "custom_ref": "tracking001"
    },
    {
      "to": "0412345679",
      "message": "Hello 🌏 from Mobile Message",
      "sender": "CompanyABC",
      "custom_ref": "tracking002",
      "unicode": true
    }
  ]
}'
import requests
from requests.auth import HTTPBasicAuth

data = {
    "enable_unicode": True,
    "messages": [
        {
            "to": "0412345678",
            "message": "Hello, this is a test message",
            "sender": "CompanyABC",
            "custom_ref": "tracking001"
        },
        {
            "to": "0412345679",
            "message": "Hello 🌏 from Mobile Message",
            "sender": "CompanyABC",
            "custom_ref": "tracking002",
            "unicode": true
        }
    ]
}

response = requests.post('https://api.mobilemessage.com.au/v1/messages',
                         json=data, auth=HTTPBasicAuth('user123', 'mypassword'))
print(response.json())
const body = {
  enable_unicode: true,
  messages: [
    {
      to: "0412345678",
      message: "Hello, this is a test message",
      sender: "CompanyABC",
      custom_ref: "tracking001"
    },
    {
      to: "0412345679",
      message: "Hello 🌏 from Mobile Message",
      sender: "CompanyABC",
      custom_ref: "tracking002",
      unicode: true
    }
  ]
};

fetch('https://api.mobilemessage.com.au/v1/messages', {
  method: 'POST',
  headers: {
    'Authorization': 'Basic ' + btoa('user123:mypassword'),
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(body)
})
.then(r => r.json())
.then(console.log);
<?php
$data = [
  "enable_unicode" => true,
  "messages" => [
    [
      "to" => "0412345678",
      "message" => "Hello, this is a test message",
      "sender" => "CompanyABC",
      "custom_ref" => "tracking001"
    ],
    [
      "to" => "0412345679",
      "message" => "Hello 🌏 from Mobile Message",
      "sender" => "CompanyABC",
      "custom_ref" => "tracking002",
      "unicode" => true
    ]
  ]
];

$ch = curl_init('https://api.mobilemessage.com.au/v1/messages');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "user123:mypassword");
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;

public class SendSMS {
    public static void main(String[] args) throws Exception {
        String json = """
        {
          "enable_unicode": true,
          "messages": [
            {"to":"0412345678","message":"Hello, this is a test message","sender":"CompanyABC","custom_ref":"tracking001"},
            {"to":"0412345679","message":"Hello 🌏 from Mobile Message","sender":"CompanyABC","custom_ref":"tracking002","unicode":true}
          ]
        }""";
        String credentials = Base64.getEncoder().encodeToString("user123:mypassword".getBytes());
        URL url = new URL("https://api.mobilemessage.com.au/v1/messages");
        HttpURLConnection c = (HttpURLConnection) url.openConnection();
        c.setRequestMethod("POST");
        c.setRequestProperty("Authorization", "Basic " + credentials);
        c.setRequestProperty("Content-Type", "application/json");
        c.setDoOutput(true);
        try (OutputStream os = c.getOutputStream()) { os.write(json.getBytes("utf-8")); }
        // Handle response...
    }
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;

class Program {
  static async Task Main() {
    var body = new {
      enable_unicode = true,
      messages = new[] {
        new { to = "0412345678", message = "Hello, this is a test message", sender = "CompanyABC", custom_ref = "tracking001" },
        new { to = "0412345679", message = "Hello 🌏 from Mobile Message", sender = "CompanyABC", custom_ref = "tracking002", unicode = true }
      }
    };
    var client = new HttpClient();
    var creds = Convert.ToBase64String(Encoding.ASCII.GetBytes("user123:mypassword"));
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", creds);
    var content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json");
    var resp = await client.PostAsync("https://api.mobilemessage.com.au/v1/messages", content);
    Console.WriteLine(await resp.Content.ReadAsStringAsync());
  }
}

Response example

{
  "status": "complete",
  "ignore_unsubscribes": false,
  "total_cost": 2,
  "results": [
    {
      "to": "0412345678",
      "message": "Hello, this is a test message",
      "sender": "CompanyABC",
      "custom_ref": "tracking001",
      "status": "success",
      "cost": 1,
      "message_id": "abcd1234-efgh-5678-ijkl-9876543210mn",
      "encoding": "gsm7"
    },
    {
      "to": "0412345679",
      "message": "Hello 🌏 from Mobile Message",
      "sender": "CompanyABC",
      "custom_ref": "tracking002",
      "status": "success",
      "cost": 1,
      "message_id": "abcd1234-efgh-5678-ijkl-9876543210xy",
      "encoding": "ucs2"
    }
  ]
}

encoding appears only if Unicode was enabled in the request (either top-level or per message).

Send to List

POST /v1/list-send

Send an SMS to all contacts in a list in a single request. Supports per-contact variable substitution, {optout}, and scheduled delivery. Unsubscribed numbers are automatically filtered unless ignore_unsubscribes is set.

Use GET /v1/messages?custom_ref=your-ref to check delivery status per recipient after sending.

FieldTypeDescription
list_idIntegerID of the list to send to.
senderStringYour approved Sender ID. Use GET /v1/senders to list your available senders.
messageStringMessage content. Supports {first_name}, {last_name}, {company}, {other}, and {optout}. Each contact's details are substituted individually.
enable_unicode (optional)BooleanWhen true, messages containing emojis or non-GSM characters are sent as UCS-2. Defaults to false (non-GSM characters are stripped).
max_parts (optional)IntegerMaximum SMS parts (credits) per message. Messages that exceed this limit are skipped and counted in total_skipped_too_long. Default 10, range 1–99.
custom_ref (optional)StringReference stored against every message in this send.
ignore_unsubscribes (optional)BooleanBypass unsubscribe filtering. Default false.
scheduled_for (optional)StringUTC datetime to send (ISO 8601). Must be at least 1 minute in the future. If omitted, sends immediately. A scheduled list send can be cancelled in bulk by passing the custom_ref to DELETE /v1/messages.
curl -u user123:mypassword -X POST https://api.mobilemessage.com.au/v1/list-send \
-H "Content-Type: application/json" \
-d '{
  "list_id": 5,
  "sender": "CompanyABC",
  "message": "Hi {first_name}, our sale starts today.{optout}",
  "custom_ref": "march-sale"
}'
{
  "status": "complete",
  "list_id": 5,
  "total_recipients": 150,
  "total_blocked_unsubscribed": 3,
  "total_skipped_too_long": 0,
  "total_cost": 150,
  "scheduled_for": null,
  "send_status": "queued"
}

Message History

GET /v1/messages

Retrieve sent message history. You can look up a specific message by ID or custom reference, or browse paginated history with optional filters.

Lookup by ID or reference

Parameter Type Description
message_id String The unique message ID (UUID) returned when the message was sent.
custom_ref String Your custom reference (exact match). Returns all messages with this reference.

Paginated history

When neither message_id nor custom_ref is provided, returns paginated outbound message history.

Parameter Type Description
status (optional) String Filter by status. One of: pending, scheduled, sent, delivered, failed, cancelled.
from (optional) String Filter messages sent on or after this date (YYYY-MM-DD, UTC).
to (optional) String Filter messages sent before this date (YYYY-MM-DD, UTC).
limit (optional) Integer Results per page. Default 50, max 200.
offset (optional) Integer Pagination offset. Default 0.

Code Examples

curl -u user123:mypassword -X GET "https://api.mobilemessage.com.au/v1/messages?message_id=abcd1234-efgh-5678-ijkl-9876543210mn"
import requests
from requests.auth import HTTPBasicAuth

url = "https://api.mobilemessage.com.au/v1/messages?message_id=abcd1234-efgh-5678-ijkl-9876543210mn"
response = requests.get(url, auth=HTTPBasicAuth('user123', 'mypassword'))
print(response.json())
const messageId = "abcd1234-efgh-5678-ijkl-9876543210mn";

fetch(`https://api.mobilemessage.com.au/v1/messages?message_id=${messageId}`, {
    headers: {
        'Authorization': 'Basic ' + btoa('user123:mypassword')
    }
})
.then(response => response.json())
.then(data => console.log(data));
<?php
$message_id = "abcd1234-efgh-5678-ijkl-9876543210mn";
$url = "https://api.mobilemessage.com.au/v1/messages?message_id=" . $message_id;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "user123:mypassword");
$response = curl_exec($ch);
curl_close($ch);
echo $response;
?>
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;

public class LookupMessage {
    public static void main(String[] args) throws Exception {
        String message_id = "abcd1234-efgh-5678-ijkl-9876543210mn";
        URL url = new URL("https://api.mobilemessage.com.au/v1/messages?message_id=" + message_id);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        String credentials = Base64.getEncoder().encodeToString("user123:mypassword".getBytes());
        connection.setRequestProperty("Authorization", "Basic " + credentials);
        connection.setRequestMethod("GET");
        // Process the response...
    }
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

class Program {
    static async Task Main() {
        string message_id = "abcd1234-efgh-5678-ijkl-9876543210mn";
        string url = $"https://api.mobilemessage.com.au/v1/messages?message_id={message_id}";
        var client = new HttpClient();
        var byteArray = System.Text.Encoding.ASCII.GetBytes("user123:mypassword");
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
        var response = await client.GetAsync(url);
        Console.WriteLine(await response.Content.ReadAsStringAsync());
    }
}

Response — lookup by ID or reference

{
    "status": "complete",
    "results": [
        {
            "message_id": "abcd1234-efgh-5678-ijkl-9876543210mn",
            "recipient_number": "61412345678",
            "sender_id": "CompanyABC",
            "message_content": "Hello, this is message 1",
            "status": "delivered",
            "cost": 1,
            "cust_ref": "tracking001",
            "requested_at": "2026-01-15 09:35:00",
            "scheduled_for": null
        }
    ]
}

Response — paginated history

curl -u user123:mypassword "https://api.mobilemessage.com.au/v1/messages?status=delivered&from=2026-01-01&limit=5"
{
    "status": "complete",
    "total": 120,
    "limit": 5,
    "offset": 0,
    "results": [
        {
            "message_id": "abcd1234-efgh-5678-ijkl-9876543210mn",
            "recipient_number": "61412345678",
            "sender_id": "CompanyABC",
            "message_content": "Hello!",
            "status": "delivered",
            "cost": 1,
            "cust_ref": "tracking001",
            "requested_at": "2026-01-15 09:35:00",
            "scheduled_for": null
        }
    ]
}

Cancel Scheduled Message

DELETE /v1/messages

Cancel one or more scheduled messages and receive a full credit refund. Only messages with status=scheduled can be cancelled. Provide either message_id or custom_ref.

Request body

FieldTypeDescription
message_idStringThe UUID of a single scheduled message to cancel.
custom_refStringCancel all scheduled messages with this custom reference (useful for cancelling a batch).

Cancel by message_id

curl -u user123:mypassword -X DELETE https://api.mobilemessage.com.au/v1/messages \
-H "Content-Type: application/json" \
-d '{"message_id":"abcd1234-efgh-5678-ijkl-9876543210mn"}'
{ "status": "complete", "message_id": "abcd1234-efgh-5678-ijkl-9876543210mn", "cancelled": true, "credits_refunded": 1 }

Cancel by custom_ref

curl -u user123:mypassword -X DELETE https://api.mobilemessage.com.au/v1/messages \
-H "Content-Type: application/json" \
-d '{"custom_ref":"march-campaign"}'
{ "status": "complete", "custom_ref": "march-campaign", "cancelled_count": 3, "credits_refunded": 3 }

Returns HTTP 404 if no matching scheduled message is found. Returns HTTP 409 if the message exists but is not in a scheduled state.

Contacts

Manage your contact list. Contacts can be added to lists and used as personalisation sources when sending SMS.

GET /v1/contacts

List contacts with optional filters. Multiple filters are combined with AND. Text fields use partial matching.

ParameterTypeDescription
number (optional)StringExact match by phone number (Australian local or international format).
first_name (optional)StringPartial match on first name.
last_name (optional)StringPartial match on last name.
company (optional)StringPartial match on company.
other (optional)StringPartial match on the other/custom field.
limit (optional)IntegerResults per page. Default 50, max 200.
offset (optional)IntegerPagination offset. Default 0.
curl -u user123:mypassword "https://api.mobilemessage.com.au/v1/contacts?limit=10"
{
  "status": "complete",
  "total": 120,
  "limit": 10,
  "offset": 0,
  "results": [
    { "contact_id": 42, "number": "61412345678", "first_name": "Jane", "last_name": "Smith", "company": "Acme", "other": "" }
  ]
}

POST /v1/contacts

Add a new contact. If duplicate contacts are disabled on your account, adding a number that already exists returns HTTP 409.

FieldTypeDescription
numberStringPhone number (required).
first_name (optional)StringFirst name — used in {first_name} variable substitution.
last_name (optional)StringLast name — used in {last_name} substitution.
company (optional)StringCompany — used in {company} substitution.
other (optional)StringCustom field — used in {other} substitution.
curl -u user123:mypassword -X POST https://api.mobilemessage.com.au/v1/contacts \
-H "Content-Type: application/json" \
-d '{"number":"0412345678","first_name":"Jane","last_name":"Smith","company":"Acme"}'
{ "status": "complete", "contact_id": 42, "number": "61412345678" }

PATCH /v1/contacts

Update one or more fields on an existing contact. Only the fields you provide will be changed.

FieldTypeDescription
contact_idIntegerID of the contact to update (required).
number (optional)StringNew phone number.
first_name (optional)StringFirst name.
last_name (optional)StringLast name.
company (optional)StringCompany.
other (optional)StringCustom field.
curl -u user123:mypassword -X PATCH https://api.mobilemessage.com.au/v1/contacts \
-H "Content-Type: application/json" \
-d '{"contact_id":42,"first_name":"Jane","company":"Acme Corp"}'
{ "status": "complete", "contact_id": 42 }

DELETE /v1/contacts

Remove a contact. The contact is also removed from all lists.

curl -u user123:mypassword -X DELETE https://api.mobilemessage.com.au/v1/contacts \
-H "Content-Type: application/json" \
-d '{"contact_id":42}'
{ "status": "complete", "contact_id": 42, "removed": true }

Contact Lists

Organise contacts into named lists for use with Send to List.

GET /v1/lists

List all contact lists including their contact count.

curl -u user123:mypassword https://api.mobilemessage.com.au/v1/lists
{
  "status": "complete",
  "results": [
    { "list_id": 5, "name": "VIP Customers", "created_at": "2026-01-15 09:00:00", "contact_count": 150 }
  ]
}

POST /v1/lists

Create a new contact list.

curl -u user123:mypassword -X POST https://api.mobilemessage.com.au/v1/lists \
-H "Content-Type: application/json" \
-d '{"name":"VIP Customers"}'
{ "status": "complete", "list_id": 5, "name": "VIP Customers" }

PATCH /v1/lists

Rename a list.

curl -u user123:mypassword -X PATCH https://api.mobilemessage.com.au/v1/lists \
-H "Content-Type: application/json" \
-d '{"list_id":5,"name":"VIP Customers 2026"}'
{ "status": "complete", "list_id": 5, "name": "VIP Customers 2026" }

DELETE /v1/lists

Delete a list. By default only the list and its membership records are removed — contact records are kept. Set delete_contacts to true to also permanently delete all contact records that were members of the list.

# Delete list only (keep contacts)
curl -u user123:mypassword -X DELETE https://api.mobilemessage.com.au/v1/lists \
-H "Content-Type: application/json" \
-d '{"list_id":5}'

# Delete list and all its contacts
curl -u user123:mypassword -X DELETE https://api.mobilemessage.com.au/v1/lists \
-H "Content-Type: application/json" \
-d '{"list_id":5,"delete_contacts":true}'
{ "status": "complete", "list_id": 5, "removed": true }

List Members

Add, remove, and view contacts within a specific list.

GET /v1/list-contacts

ParameterTypeDescription
list_idIntegerID of the list to query (required).
limit (optional)IntegerDefault 50, max 200.
offset (optional)IntegerPagination offset.
curl -u user123:mypassword "https://api.mobilemessage.com.au/v1/list-contacts?list_id=5"
{
  "status": "complete",
  "total": 1,
  "limit": 50,
  "offset": 0,
  "results": [
    { "contact_id": 42, "number": "61412345678", "first_name": "Jane", "last_name": "Smith", "company": "Acme", "added": "2026-01-20 10:00:00" }
  ]
}

POST /v1/list-contacts

Add a contact to a list. Has no effect if the contact is already a member.

curl -u user123:mypassword -X POST https://api.mobilemessage.com.au/v1/list-contacts \
-H "Content-Type: application/json" \
-d '{"list_id":5,"contact_id":42}'
{ "status": "complete", "list_id": 5, "contact_id": 42, "added": true }

DELETE /v1/list-contacts

Remove a contact from a list (the contact itself is not deleted).

curl -u user123:mypassword -X DELETE https://api.mobilemessage.com.au/v1/list-contacts \
-H "Content-Type: application/json" \
-d '{"list_id":5,"contact_id":42}'
{ "status": "complete", "list_id": 5, "contact_id": 42, "removed": true }

Unsubscribes

Manage your opt-out list. Adding a number blocks it from receiving future messages, cancels any scheduled messages to that number, and removes the contact from all lists.

GET /v1/unsubscribes

ParameterTypeDescription
number (optional)StringFilter by phone number.
limit (optional)IntegerResults per page. Default 50, max 200.
offset (optional)IntegerPagination offset. Default 0.
curl -u user123:mypassword "https://api.mobilemessage.com.au/v1/unsubscribes?limit=100&offset=0"
{
  "status": "complete",
  "total": 1250,
  "limit": 100,
  "offset": 0,
  "results": [
    { "number": "61412345678", "updated_at": "2026-01-15 09:00:00" }
  ]
}

POST /v1/unsubscribes

Add a number to your unsubscribe list.

curl -u user123:mypassword -X POST https://api.mobilemessage.com.au/v1/unsubscribes \
-H "Content-Type: application/json" \
-d '{"number":"0412345678"}'
{ "status": "complete", "number": "61412345678", "added": true }

DELETE /v1/unsubscribes

Remove a number from your unsubscribe list.

curl -u user123:mypassword -X DELETE https://api.mobilemessage.com.au/v1/unsubscribes \
-H "Content-Type: application/json" \
-d '{"number":"0412345678"}'
{ "status": "complete", "number": "61412345678", "removed": true }

Account Credit Balance

GET /v1/account

Retrieve your current SMS credit balance using your authenticated credentials. No extra parameters are required.

Code Examples

# Execute the GET request and view the response
curl -u user123:mypassword -X GET https://api.mobilemessage.com.au/v1/account

# Example response output:
# {"status": "complete", "credit_balance": 1000}
import requests
from requests.auth import HTTPBasicAuth

url = "https://api.mobilemessage.com.au/v1/account"
response = requests.get(url, auth=HTTPBasicAuth('user123', 'mypassword'))

# Parse the JSON response
data = response.json()
credit_balance = data.get('credit_balance', 'N/A')

print(f"Credit Balance: {credit_balance}")
# Output might be: Credit Balance: 1000
// Using Fetch API to get and process account balance
fetch('https://api.mobilemessage.com.au/v1/account', {
    method: 'GET',
    headers: {
        'Authorization': 'Basic ' + btoa('user123:mypassword'),
        'Content-Type': 'application/json'
    }
})
.then(response => response.json())
.then(data => {
    const creditBalance = data.credit_balance || 'N/A';
    console.log("Credit Balance:", creditBalance);
})
.catch(error => console.error(error));
<?php
$url = "https://api.mobilemessage.com.au/v1/account";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_USERPWD, "user123:mypassword");
$response = curl_exec($ch);
curl_close($ch);

$data = json_decode($response, true);
$creditBalance = isset($data['credit_balance']) ? $data['credit_balance'] : 'N/A';
echo "Credit Balance: " . $creditBalance;
// Output might be: Credit Balance: 1000
?>
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Base64;
import org.json.JSONObject;  // Requires org.json library

public class GetBalance {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://api.mobilemessage.com.au/v1/account");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        String credentials = Base64.getEncoder().encodeToString("user123:mypassword".getBytes());
        connection.setRequestProperty("Authorization", "Basic " + credentials);
        connection.setRequestMethod("GET");

        BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String inputLine;
        StringBuilder responseStr = new StringBuilder();
        while ((inputLine = in.readLine()) != null) {
            responseStr.append(inputLine);
        }
        in.close();

        JSONObject json = new JSONObject(responseStr.toString());
        int creditBalance = json.getInt("credit_balance");
        System.out.println("Credit Balance: " + creditBalance);
    }
}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;  // Requires Newtonsoft.Json package

class Program {
    static async Task Main() {
        var client = new HttpClient();
        var byteArray = Encoding.ASCII.GetBytes("user123:mypassword");
        client.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

        var response = await client.GetAsync("https://api.mobilemessage.com.au/v1/account");
        var responseString = await response.Content.ReadAsStringAsync();
        var json = JObject.Parse(responseString);
        var creditBalance = json["credit_balance"];
        Console.WriteLine("Credit Balance: " + creditBalance);
    }
}
Example Successful Response (200)
{
    "status": "complete",
    "credit_balance": 1000
}

Example Error Responses

Account Not Found (404)
{
    "error": "Account not found or no credit balance available."
}
Invalid Request Method (405)
{
    "error": "Invalid request method. Only GET is allowed."
}

Sender IDs

List your active Sender IDs or register your own mobile number as a sender via a two-step verification flow.

GET /v1/senders

List all active Sender IDs on your account.

curl -u user123:mypassword https://api.mobilemessage.com.au/v1/senders
{
  "status": "complete",
  "results": [
    { "sender": "CompanyABC", "type": "alpha", "label": "My Brand", "is_default": true },
    { "sender": "61412345678", "type": "own", "label": "My mobile", "is_default": false }
  ]
}

POST /v1/senders

Register your own mobile number as a sender. An SMS containing a confirmation link is sent to the number at no charge. The owner must click the link and confirm before the number is activated as a sender on your account.

FieldTypeDescription
numberStringThe mobile number to register.
label (optional)StringA label to identify this sender in your account.
curl -u user123:mypassword -X POST https://api.mobilemessage.com.au/v1/senders \
-H "Content-Type: application/json" \
-d '{"number":"0412345678","label":"My mobile"}'
{ "status": "verification_sent", "message": "A verification link has been sent to the number." }

Returns HTTP 409 if the number is already an active sender on your account. Returns HTTP 429 if you have too many pending verifications or a verification was sent to that number in the last 5 minutes.

Inbound SMS

GET /v1/inbound

Retrieve paginated inbound SMS messages and opt-out replies received on your dedicated numbers. For real-time notification of inbound messages, configure a webhook.

ParameterTypeDescription
from (optional)StringFilter messages received on or after this date (YYYY-MM-DD, UTC).
to (optional)StringFilter messages received before this date (YYYY-MM-DD, UTC).
limit (optional)IntegerResults per page. Default 50, max 200.
offset (optional)IntegerPagination offset. Default 0.
curl -u user123:mypassword "https://api.mobilemessage.com.au/v1/inbound?from=2026-01-01&limit=10"
{
  "status": "complete",
  "total": 5,
  "limit": 10,
  "offset": 0,
  "results": [
    {
      "message_id": "abc123def-456g-7890-hijk-lmnopqrstuvw",
      "from": "61412345678",
      "to": "61400000000",
      "message": "Yes, I'd like more info",
      "type": "inbound",
      "received_at": "2026-01-15 09:35:00"
    }
  ]
}

Delivery Receipts & Inbound Messages (Webhooks)

Configure webhooks to receive real-time notifications for inbound messages and delivery receipts.

Managing webhook URLs via API

You can get and update your webhook URLs programmatically using the /v1/webhooks endpoint.

GET /v1/webhooks
curl -u user123:mypassword https://api.mobilemessage.com.au/v1/webhooks
{ "status": "complete", "webhooks": { "inbound": "https://yourapp.com/inbound", "status": null } }
POST /v1/webhooks — set a webhook URL
curl -u user123:mypassword -X POST https://api.mobilemessage.com.au/v1/webhooks \
-H "Content-Type: application/json" \
-d '{"type":"inbound","url":"https://yourapp.com/sms-inbound"}'
{ "status": "complete", "type": "inbound", "url": "https://yourapp.com/sms-inbound" }
DELETE /v1/webhooks — remove a webhook URL
curl -u user123:mypassword -X DELETE https://api.mobilemessage.com.au/v1/webhooks \
-H "Content-Type: application/json" \
-d '{"type":"inbound"}'
{ "status": "complete", "type": "inbound", "url": null }

Webhook URL Setup

Set your Inbound and/or Status URL in your account settings (or via the API above). These URLs will receive POST requests with a JSON payload when an event occurs.

Webhook Payload Structure

Field Type Description
to String Recipient's phone number.
message String Content of the SMS.
sender String The sender's ID or phone number.
received_at String UTC timestamp when the event was received.
type (inbound only) String Either "inbound" or "unsubscribe".
original_message_id (inbound only) String The UUID of the original outbound message.
original_custom_ref (inbound only) String Your custom reference for the original message.
status (status webhooks only) String Either "delivered" or "failed".
message_id (status webhooks only) String The unique message ID.
custom_ref (status webhooks only) String Your custom reference (if provided) for the outbound message.
part_number (status webhooks only) Number The part number for this delivery receipt.
For non-concatenated messages this will be 1.
total_parts (status webhooks only) Number Total number of parts for the outbound message.
For non-concatenated messages this will be 1.

Example Inbound Webhook Payload

{
  "to": "61412345678",
  "message": "Hello, this is message 1",
  "sender": "61412345699",
  "received_at": "2024-09-30 14:35:00",
  "type": "inbound",
  "original_message_id": "db6190e1-1ce8-4cdd-b871-244257d57abc",
  "original_custom_ref": "tracking001"
}

Example Status Webhook Payload

{
  "to": "61412345678",
  "message": "Hello, this is message 1",
  "sender": "Mobile MSG",
  "custom_ref": "tracking001",
  "status": "delivered",
  "message_id": "044b035f-0396-4a47-8428-12d5273ab04a",
  "received_at": "2024-09-30 14:35:00",
  "part_number": 1,
  "total_parts": 1
}

Example Status Webhook Payload (Concatenated Message)

{
  "to": "61412345678",
  "message": "Hello, this is a longer message that was split into multiple parts",
  "sender": "Mobile MSG",
  "custom_ref": "tracking001",
  "status": "delivered",
  "message_id": "044b035f-0396-4a47-8428-12d5273ab04a",
  "received_at": "2024-09-30 14:35:00",
  "part_number": 2,
  "total_parts": 3
}

Inbound Webhook Examples

Below are sample implementations for receiving inbound SMS messages.

from flask import Flask, request

app = Flask(__name__)

@app.route('/webhook-inbound', methods=['POST'])
def inbound_webhook():
    data = request.get_json(force=True)
    
    # Extract inbound fields
    to = data.get('to', '')
    message = data.get('message', '')
    sender = data.get('sender', '')
    received_at = data.get('received_at', '')
    inbound_type = data.get('type', '')
    original_message_id = data.get('original_message_id', '')
    original_custom_ref = data.get('original_custom_ref', '')

    print("Inbound Webhook Received:")
    print(f"  To: {to}")
    print(f"  From: {sender}")
    print(f"  Received At: {received_at}")
    print(f"  Message: {message}")
    print(f"  Type: {inbound_type}")
    print(f"  Original Message ID: {original_message_id}")
    print(f"  Original Custom Ref: {original_custom_ref}")

    # Respond with simple 'OK'
    return "OK", 200

if __name__ == '__main__':
    app.run(port=5000)
const express = require('express');
const app = express();
app.use(express.json());

app.post('/webhook-inbound', (req, res) => {
  const {
    to,
    message,
    sender,
    received_at,
    type,
    original_message_id,
    original_custom_ref
  } = req.body;

  console.log("Inbound Webhook Received:");
  console.log("  To:", to);
  console.log("  From:", sender);
  console.log("  Received At:", received_at);
  console.log("  Message:", message);
  console.log("  Type:", type);
  console.log("  Original Message ID:", original_message_id);
  console.log("  Original Custom Ref:", original_custom_ref);

  res.status(200).send("OK");
});

app.listen(3000, () => {
  console.log('Inbound webhook server listening on port 3000');
});
<?php
// Simple inbound webhook example in PHP
$rawData = file_get_contents('php://input');
$data = json_decode($rawData, true);

$to = $data['to'] ?? '';
$message = $data['message'] ?? '';
$sender = $data['sender'] ?? '';
$receivedAt = $data['received_at'] ?? '';
$type = $data['type'] ?? '';
$originalMessageId = $data['original_message_id'] ?? '';
$originalCustomRef = $data['original_custom_ref'] ?? '';

error_log("Inbound Webhook Received:");
error_log("  To: $to");
error_log("  From: $sender");
error_log("  Received At: $receivedAt");
error_log("  Message: $message");
error_log("  Type: $type");
error_log("  Original Message ID: $originalMessageId");
error_log("  Original Custom Ref: $originalCustomRef");

// Send a simple OK response
http_response_code(200);
echo "OK";
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;

@RestController
public class InboundWebhookController {

    @PostMapping("/webhook-inbound")
    public ResponseEntity<String> handleInbound(@RequestBody InboundPayload payload) {
        System.out.println("Inbound Webhook Received:");
        System.out.println("  To: " + payload.getTo());
        System.out.println("  From: " + payload.getSender());
        System.out.println("  Received At: " + payload.getReceivedAt());
        System.out.println("  Message: " + payload.getMessage());
        System.out.println("  Type: " + payload.getType());
        System.out.println("  Original Message ID: " + payload.getOriginalMessageId());
        System.out.println("  Original Custom Ref: " + payload.getOriginalCustomRef());

        return ResponseEntity.ok("OK");
    }
}

// Example inbound payload model
class InboundPayload {
    private String to;
    private String message;
    private String sender;
    private String receivedAt;
    private String type;
    private String originalMessageId;
    private String originalCustomRef;

    // Getters and setters...
}
using Microsoft.AspNetCore.Mvc;
using System;

[ApiController]
[Route("webhook-inbound")]
public class InboundWebhookController : ControllerBase {
    [HttpPost]
    public IActionResult HandleInbound([FromBody] InboundPayload payload) {
        Console.WriteLine("Inbound Webhook Received:");
        Console.WriteLine($"  To: {payload.To}");
        Console.WriteLine($"  From: {payload.Sender}");
        Console.WriteLine($"  Received At: {payload.ReceivedAt}");
        Console.WriteLine($"  Message: {payload.Message}");
        Console.WriteLine($"  Type: {payload.Type}");
        Console.WriteLine($"  Original Message ID: {payload.OriginalMessageId}");
        Console.WriteLine($"  Original Custom Ref: {payload.OriginalCustomRef}");

        return Ok("OK");
    }
}

public class InboundPayload {
    public string To { get; set; }
    public string Message { get; set; }
    public string Sender { get; set; }
    public string ReceivedAt { get; set; }
    public string Type { get; set; }
    public string OriginalMessageId { get; set; }
    public string OriginalCustomRef { get; set; }
}

Status Webhook Examples

Below are sample implementations for receiving message delivery status updates. These use fields status and message_id, plus any custom reference used when sending the message. Each status webhook also includes part_number and total_parts so you can track delivery for concatenated messages.

from flask import Flask, request

app = Flask(__name__)

@app.route('/webhook-status', methods=['POST'])
def status_webhook():
    data = request.get_json(force=True)

    # Extract status-related fields
    to = data.get('to', '')
    message = data.get('message', '')
    sender = data.get('sender', '')
    custom_ref = data.get('custom_ref', '')
    status = data.get('status', '')
    message_id = data.get('message_id', '')
    received_at = data.get('received_at', '')
    part_number = data.get('part_number', 1)
    total_parts = data.get('total_parts', 1)

    print("Status Webhook Received:")
    print(f"  To: {to}")
    print(f"  From: {sender}")
    print(f"  Received At: {received_at}")
    print(f"  Message: {message}")
    print(f"  Custom Ref: {custom_ref}")
    print(f"  Status: {status}")
    print(f"  Message ID: {message_id}")
    print(f"  Part: {part_number}/{total_parts}")

    return "OK", 200

if __name__ == '__main__':
    app.run(port=5000)
const express = require('express');
const app = express();
app.use(express.json());

app.post('/webhook-status', (req, res) => {
  const {
    to,
    message,
    sender,
    custom_ref,
    status,
    message_id,
    received_at,
    part_number,
    total_parts
  } = req.body;

  console.log("Status Webhook Received:");
  console.log("  To:", to);
  console.log("  From:", sender);
  console.log("  Received At:", received_at);
  console.log("  Message:", message);
  console.log("  Custom Ref:", custom_ref);
  console.log("  Status:", status);
  console.log("  Message ID:", message_id);
  console.log("  Part:", `${part_number}/${total_parts}`);

  res.status(200).send("OK");
});

app.listen(3000, () => {
  console.log('Status webhook server listening on port 3000');
});
<?php
$rawData = file_get_contents('php://input');
$data = json_decode($rawData, true);

$to = $data['to'] ?? '';
$message = $data['message'] ?? '';
$sender = $data['sender'] ?? '';
$customRef = $data['custom_ref'] ?? '';
$status = $data['status'] ?? '';
$messageId = $data['message_id'] ?? '';
$receivedAt = $data['received_at'] ?? '';
$partNumber = $data['part_number'] ?? 1;
$totalParts = $data['total_parts'] ?? 1;

error_log("Status Webhook Received:");
error_log("  To: $to");
error_log("  From: $sender");
error_log("  Received At: $receivedAt");
error_log("  Message: $message");
error_log("  Custom Ref: $customRef");
error_log("  Status: $status");
error_log("  Message ID: $messageId");
error_log("  Part: {$partNumber}/{$totalParts}");

http_response_code(200);
echo "OK";
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;

@RestController
public class StatusWebhookController {

    @PostMapping("/webhook-status")
    public ResponseEntity<String> handleStatus(@RequestBody StatusPayload payload) {
        System.out.println("Status Webhook Received:");
        System.out.println("  To: " + payload.getTo());
        System.out.println("  From: " + payload.getSender());
        System.out.println("  Received At: " + payload.getReceivedAt());
        System.out.println("  Message: " + payload.getMessage());
        System.out.println("  Custom Ref: " + payload.getCustomRef());
        System.out.println("  Status: " + payload.getStatus());
        System.out.println("  Message ID: " + payload.getMessageId());
        System.out.println("  Part: " + payload.getPartNumber() + "/" + payload.getTotalParts());

        return ResponseEntity.ok("OK");
    }
}

// Example status payload model
class StatusPayload {
    private String to;
    private String message;
    private String sender;
    private String customRef;
    private String status;
    private String messageId;
    private String receivedAt;
    private Integer partNumber;
    private Integer totalParts;

    // Getters and setters...
}
using Microsoft.AspNetCore.Mvc;
using System;

[ApiController]
[Route("webhook-status")]
public class StatusWebhookController : ControllerBase {
    [HttpPost]
    public IActionResult HandleStatus([FromBody] StatusPayload payload) {
        Console.WriteLine("Status Webhook Received:");
        Console.WriteLine($"  To: {payload.To}");
        Console.WriteLine($"  From: {payload.Sender}");
        Console.WriteLine($"  Received At: {payload.ReceivedAt}");
        Console.WriteLine($"  Message: {payload.Message}");
        Console.WriteLine($"  Custom Ref: {payload.CustomRef}");
        Console.WriteLine($"  Status: {payload.Status}");
        Console.WriteLine($"  Message ID: {payload.MessageId}");
        Console.WriteLine($"  Part: {payload.PartNumber}/{payload.TotalParts}");

        return Ok("OK");
    }
}

public class StatusPayload {
    public string To { get; set; }
    public string Message { get; set; }
    public string Sender { get; set; }
    public string CustomRef { get; set; }
    public string Status { get; set; }
    public string MessageId { get; set; }
    public string ReceivedAt { get; set; }
    public int PartNumber { get; set; }
    public int TotalParts { get; set; }
}

Common API Errors and Solutions

Error Message HTTP/Message Code Description and Solution
Unauthorized 401 Invalid API username or password. Check your credentials and ensure they are encoded correctly in your request.
Missing or invalid "messages" parameter. 400 The request body must contain a valid "messages" array. Ensure the JSON structure is correct and the "messages" array is present.
Invalid phone number format error The phone number provided is incorrectly formatted. Ensure numbers are in either Australian local or international format.
Message content cannot be empty error Your message content is empty.
Invalid sender. You do not have permission to use this sender. error You have attempted to use a sender ID not registered in your account. Register the sender ID first or select an authorised sender. To view your sender IDs, login to your account and click Settings > Sender IDs.
The recipient has unsubscribed and cannot receive messages. blocked The recipient has unsubscribed from your messages. Remove this number from your recipient list or contact the recipient directly.
Message contains non-GSM characters error Your message contains unsupported characters (e.g., emojis). Use standard GSM characters only.
Message exceeds the maximum allowed length. error Reduce your message length. Limits are:
• GSM-7: 1530 characters (10 parts)
• UCS-2: 670 characters (10 parts)
Insufficient credits to send the batch of messages. 403 You do not have enough SMS credits for the request. Please add more credits to your account.
Too many concurrent requests. Please wait. 429 Your account has reached the maximum number of simultaneous requests (5). Wait briefly before trying again.
Invalid request method. 405 The HTTP method used is not supported by this endpoint. Check the documentation for the correct method (GET, POST, or DELETE).
Message not found or is not in a scheduled state. 404 / 409 Returned when attempting to cancel a message that does not exist (404) or is not currently scheduled (409).
This phone number already exists in your contacts. 409 Duplicate contact blocked. Your account has duplicate contacts disabled. Use a different number or enable duplicates in your account settings.
You have too many pending verifications. 429 You have reached the limit of 3 pending sender verifications. Wait for existing ones to complete or expire before adding another.

Simple API

GET /simple/send-sms.php

When you can’t send a JSON body, use our Simple API endpoint. All parameters go in the query string.

Example request URLs

GSM-7 (default, non-GSM characters are stripped):

https://api.mobilemessage.com.au/simple/send-sms.php?api_username=YOUR_USERNAME&api_password=YOUR_PASSWORD&sender=61412345678&to=61498765432&message=Hello+there&custom_ref=OptionalRef123

Allow Unicode when required (uses UCS-2 and 70/67 per-part limits):

https://api.mobilemessage.com.au/simple/send-sms.php?api_username=YOUR_USERNAME&api_password=YOUR_PASSWORD&sender=61412345678&to=61498765432&message=Hello+🌏&unicode=true

Query parameters

Parameter Required? Description
api_username Yes Your API username.
api_password Yes Your API password.
sender Yes Your approved sender ID or phone number (for example 61412345678). Use GET /v1/senders to list your available senders.
to Yes Recipient’s phone number in international format (for example 61498765432).
message Yes URL-encoded SMS text (spaces as +, special characters percent-encoded).
custom_ref No Your own tracking reference.
unicode No Set to true to allow UCS-2 when needed. If not set, non-GSM characters are stripped and GSM-7 limits apply.
max_parts No Maximum SMS parts (credits). Returns 400 if the message exceeds this limit. Default 10, range 1–99.
ignore_unsubscribes No Set to true to bypass unsubscribe blocking for this send. If omitted or set to false, normal unsubscribe blocking applies. Use with caution, as bypassing your unsubscribe list could result in spam complaints.

Length limits

By default up to 10 parts per message (GSM-7: 1530 septets; UCS-2: 670 characters). Use max_parts to lower or raise this limit (1–99).

Response

On success, the Simple API returns a single response object.

{
  "status": "success",
  "message_id": "5f8b1c22-3f7a-4b5e-9a08-2e62d4f7c9b1",
  "custom_ref": "dev-test-1708869123",
  "to": "61412345678",
  "sender": "61400000000",
  "message": "API dev test message 2026-02-25 17:10:00",
  "cost": 1,
  "ignore_unsubscribes": true
}