REST API

    Australian SMS API for Developers, SaaS Businesses and Agencies

    Send SMS messages programmatically for just 3¢ each. Simple REST API, no SDK required. Get started in minutes.

    The Texto SMS API is a REST API for sending SMS to Australian and New Zealand numbers. Authenticate with a bearer API key and POST to /send. HMAC-SHA256 signed webhooks are available for delivery receipts and inbound messages, with account management endpoints for SaaS platforms, agencies and multi-account hierarchies.

    Send SMS via API in 3 Simple Steps

    No SDK to install — most customers are integrating and sending within 5 minutes.

    1

    Create an account

    Sign up free and get 5 SMS credits to test with.

    2

    Generate an API key

    Go to the Developer page in-app and create a key.

    3

    Send your first SMS

    Make a POST request to /send with your key.

    curl -X POST https://api.texto.com.au/send \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "to": "+61412345678",
        "message": "Hello from Texto!",
        "sender": "MyBrand"
      }'

    Why Choose Texto's SMS API

    Built for Australian businesses and developers who need reliable, affordable SMS delivery.

    Flat 3¢ Per SMS

    No monthly fees, no setup charges, no minimum spend. Pay only for the messages you send — every SMS costs exactly 3 cents.

    Sub-Second Delivery

    Messages are routed through direct Australian carrier connections for the fastest possible delivery. Most SMS arrive within one second.

    Australian Routes

    All traffic stays on Australian carrier networks. No grey routes, no international re-routing — just reliable local delivery to every Australian mobile.

    No SDK Required

    Texto is a clean REST API. Any language that can make an HTTP request works — Python, JavaScript, PHP, Go, cURL, even VBA in Excel macros.

    SMS API Reference & Endpoints

    Base URL: https://api.texto.com.au

    Authentication

    All requests require an Authorization: Bearer txt_... header with your API key.

    Credit Calculation

    1 credit = 1 message part. Messages ≤160 characters = 1 part. Longer messages split into 154-character parts.

    Request Parameters

    ParameterRequiredDescription
    toYesRecipient Australian mobile number (e.g. +61412345678)
    messageYesSMS body text
    senderNoSpecify a registered Sender ID (e.g. "MyBrand") or dedicated number (e.g. "+61400000000") to send from. If omitted, your account's default sending number will be used.
    campaignNoOptional campaign name (max 200 chars) that groups sends under a named campaign for reporting. Reuse the same name to roll up stats (recipient count + credits) across many API calls. Useful when sending on behalf of different clients, departments, or workflows.

    Sending

    Tracking & Reports

    Account Management

    A multi-account SMS API built for SaaS platforms, agencies and resellers.

    If you sell software or services to other businesses, SMS shouldn't mean onboarding forms, shared logins and manual top-ups. The Texto account management endpoints let you create a sub-account for every customer, issue them their own API key, fund them with credits, assign a dedicated Australian number, invite their users and pull usage reporting, all via the API. See account hierarchy for account structure details and see our pricing for volume rates as you scale.

    Account hierarchy needs to be switched on for your parent account before these endpoints return data. and we'll enable it.

    Accounts

    Sharing your Sender IDs and dedicated numbers. Set inherit_parent_senders to true on a sub-account and it can send using your registered Sender IDs and dedicated numbers in the from field, on top of anything it holds itself. It is off by default, only the parent account can change it, and a sub-account can't switch it on for itself. An ACMA-registered Sender ID may only be used by the business (ABN) it was registered to — sharing it across locations, brands or departments of that same business is fine, but a sub-account that is a separate legal entity with its own ABN must register its own Sender ID.

    Credits

    API keys

    Users & access

    Numbers

    Webhook configuration

    Reporting

    Error Codes

    StatusMeaning
    400Bad request — invalid parameters or phone number
    401Unauthorized — invalid or revoked API key
    402Payment required — insufficient credits
    404Not found — resource doesn't exist
    500Internal server error

    Rate Limits & Best Practices

    Rate limitMax 50 requests/second across all endpoints per API key.
    ConcurrencyMax 25 concurrent requests per API key.
    Batch sizeMax 1,000 recipients per /send-batch call.
    Large sendsFor more than 1,000 recipients, split into multiple calls with a 1–2 second delay between each.
    Higher limitsNeed more throughput? and we can raise your limits.
    Service statusLive status of the API, web app and message delivery is published at status.texto.com.au.

    Delivery Receipt Webhooks

    Configure an endpoint URL in your Texto dashboard and we'll POST a JSON event every time a delivery receipt is recorded for one of your messages. Signed with HMAC-SHA256, retried on failure, and idempotent by design.

    Trigger

    Fired once per delivery receipt for any message on your account, including team-member sends.

    Request

    POST
    <your endpoint URL>

    Headers

    HeaderValueDescription
    Content-Typeapplication/jsonBody is always UTF-8 JSON.
    X-Texto-Eventmessage.dlrEvent type. Currently always message.dlr.
    X-Texto-DeliveryUUIDUnique per delivery. Same UUID is sent on retries — dedupe on this.
    X-Texto-Signaturesha256=<hex>HMAC-SHA256 of the raw body using your signing secret. Only sent when signing is enabled.

    Body

    Byte-identical to GET /message/:id on the REST API — same fields, same names, same types.

    {
      "message": {
        "id": "8c1f9b2e-1a4c-4f87-9bd2-2d2f6f6f6f6f",
        "recipient": "+61412345678",
        "body": "Hi Sam, your appointment is confirmed for Tue 9am.",
        "status": "delivered",
        "sent_at": "2026-05-06T03:14:22.000Z"
      },
      "delivery_receipt": {
        "status": "delivered",
        "received_at": "2026-05-06T03:14:25.421Z"
      }
    }

    Verifying the signature (Node.js)

    Always verify the signature before trusting the payload. Use the raw request bytes (not a re-serialised JSON string) and a constant-time comparison.

    import crypto from "node:crypto";
    
    app.post("/webhooks/texto", express.raw({ type: "application/json" }), (req, res) => {
      const signatureHeader = req.header("x-texto-signature") || "";
      const expected = crypto
        .createHmac("sha256", process.env.TEXTO_WEBHOOK_SECRET)
        .update(req.body) // raw bytes — not JSON.stringify(parsed)
        .digest("hex");
    
      const provided = signatureHeader.replace(/^sha256=/, "");
    
      const ok =
        provided.length === expected.length &&
        crypto.timingSafeEqual(Buffer.from(provided, "hex"), Buffer.from(expected, "hex"));
    
      if (!ok) return res.status(401).send("invalid signature");
    
      const event = JSON.parse(req.body.toString("utf8"));
      // event.message, event.delivery_receipt …
      res.sendStatus(200);
    });

    Retry schedule

    Up to 3 attempts in total. After the third failure the delivery is dropped and shown as failed in your "Recent deliveries" log. Reply with any 2xx within 15 seconds to acknowledge.

    AttemptWhen
    1Immediately when the delivery receipt is recorded
    2~1 minute after attempt 1 fails
    3~5 minutes after attempt 2 fails
    After a further ~30 minutes the delivery is given up on

    Inbound Message Webhooks

    Want every reply pushed to your server in real time? Configure an inbound webhook in your Texto dashboard and we'll POST a JSON event every time someone texts back to one of your numbers — an MO (Mobile Originated) message. STOP replies are included, with an is_optout flag so you can handle them separately. Signed with HMAC-SHA256, retried on failure, idempotent by message_id.

    Trigger

    Fired once for every inbound message received on any of your numbers, including replies to team-member sends. Opt-out replies (STOP, UNSUBSCRIBE, etc.) still fire the webhook — is_optout tells you which they were, and the opt-out has already been recorded on your account.

    Request

    POST
    <your endpoint URL>

    Headers

    HeaderValueDescription
    Content-Typeapplication/jsonBody is always UTF-8 JSON.
    X-Texto-Eventmessage.inboundEvent type. Currently always message.inbound.
    X-Texto-DeliveryUUIDUnique per delivery attempt. Same UUID on retries — dedupe on this or on message_id.
    X-Texto-Signaturesha256=<hex>HMAC-SHA256 of the raw body using your signing secret. Only sent when signing is enabled.

    Body

    message_id is the stable identifier for the inbound message — use it as your idempotency key so duplicate deliveries (network hiccups, retries) don't double-process.

    {
      "event": "message.inbound",
      "message_id": "8c1f9b2e-1a4c-4f87-9bd2-2d2f6f6f6f6f",
      "from": "+61412345678",
      "to": "+61480123456",
      "body": "STOP",
      "received_at": "2026-05-06T03:14:25.421Z",
      "in_reply_to": "1d4e9b2e-1a4c-4f87-9bd2-2d2f6f6f6f6f",
      "is_optout": true
    }
    FieldTypeDescription
    message_iduuidStable ID of the inbound message. Use as your idempotency key.
    fromstringThe customer's phone number in E.164 format.
    tostringThe Texto number that received the reply.
    bodystringThe message text as received.
    received_atISO 8601When we received the message.
    in_reply_touuid | nullIf this looks like a reply to an outbound message, the ID of that message.
    is_optoutbooleanTrue if we detected an opt-out keyword (STOP, UNSUBSCRIBE, etc.). We've already recorded the opt-out.

    Verifying the signature (Node.js)

    Always verify the signature before trusting the payload. Use the raw request bytes (not a re-serialised JSON string) and a constant-time comparison.

    import crypto from "node:crypto";
    
    app.post("/webhooks/texto-inbound", express.raw({ type: "application/json" }), (req, res) => {
      const signatureHeader = req.header("x-texto-signature") || "";
      const expected = crypto
        .createHmac("sha256", process.env.TEXTO_INBOUND_WEBHOOK_SECRET)
        .update(req.body) // raw bytes — not JSON.stringify(parsed)
        .digest("hex");
    
      const provided = signatureHeader.replace(/^sha256=/, "");
    
      const ok =
        provided.length === expected.length &&
        crypto.timingSafeEqual(Buffer.from(provided, "hex"), Buffer.from(expected, "hex"));
    
      if (!ok) return res.status(401).send("invalid signature");
    
      const event = JSON.parse(req.body.toString("utf8"));
      // Dedupe on event.message_id (stable across retries)
      res.sendStatus(200);
    });

    Retry schedule

    Up to 3 attempts in total — same schedule as delivery receipts. Reply with any 2xx within 15 seconds to acknowledge.

    AttemptWhen
    1Immediately when the message is received
    2~1 minute after attempt 1 fails
    3~5 minutes after attempt 2 fails
    After a further ~30 minutes the delivery is given up on

    SMS API Code Examples

    Send your first SMS in any language.

    curl -X POST https://api.texto.com.au/send \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "to": "+61412345678",
        "message": "Hello from Texto!"
      }'

    Why use an SMS API?

    SMS is still the highest-engagement channel businesses have. Open rates sit around 98% — usually within three minutes of delivery — compared with about 20% for email. If you actually need someone to see a message, SMS is hard to beat.

    An SMS API takes that channel and makes it programmable. Instead of logging into a dashboard, you fire a single HTTPS request from your app, CRM, automation tool, or AI agent, and the message goes out through a direct carrier route. The whole exchange usually completes in under a second.

    That unlocks the use cases below — anything where timing, reliability and "did they actually see it" matter more than fancy formatting. 2FA codes, payment receipts, appointment reminders, delivery updates, outage alerts, marketing broadcasts, AI-driven workflows.

    The job of a good SMS API is to get out of the way: plain REST, no SDK, predictable pricing, real delivery receipts, and opt-out handling that keeps you compliant without extra code. That's what Texto is built for — Australian carriers, Australian data, 3¢ a message, 24/7 chat if you ever need a human.

    2FA & OTP codes

    Deliver one-time passwords in under a second for sign-ins and verification.

    Transactional alerts

    Order confirmations, payment receipts, fraud alerts, status changes.

    Appointment reminders

    Cut no-shows in half — clinics, salons, trades, professional services.

    Delivery notifications

    Dispatch, on-the-way, and arrival pings with shortened tracking links.

    Marketing campaigns

    Personalised broadcasts with merge fields, opt-out handling baked in.

    AI-driven workflows

    Let AI agents send SMS via the API or our MCP server at mcp.texto.com.au.

    What the Texto SMS API can do

    A quick map of every capability and how to reach it. Everything is plain REST — no SDKs, no proprietary wire formats.

    CapabilityEndpoint / mechanismNotes
    Send single SMSPOST /sendOne-off transactional and conversational sends.
    Batch sendPOST /send-batchUp to 1,000 recipients per call, merge fields supported.
    Personalisation / merge fields{{merge}} placeholdersPer-recipient values in /send-batch.
    Delivery receipts (poll)GET /message/:idStatus + timestamp for any message.
    Delivery receipts (push)Webhook (HMAC-SHA256 signed)Real-time, retried, idempotent.
    Inbound messages (poll)GET /inboxTwo-way SMS with pagination and filters.
    Inbound replies (push)Webhook (HMAC-SHA256 signed)Real-time MOs including opt-outs, retried, idempotent.
    Opt-out managementGET /optoutsAuto STOP handling, queryable list.
    One-tap opt-out link{{OptOutLink}} merge fieldShort texto.au link per recipient. Confirms opt-out on click. Ideal for Sender ID sends without inbound reply path.
    Campaign trackingGET /campaign/:idPer-campaign rollup and message detail.
    Balance checkGET /balanceProgrammatic credit monitoring.
    Sender ID / dedicated number"sender" parameterACMA-registered alpha sender or your AU number.
    Scheduled sendingIn-app schedulerSchedule from the dashboard or via the app.
    AI agent integrationMCP serverhttps://mcp.texto.com.au — Claude, OpenAI tools, etc.
    Language supportPlain RESTAny language with HTTP — no SDK required.
    Sub-account provisioningPOST /accountsCreate an account per customer, with its own balance, opt-out list and sender ID.
    Credit allocationPOST /account/:id/credits/allocateFund or recall customer credits from your parent balance.
    API key provisioningPOST /account/:id/keyIssue and revoke keys on behalf of your customers.
    Number assignmentPOST /account/:id/numbers/assignGive a customer a dedicated AU or NZ number, recall it later.
    Group reportingGET /report/groupUsage, credits and delivery rate for every account in one call.

    Reliability, Security & Data Handling

    The boring stuff that actually matters when you put a phone number in front of your customers.

    Data infrastructure hosted in Australia

    Your data stays onshore. No offshore failover, no surprise data transfers.

    Encrypted in transit and at rest

    TLS 1.2+ for every request; AES-256 for stored data.

    Ephemeral by design

    Message content is automatically deleted after 90 days. Spreadsheet uploads are discarded as soon as the campaign is queued.

    HMAC-SHA256 signed webhooks

    Every delivery receipt is signed with your secret, retried on failure, and idempotent by design.

    API key auth with rotation

    Bearer token auth. Rotate or revoke keys instantly from the Developer page — no downtime.

    TIO Member · ACMA-approved telco

    Telecommunications Industry Ombudsman member and ACMA-approved for SMS Sender ID registration.

    24/7 live chat support

    Real humans on chat around the clock. No tier-1 ticket queue, no overseas overnight handoff.

    Compliant SMS sending in Australia

    Sending commercial SMS in Australia is governed by the Spam Act 2003 and the ACMA. The rules boil down to three things: consent, identification, and unsubscribe.

    • Consent. You must have express or inferred consent from every recipient before you send a commercial message.
    • Identification. The sender must be clearly identifiable — use a registered Sender ID or a number tied to your business.
    • Unsubscribe. Every commercial message needs a free, functional opt-out path. The Australian standard is replying STOP.

    Texto handles the unsubscribe side automatically. STOP replies are processed in real time, the number is added to your account-wide opt-out list, and any future API send to that number is blocked before it hits the carrier — so you can't accidentally re-message someone who has opted out. You can query the full list at any time via GET /optouts.

    For branded alphanumeric senders (e.g. "MyBrand"), Australia requires registration with the ACMA SMS Sender ID Register. Texto handles that registration for you for free as part of the service.

    Developers trust Texto

    CapterraRated 5 stars on Capterra

    "Excellent product, highly recommend"

    Easy to use, intuitive product and great value. So good to see a new business getting it right. Product, performance and price.

    Switched from Sinch MessageMedia

    Mark O.

    Director NBS · Banking

    Verified Capterra Review

    "Love it so far"

    Simple and Responsive. Their pricing is competitive and a great alternative to other established options.

    Josh S.

    Principal Consultant · Management Consulting

    Verified Capterra Review

    SMS API — Frequently Asked Questions

    How long does it take to set up an SMS API?
    The Texto SMS REST API is so easy to use, customers are typically integrating and sending within 5 minutes. Sign up, generate an API key from the Developer page, and make your first POST /send request — no SDK, no SOAP, no sales call.
    How much does the Texto SMS API cost?
    Every SMS sent through the Texto API costs just 3¢ (AUD). There are no monthly fees, no setup charges, and no minimum spend. You only pay for what you send.
    Do I need to install an SDK?
    No. Texto is a simple REST API — any language that can make HTTP requests works out of the box. We provide code examples for cURL, Python, JavaScript, PHP, Go, and VBA.
    What are the API rate limits?
    You can make up to 50 requests per second and 25 concurrent requests per API key. For batch sending, each /send-batch call supports up to 1,000 recipients. If you need higher limits, chat with us and we can raise them.
    Can I send bulk SMS campaigns via the API?
    Yes. Use the /send-batch endpoint to send to up to 1,000 recipients per call with personalised merge fields. For larger campaigns, split into multiple calls with a short delay.
    Is the Texto SMS API secure?
    Yes. All requests use TLS 1.2+ in transit, data is encrypted at rest with AES-256, API keys use bearer authentication and can be rotated or revoked instantly, and delivery webhooks are signed with HMAC-SHA256.
    How long do you keep my message data?
    Message content is automatically deleted after 90 days. Spreadsheet uploads used for batch sends are discarded as soon as the campaign is queued. The only thing kept permanently is the list of numbers that have opted out, so you don't accidentally re-message them.
    Do you support 2FA and OTP delivery?
    Yes. The /send endpoint is well suited to one-time passcodes — sub-second delivery via direct Australian carrier routes, signed webhooks for real-time delivery receipts, and no SDK to get in the way.
    What's your uptime?
    We don't offer a contractual uptime SLA, but the Texto API is built on redundant Australian cloud infrastructure with multi-AZ failover, direct carrier routes, and continuous health monitoring. In practice the platform runs at near-perfect availability, and our 24/7 chat team is on standby if anything ever looks off.
    Can I send international SMS?
    Texto is primarily AU-focused, but we can enable message delivery and provide numbers / shortcodes for New Zealand, the UK, USA and Canada at very competitive rates. Get in touch via chat and we'll set you up.
    How do I handle STOP and opt-outs?
    Texto handles STOP replies automatically — once a recipient opts out, they're added to your account-wide opt-out list and future sends to that number are blocked. Query the list any time via GET /optouts. You stay compliant with the Spam Act 2003 without writing any extra logic. You can also include a {{OptOutLink}} merge field in any API send — each recipient gets a unique short texto.au link that unsubscribes them in one tap. Perfect for Sender ID campaigns where recipients can't reply STOP.
    Do I need a registered Sender ID?
    Not to start. You can send straight from your account's default number. To send under a branded alphanumeric sender (e.g. "MyBrand") you'll need to register it with ACMA — Texto handles the registration for you for free as part of the service.
    Does Texto support webhooks?
    Yes — two of them. Delivery receipts are POSTed to your endpoint in real time as messages are delivered, and inbound replies (MOs) are POSTed every time someone texts back to one of your numbers (STOP replies included, with an is_optout flag). Both are HMAC-SHA256 signed, include a stable UUID for idempotency, and are automatically retried on failure. See https://texto.com.au/webhooks for delivery receipts and https://texto.com.au/inbound-webhooks for inbound messages.
    Can I create and manage accounts for my customers via the API?
    Yes. The account management endpoints let you create a sub-account per customer with POST /accounts, issue them their own API key, allocate or recall credits, assign a dedicated Australian number, invite their users and update their daily send limits — all programmatically. Each customer gets their own balance, opt-out list, sender ID and message history while you keep a parent-level view. Account hierarchy needs to be enabled on your parent account first — just ask us on chat.
    Can I white-label or resell Texto SMS through my own platform?
    Yes. SaaS platforms, agencies and resellers embed Texto by provisioning a Texto sub-account behind each of their own customers, funding it with credits from the parent balance, and sending on that customer's behalf via the API. Your customers never need to touch Texto directly. Pricing starts at a flat 3¢ per SMS to Australian numbers with volume rates as you scale, so the margin is yours.
    How do I report on SMS usage across all of my customer accounts?
    Call GET /report/group for a single response containing per-account message totals, parts, delivered and failed counts, credits consumed, inbound messages, opt-outs and delivery rate, plus a grand total across the hierarchy. For one customer, use GET /account/:id/report with from and to dates, and optional filters for direction, status, country, campaign, keyword or number.
    How do I get started?
    Sign up for a free Texto account to receive 5 free SMS credits. Then generate an API key from the Developer page and make your first POST request to /send.

    Start Sending SMS via API Today

    Sign up free, get 5 credits, and send your first message in under a minute.

    Get Your Free API Key

    Have questions? .