Get a key
SMS API

Receive SMS in your own software

Your MirageTEL numbers receive texts — sign-in codes, booking alerts, replies from customers. Read them with one API call, or have each one pushed to your server, signed, the moment it lands.

1

Ask

GET /messages?after=… with a key. Texts come oldest first; keep nextAfter and you read every text exactly once.

2

Be told

Add a webhook: each text is POSTed to your https address the moment it arrives, signed with HMAC-SHA256, retried for 24 hours.

3

Only what it needs

A key reads, nothing else. Narrow it to some numbers and some senders — the right shape for sign-in codes. Revoke in one click.

One call

curl -H "X-Api-Key: $MIRAGETEL_SMS_KEY" \
  "https://miragetel.com/api/v1/sms/messages?after=<the last id you have>"
{
  "data": [
    {
      "id": "0b6f1c2e-5a8d-4c1e-9f3a-2d7b8e6a1c40",
      "number": "+13075550100",
      "from": "22000",
      "body": "123456 is your verification code",
      "bodyRetained": true,
      "receivedAt": "2026-10-02T12:41:51.009Z"
    }
  ],
  "hasMore": false,
  "nextAfter": "0b6f1c2e-5a8d-4c1e-9f3a-2d7b8e6a1c40"
}

body is null with bodyRetained: false once the words have been removed — never an empty string that looks like an empty text.

Reference

Base URL https://miragetel.com/api/v1/sms · header X-Api-Key: mts_…

EndpointAnswers
GET /messagesTexts received, oldest first: {data, hasMore, nextAfter}
GET /messages/{id}One text: {data}
GET /numbersThe numbers this key reads
ParameterMeaning
afterA message id (preferred) or an ISO 8601 time. Texts strictly after it, oldest first. Without it: the last 24 hours.
numberOne of your numbers, E.164 — %2B13075550100.
fromOne sender. Spaces, dots, dashes, + and capitals do not matter.
limit1–200, default 50.
HTTPError
400INVALID_AFTER · INVALID_NUMBER · INVALID_SENDER
401API_KEY_REQUIRED · API_KEY_INVALID — the same answer for a revoked key and one that never existed
404CURSOR_NOT_FOUND · MESSAGE_NOT_FOUND — another account answers the same
429RATE_LIMITED — more than 120 requests in a minute on one key

Waiting for a sign-in code? Note the time before you ask for the code, then ask every 3–5 seconds with after=<that time> and from=<the sender>, and stop after about two minutes.

Webhooks

POST /your/endpoint
Content-Type: application/json
X-MirageTel-Event: sms.received
X-MirageTel-Delivery: 7c1d9e…
X-MirageTel-Timestamp: 1790955722
X-MirageTel-Signature: 3f9a…

{"event":"sms.received","deliveryId":"7c1d9e…",
 "data":{ …the same text as GET /messages… },
 "sentAt":"2026-10-02T12:41:51.402Z"}

Verify every push before you trust it — HMAC-SHA256 of "<timestamp>.<raw body>" with your secret, and refuse a timestamp older than five minutes. deliveryId stays the same on every retry, so a duplicate is easy to ignore.

const crypto = require('crypto');
const ts = req.get('X-MirageTel-Timestamp');
const expected = crypto.createHmac('sha256', SECRET)
  .update(ts + '.' + rawBody).digest('hex');
const ok = expected === req.get('X-MirageTel-Signature')
  && Math.abs(Date.now() / 1000 - ts) < 300;
import hmac, hashlib, time
ts = request.headers["X-MirageTel-Timestamp"]
expected = hmac.new(SECRET.encode(), f"{ts}.".encode() + raw_body,
                    hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, request.headers["X-MirageTel-Signature"]) \
     and abs(time.time() - int(ts)) < 300

Addresses inside private networks are refused, before every delivery, and redirects are not followed. Send test in your account posts one signed sms.test event.

Limits

Requests120 a minute per key — enough to ask every half second
KeysUp to 10 per account, each narrowable to some numbers and some senders
WebhooksUp to 5 per account, https only, public addresses only
Retries30 s → 6 h, for 24 hours; answer any 2xx within 8 s
A dead endpointSwitched off after 50 failures in a row with nothing delivered for a day — you are told, texts stay readable
Text contentRemoved after 90 days; the record stays

Numbers that receive texts

Numbers in 4 of the 93 countries we sell receive texts; the others take calls only. A received text costs 1¢ from your wallet, or one text from a calling pack. The API itself is free.

Questions

Does the SMS API cost anything?

No. The API, the keys and the webhooks are free. A text your number receives costs what it always costs: 1¢ from your wallet, or one text from a calling pack of that country.

Which numbers can receive texts?

Numbers in 4 of the 93 countries we sell receive texts; the others take calls only. Each country page says which.

Will a particular service be able to text my number?

That depends on the service and on the destination network, not on us — some services send only to mobile numbers of certain countries. Send yourself a test before you depend on it.

Can the API send texts?

Not yet. Version 1 reads the texts your numbers receive. Sending stays in your account and the app.

What can somebody do with a leaked key?

Read the texts the key may read — and nothing else. A key cannot send, buy, move money or see another account. Narrow it to the numbers and senders it needs, and revoke it in one click.

What if my server is down?

We retry after 30 s, 2 min, 10 min, 30 min, 1 h, 3 h and 6 h, for 24 hours. The texts stay readable with a key all the while.

How long are texts kept?

The words of a text are removed after 90 days; the record that it arrived stays, with bodyRetained set to false.