SMSToGo

Developers

API reference

Order a one-time verification number, read the code that arrives, and pay for it from the same balance your dashboard spends. One key, six endpoints, no SDK required.

https://smstogo.net/api/v1

Your key lives in dashboard settings.

Overview

The API does what the dashboard does. You ask for a number for one service, we rent it, and you read the verification message it receives. Every request is JSON over HTTPS and every response is JSON.

Base URL
https://smstogo.net/api/v1

Numbers are available in the United States today. The catalog endpoint always tells you exactly what can be ordered right now, so read it rather than hard-coding a service list.

There is no published rate limit. A pending order is refreshed against our upstream provider at most once every 15 seconds, so polling faster than that returns the last state we know rather than a newer one.

Authentication

Every request carries your API key as a bearer token. Generate one under Settings in your dashboard. The key is shown once, at the moment it is created: we store only a hash of it, so nobody — including us — can read it back afterwards.

Authenticated request
curl https://smstogo.net/api/v1/account/balance \
  -H "Authorization: Bearer sk_9fA2kQzB…"

A key spends your balance, so treat it like a password: keep it server-side, out of version control, and out of anything that runs in a browser. Generating a new key retires the old one immediately — that is how you revoke one that leaked.

A missing, unknown, or retired key returns 401. Session cookies are not accepted here, and your key does not open the dashboard.

Balance and pricing

Orders are charged to the balance of the account the key belongs to — the same balance your dashboard shows, topped up the same way. There is no separate API billing.

All money is expressed in integer minor units of the currency: price_minor of 50 in USD is $0.50. Never parse a decimal; the integer is the source of truth.

You are charged when the order is created, before we ask the provider for a number. An order that never delivers a message — cancelled, expired, or never rented — is refunded in full, automatically. A delivered order is final.

GET/account/balance

The balance every order on this key is charged against.

Response
{
  "currency": "USD",
  "balance_minor": 2500
}

Catalog

What you can actually order, with the price you will be charged. This is narrower than the catalog on our marketing pages, and it is the list to order from.

GET/services

Every country and service pair open for ordering.

Response
[
  {
    "country_code": "us",
    "service_slug": "google",
    "service_name": "Google",
    "price_minor": 50,
    "currency": "USD"
  }
]

Orders

An order is one rented number for one service. Create it, poll it until a code arrives, and cancel it if you no longer need it.

POST/orders

Charge your balance and rent a number. Responds 201 with the order.

country_codestring
Country of the number, as given by the catalog — for example "us".
service_slugstring
Service the number is for, as given by the catalog — for example "google".
Response
{
  "id": "6f1b0c2a-8d54-4f0a-9a1e-2c0b7d3e51aa",
  "status": "waiting_sms",
  "country_code": "us",
  "service_slug": "google",
  "service_name": "Google",
  "phone_number": "15302286946",
  "carrier": "TMobile",
  "price_minor": 50,
  "currency": "USD",
  "failure_reason": null,
  "expires_at": "2026-09-11T18:22:04Z",
  "completed_at": null,
  "refunded_at": null,
  "created_at": "2026-09-11T18:07:04Z",
  "messages": []
}

GET/orders/{order_id}

Read one order and any message it has received. This is the endpoint to poll.

Response
{
  "id": "6f1b0c2a-8d54-4f0a-9a1e-2c0b7d3e51aa",
  "status": "completed",
  "phone_number": "15302286946",
  "completed_at": "2026-09-11T18:09:31Z",
  "messages": [
    {
      "id": "b83c1f77-1a4e-4c33-9f2d-77a0c5e9d410",
      "sender": "22000",
      "body": "G-804036 is your Google verification code.",
      "code": "G-804036",
      "received_at": "2026-09-11T18:09:28Z"
    }
  ]
}

The verification code is on each message as code, with the full text in body. A message is stored once, so the same code never appears twice.

GET/orders

Your 20 most recent orders, newest first.

POST/orders/{order_id}/cancel

Give a number back before its code arrives and refund the charge in full.

Cancelling an order that already received a message is refused with 409: it delivered what you paid for.

Order status

status is how far along the order is. The first three can still change on their own; the last four are final.

reservingpending
Charged and recorded. The provider has not answered yet.
awaiting_numberpending
The request is accepted but no number has been assigned.
waiting_smspending
A number is reserved and phone_number is set. Poll from here.
completedfinal
A message arrived and is in messages. The order stays charged.
cancelledfinal · refunded
You gave the number back before a message arrived.
expiredfinal · refunded
The rental window closed without a message.
failedfinal · refunded
No number was ever rented. failure_reason says what happened.

Errors

Anything other than a 2xx carries a JSON body with a detail string written for a person to read. Branch on the status code, not on the wording.

Error body
{
  "detail": "Your balance is too low for this number. Top up and try again."
}
401Unauthorized
The key is missing, unknown, retired, or its account is closed.
402Payment required
Your balance is below the price of this number. Nothing was charged.
404Not found
No such order on this account, or no such country and service pair.
409Conflict
The pair exists but cannot be ordered, no numbers are free for it, or the order is already finished.
422Unprocessable content
The request body is missing a field or malformed.
502 · 503Upstream unavailable
We could not reach the number provider. Nothing was charged; retry shortly.