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:
- Combine your
username:password. - Encode the resulting string in Base64.
- Add this string to the
Authorizationheader 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. |
{first_name}, {last_name}, {company}, and {other} will be replaced with the values from that contact record. If no matching contact is found, placeholders are replaced with an empty string.
{optout} token: Include {optout} anywhere in your message body and it will automatically be replaced with an opt-out instruction before sending. The replacement is always exactly 20 characters:
- Dedicated or shared number senders →
Opt out: Reply Stop - Alphanumeric or own-number senders →
OptOut mb.st/XXXXXX(whereXXXXXXis your account's unique 6-character opt-out code)
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.
| Field | Type | Description |
|---|---|---|
list_id | Integer | ID of the list to send to. |
sender | String | Your approved Sender ID. Use GET /v1/senders to list your available senders. |
message | String | Message content. Supports {first_name}, {last_name}, {company}, {other}, and {optout}. Each contact's details are substituted individually. |
enable_unicode (optional) | Boolean | When true, messages containing emojis or non-GSM characters are sent as UCS-2. Defaults to false (non-GSM characters are stripped). |
max_parts (optional) | Integer | Maximum 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) | String | Reference stored against every message in this send. |
ignore_unsubscribes (optional) | Boolean | Bypass unsubscribe filtering. Default false. |
scheduled_for (optional) | String | UTC 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
| Field | Type | Description |
|---|---|---|
message_id | String | The UUID of a single scheduled message to cancel. |
custom_ref | String | Cancel 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.
| Parameter | Type | Description |
|---|---|---|
number (optional) | String | Exact match by phone number (Australian local or international format). |
first_name (optional) | String | Partial match on first name. |
last_name (optional) | String | Partial match on last name. |
company (optional) | String | Partial match on company. |
other (optional) | String | Partial match on the other/custom field. |
limit (optional) | Integer | Results per page. Default 50, max 200. |
offset (optional) | Integer | Pagination 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.
| Field | Type | Description |
|---|---|---|
number | String | Phone number (required). |
first_name (optional) | String | First name — used in {first_name} variable substitution. |
last_name (optional) | String | Last name — used in {last_name} substitution. |
company (optional) | String | Company — used in {company} substitution. |
other (optional) | String | Custom 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.
| Field | Type | Description |
|---|---|---|
contact_id | Integer | ID of the contact to update (required). |
number (optional) | String | New phone number. |
first_name (optional) | String | First name. |
last_name (optional) | String | Last name. |
company (optional) | String | Company. |
other (optional) | String | Custom 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
| Parameter | Type | Description |
|---|---|---|
list_id | Integer | ID of the list to query (required). |
limit (optional) | Integer | Default 50, max 200. |
offset (optional) | Integer | Pagination 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
| Parameter | Type | Description |
|---|---|---|
number (optional) | String | Filter by phone number. |
limit (optional) | Integer | Results per page. Default 50, max 200. |
offset (optional) | Integer | Pagination 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.
| Field | Type | Description |
|---|---|---|
number | String | The mobile number to register. |
label (optional) | String | A 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.
| Parameter | Type | Description |
|---|---|---|
from (optional) | String | Filter messages received on or after this date (YYYY-MM-DD, UTC). |
to (optional) | String | Filter messages received before this date (YYYY-MM-DD, UTC). |
limit (optional) | Integer | Results per page. Default 50, max 200. |
offset (optional) | Integer | Pagination 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
}