For developers

An API that reads like the docs.

One authenticated endpoint, scoped keys you set the permissions on, and events that come to you so nothing has to poll.

Send in three lines

Bearer-auth an API key, POST a number and a body. Add an Idempotency-Key header and a retry after a timeout can never double-send.

Get an API key API reference
curl -X POST https://app.sms365.com.au/v1/messages \
  -H "Authorization: Bearer sk_live_…" \
  -H "Content-Type: application/json" \
  -d '{"to":"0412345678","body":"Your order is on its way."}'
await fetch("https://app.sms365.com.au/v1/messages", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SMS365_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": order.id,
  },
  body: JSON.stringify({ to: "0412345678", body: "Your order is on its way." }),
});
import requests

requests.post(
  "https://app.sms365.com.au/v1/messages",
  headers={"Authorization": f"Bearer {KEY}", "Idempotency-Key": order_id},
  json={"to": "0412345678", "body": "Your order is on its way."},
)
$ch = curl_init("https://app.sms365.com.au/v1/messages");
curl_setopt_array($ch, [
  CURLOPT_POST => true,
  CURLOPT_HTTPHEADER => ["Authorization: Bearer $key", "Content-Type: application/json"],
  CURLOPT_POSTFIELDS => json_encode(["to" => "0412345678", "body" => "…"]),
]);
curl_exec($ch);
Built for integration

Everything you'd expect, and the parts you'd forget.

Scoped API keys

Give each key exactly the permissions it needs — 25 scopes across seven groups. Secrets are stored only as a hash.

Delivery events

SMS365 pushes message.sent, link.clicked and more to your endpoint, HMAC-signed and retried — so nothing polls.

Idempotency

Send a key with a request and a retry returns the first result — a double-charge is impossible by design.

OpenAPI 3.1

A spec you can read or generate a client from, and an in-app reference that never drifts from the code.

SSRF-safe webhooks

Outbound events resolve a host, refuse private and link-local addresses, and connect to the address they checked. No redirects.

Scheduling

A sendAt on any send, charged when scheduled and refunded on cancel — the same engine behind appointment reminders.

Events

Told what happened, as it happens

Subscribe an endpoint and SMS365 posts a signed event for each change — delivery, failure, cancellation, and link clicks — so your systems stay in step without polling /v1/messages.

See all event types
{
  "type": "message.sent",
  "data": { "message": {
    "id": "…",
    "to": "+61412345678",
    "status": "sent",
    "segments": 1
  } }
}
{
  "type": "link.clicked",
  "data": { "link": {
    "code": "a1B2c3D4",
    "url": "https://acme.example/offer",
    "messageId": "…"
  } }
}

Build it this afternoon.

Grab a scoped key, read the reference, and send your first message.

Get an API key →