• 228 destinations
  • No KYC, ever
  • Bitcoin, Monero, USDT and 4 more

Transactional traffic

OTP codes by SMS,
delivered while the user is still looking.

One POST per code, flagged transactional so it leaves at any hour, with a validity equal to the life of the code and an idempotency key so a retry never sends two.

01In short

To send OTP codes with SMSMeteor, call POST /v1/messages with the number in E.164, a text that starts with your brand and contains the code, validity set to the lifetime of the code, and window.quiet_hours set to bypass. The response carries the price, and a message.delivered webhook confirms arrival, usually within seconds.

No identity verification is needed to open the account, and the same per-destination rate applies from the first code to the millionth.

Recommended settings

Traffic type
Transactional, exempt from quiet hours
API call
POST /v1/messages, one per code
Validity
5 to 10 minutes (default is 48 hours)
Length
One GSM-7 segment, no link
Retries
Same Idempotency-Key, never a second code
Confirmation
message.delivered webhook or status poll

02How it works here

From nothing to delivered, in 4 moves.

  1. 01Create a key

    A send-scoped key for the service that issues codes, with an IP allowlist if it runs on fixed servers. The test key lets you build the flow without funds.

  2. 02Send the code

    Brand first, code second, expiry third. One segment. Set validity to the code lifetime and flag the message transactional.

  3. 03Listen for the result

    A delivered event closes the loop; a failed event with an unknown-number reason tells your UI to ask for another number instead of offering a resend.

  4. 04Protect the endpoint

    Limit requests per number, per IP and per account, and require a challenge after the second request. A flood to valid numbers is billed.

03What matters

What makes a code arrive

Three things decide whether a user sees the code in time: the route, the format and the hour. The route is ours to get right: one measured route per destination, with transactional traffic never queued behind a campaign. The format is yours: a short GSM-7 text with the brand in the first words, because in the Americas and wherever senders must be registered the recipient will see a number rather than your name. The hour is handled by the transactional flag, which lets the message leave outside the local marketing window.

Avoid links in code messages. Operators filter codes with links more than any other pattern, and a filtered code looks to your user exactly like a broken product.

04In practice

Resend logic that does not burn the balance

Let the user ask again after 30 seconds, then 60, then 120. Invalidate the previous code when a new one is issued. Build the idempotency key from the user and the attempt number so that a timeout on your side can be retried safely. When the webhook reports a failure for an unknown number, stop offering resends: the number is wrong, not the network.

Measure conversion from code sent to code entered, per destination. It is a better delivery metric than any receipt, because it includes the handset, the notification and the person.

05What it costs

10,000 messages, priced per destination.

One segment each at today's published rates. The same unit price applies to one message or a million; there is no plan, no setup fee and no monthly fee.

Rate card last updated 22 September 2026

DestinationRate per SMS10,000 messages
United States$0.0084$84.00
United Kingdom$0.0130$130.00
India$0.0256$256.00
Brazil$0.0042$42.00
Nigeria$0.0326$326.00
Germany$0.0238$238.00

Other destinations: cost calculator

06A message that works

What it looks like on the phone, and in the request.

Brand first, code early, no link, one segment.

METEORTransactional message
ACME: your code is 493 201. It expires in 10 minutes. We will never ask you for it.
83 characters1 segment, GSM-7
cURLPOST /v1/messages
curl https://api.smsmeteor.com/v1/messages \
  -H "Authorization: Bearer $SMSMETEOR_KEY" \
  -H "Idempotency-Key: otp-user-8841-attempt-1" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+14155550142",
    "from": "ACME",
    "text": "ACME: your code is 493 201. It expires in 10 minutes.",
    "validity": 10,
    "window": { "quiet_hours": "bypass" },
    "campaign": "otp-login"
  }'

07Pitfalls

Three mistakes we see, and how to avoid them.

  • Links in code messages

    The most filtered pattern in SMS. Put the code in the text and nothing to tap.

  • Default validity on a 10-minute code

    A code delivered after it expired is a support ticket. Set validity to the code lifetime.

  • A new idempotency key on each retry

    That sends two codes. Reuse the key of the attempt; change it only when the user asks for a new code.

09Questions, answered

OTP and verification codes by SMS: questions, answered.

How fast are OTP messages delivered?

On a healthy route a code reaches the handset within a few seconds of the API call. Transactional messages are not queued behind campaigns, and the status page publishes delivery latency so you can check the current figures.

Can OTP codes be sent at night?

Yes. Set window.quiet_hours to bypass and the message is treated as transactional: it leaves immediately in every destination. Quiet hours only hold marketing traffic.

Will the code show my brand as the sender?

Where the destination delivers alphanumeric senders as typed, yes. In the Americas, China and countries that require registration, recipients see a number, which is why the brand belongs in the first words of the text. Each country page states the rule.

What does an OTP message cost?

The destination's published rate for one segment, for example $0.0084 to the United States or $0.0256 to India. There is no per-verification fee and no monthly fee.

Do I need to verify my company to send codes?

No. An email address opens the account. What is checked is the content: codes are fine, impersonating a bank or a public service is not.

How do I stop bots from draining my balance through the code endpoint?

Rate-limit per number, per IP and per account on your side, add a challenge after the second request, and refuse destinations you do not serve. Unsupported prefixes are rejected for free, but messages to valid numbers are billed.