1 Выберите платформу 1 304 сервисов отвечает

Укажите сервис

2 Выберите страну 145 стран

Укажите страну

3 Оператор и тариф

Назовите платформу и страну в любом порядке. Оператор и тариф появятся здесь.

Разработчикам

Справочник API

Читайте баланс и действующий тариф по любому сервису в любой стране прямо из своего кода. Один ключ в заголовке — и JSON в ответ.

Базовый адрес

https://smsactivate.io/api/v1
Выпустить ключ

Первый запрос #

Везде JSON поверх HTTPS, с авторизацией одним ключом, который вы выпускаете сами. Ничего не нужно устанавливать, ничего подписывать, песочницу выпрашивать не у кого — хватит ключа и curl.

  1. 1 Создать ключ Меню аккаунта, затем «Ключ API», затем создать. Он появляется один раз, и хранится только его отпечаток, поэтому посмотреть позже негде.
  2. 2 Передавайте его как bearer-токен Каждый вызов несёт заголовок Authorization. Второго входа нет: ни параметра в строке запроса, ни куки, ни сессии.
  3. 3 Прочитать ответ Каждый ответ — объект JSON с полем ok. Там, где ok равно false, поле error называет причину устойчивой строкой, предназначенной вашему коду.

Как предъявляется ключ #

Один ключ на аккаунт. Любой путь, кроме заголовка ниже, не поддерживается намеренно: ключ в строке запроса оседает в журналах доступа, в истории браузера и в заголовках referer, поэтому его отклоняют сразу, а не принимают, тихо утекая.

request
Authorization: Bearer sk_your_key_here

Этот ключ тратит деньги Сегодня он читает баланс; тот же ключ будет размещать заказы, когда появится оформление. Обращайтесь с ним как с паролем: не в системе контроля версий, не на скриншоте, заменять, а не передавать из рук в руки. Выпуск замены выводит прежний ключ из строя тут же.

Формы и соглашения #

Формы и соглашения
Базовый адрес https://smsactivate.io/api/v1
Транспорт Только HTTPS: на вызов по обычному HTTP приходит редирект, а редирект теряет ваш заголовок Authorization.
Формат JSON в обе стороны. В ответе всегда объект — голый массив корректным ответом не бывает.
Успех HTTP 200, и в "ok" стоит true.
Неудача Статус 4xx или 5xx, в "ok" стоит false, а в "error" — строка, написание которой никогда не меняется.
Деньги Суммы — числа в долларах США: не строки и не центы. 0.84 — это восемьдесят четыре цента.
Неизвестные поля Со временем в любом ответе могут появиться новые поля. Незнакомые пропускайте, а не считайте ошибкой.

Когда что-то не выходит #

Ветвитесь по строке ошибки и ни по чему другому. Предложение рядом с ней написано для вас, а не для вашего кода, и может быть переформулировано в любой момент; строка — нет.

Когда что-то не выходит
Статус ошиб. Причина
401 missing_key Заголовок Authorization не пришёл, либо пришло не bearer-токен.
401 bad_key Такой ключ нам неизвестен, либо он с тех пор выведен из строя или заменён.
400 unknown_service На этот код не отвечает ни один сервис. Коды берутся из каталога, а никогда не из имени, показанного на экране.
404 no_stock Для этой связки «сервис — страна» в данный момент ничего не простаивает.
404 unknown_country На этот код не отвечает ни одна страна для данного продукта. Каталоги покрывают разную территорию.
400 unknown_tech Это поколение сети в данной стране не предлагается. По городам продаются только США.
429 rate_limited Слишком много вызовов. Заголовок Retry-After называет ожидание в секундах.

Насколько сильно можно давить #

600 вызовов в минуту, засчитываемых на аккаунт, а не на адрес. Ключ рассчитан жить на одном сервере — на одном адресе, — поэтому счёт по адресам штрафовал бы обычную работу, оставляя украденному ключу свободу работать откуда угодно ещё. За потолком вы получаете 429 и Retry-After в секундах.

Маршруты #

Чтение аккаунта и каталога. Каждый маршрут называет каждый принимаемый параметр, каждое возвращаемое поле и каждый способ отказать.

Что лежит на аккаунте #

GET /api/v1/balance

Кредит на текущий момент и то, на сколько активаций его хватит по самому низкому тарифу, который сейчас есть в каталоге.

Что возвращается

Что лежит на аккаунте — Что возвращается
Ключ Вид Значение
ok boolean Присутствует и равно true всякий раз, когда статус 200.
balance number Доллары на балансе, с точностью до цента.
currency string Всегда "USD"; поле отдаётся, чтобы ничего не приходилось предполагать.
codes_at_cheapest integer Сколько кодов покроет баланс по самой низкой цене каталога. Оценка, чтобы понимать масштаб, а не котировка; null, если каталог пуст.
cheapest_code number Сама эта минимальная цена — на случай, если вы захотите пересчитать оценку от другой суммы.

Вызов

request
curl -s "https://smsactivate.io/api/v1/balance" \
  -H "Authorization: Bearer $SMSACTIVATE_KEY"

Ответ

200 OK
{
  "ok": true,
  "balance": 42.5,
  "currency": "USD",
  "codes_at_cheapest": 425,
  "cheapest_code": 0.1
}

Как отказывает missing_key bad_key rate_limited

Один сервис в одной стране #

GET /api/v1/pricing?service={service}&country={country}

Актуальный тариф и актуальное число свободных линий для одной связки. Дрейфует и то и другое: тариф идёт за самым дешёвым оператором, который держит там этот сервис, а счётчик — это то, что оператор сообщает в данное мгновение.

Что принимает

Один сервис в одной стране — Что принимает
Имя Значение
service нужен Код сервиса, например telegram — строчными буквами, как он записан в каталоге.
country можно опустить Код страны, например england. Уберите его — и одним вызовом вернутся все страны, см. ниже.

Что возвращается

Один сервис в одной стране — Что возвращается
Ключ Вид Значение
ok boolean Присутствует и равно true всякий раз, когда статус 200.
service string Код сервиса, возвращённый без изменений.
country string Код страны, возвращённый без изменений.
price number Цена одного кода в долларах у самого дешёвого оператора, где он есть.
stock integer Сколько номеров операторы сообщают свободными прямо сейчас — живое показание, меняется от минуты к минуте.

Вызов

request
curl -s "https://smsactivate.io/api/v1/pricing?service=telegram&country=england" \
  -H "Authorization: Bearer $SMSACTIVATE_KEY"

Ответ

200 OK
{
  "ok": true,
  "service": "telegram",
  "country": "england",
  "price": 0.84,
  "stock": 61213
}

Как отказывает missing_key bad_key unknown_service no_stock rate_limited

Один сервис по всем странам #

GET /api/v1/pricing?service={service}

Опустите страну — и вернутся все страны, несущие сервис. Порядок здесь собственный, сайтовый: сначала то, что реально доставляет, и уже внутри этого — самое дешёвое. Не голый тариф: он поднял бы наверх двухцентовую линию, на которую никто ничего никогда не получает.

Что принимает

Один сервис по всем странам — Что принимает
Имя Значение
service нужен Код сервиса, например telegram.

Что возвращается

Один сервис по всем странам — Что возвращается
Ключ Вид Значение
ok boolean Присутствует и равно true всякий раз, когда статус 200.
service string Код сервиса, который вы прислали.
name string Название, как оно показано на сайте, например «Telegram».
countries array По объекту на страну, в порядке, описанном выше.
countries[].country string Код страны, готовый для передачи в парный вызов.
countries[].name string Его английское название.
countries[].price number Цена одного кода в долларах.
countries[].stock integer Номеров свободно в эту минуту.

Вызов

request
curl -s "https://smsactivate.io/api/v1/pricing?service=telegram" \
  -H "Authorization: Bearer $SMSACTIVATE_KEY"

Ответ

200 OK
{
  "ok": true,
  "service": "telegram",
  "name": "Telegram",
  "countries": [
    { "country": "england", "name": "United Kingdom", "price": 0.84, "stock": 61213 },
    { "country": "poland",  "name": "Poland",         "price": 0.91, "stock": 22140 }
  ]
}

Как отказывает missing_key bad_key unknown_service rate_limited

Тарифы мобильных сессий #

GET /api/v1/proxy-pricing?country={country}&tech={tech}

Если страна не названа, вы получаете четыре, где у нас стоят модемы, — с числом операторов и начальным тарифом у каждой. Назовите страну — получите каждого оператора там и стоимость каждого отрезка. Отрезки указываются в днях: 1, 7, 30, 365.

Что принимает

Тарифы мобильных сессий — Что принимает
Имя Значение
country можно опустить Код страны, например us. Уберите его — и вместо этого вернётся список стран.
tech можно опустить Поколение сети, 4g или 5g. Оба продаются только в США; в остальных странах поле не учитывается и возвращается единственный доступный диапазон.

Что возвращается

Тарифы мобильных сессий — Что возвращается
Ключ Вид Значение
ok boolean Присутствует и равно true всякий раз, когда статус 200.
country string Код страны, который вы прислали.
tech string Поколение, к которому относится цена, уже после выбора значения по умолчанию.
techs array Каждое поколение, продающееся в этой стране.
terms array Сроки в продаже, в днях.
carriers array По объекту на оператора.
carriers[].carrier string Код оператора — передайте его при заказе.
carriers[].name string Название оператора для показа, например «T-Mobile».
carriers[].prices object Цена каждого срока в долларах, с ключом — длительностью в днях.

Вызов

request
curl -s "https://smsactivate.io/api/v1/proxy-pricing?country=us" \
  -H "Authorization: Bearer $SMSACTIVATE_KEY"

Ответ

200 OK
{
  "ok": true,
  "country": "us",
  "tech": "4g",
  "techs": ["4g", "5g"],
  "terms": [1, 7, 30, 365],
  "carriers": [
    { "carrier": "us-t-mobile", "name": "T-Mobile", "prices": { "1": 8.67, "7": 52, "30": 130, "365": 1300 } },
    { "carrier": "us-verizon",  "name": "Verizon",  "prices": { "1": 8.67, "7": 52, "30": 130, "365": 1300 } }
  ]
}

Как отказывает missing_key bad_key unknown_country unknown_tech rate_limited

Тарифы на срок #

GET /api/v1/rental-pricing?country={country}&days={days}

Если страна не названа, вы получаете каждую страну, где линию можно держать, с её начальным тарифом. Назовите страну — получите каждого оператора там и то, во что обходится у него запрошенный вами отрезок.

Что принимает

Тарифы на срок — Что принимает
Имя Значение
country можно опустить Код страны, например fr. Уберите его — и вместо этого вернётся список стран.
days можно опустить Срок в днях — 7, 14 или 30. Любое другое значение считается самым коротким сроком.

Что возвращается

Тарифы на срок — Что возвращается
Ключ Вид Значение
ok boolean Присутствует и равно true всякий раз, когда статус 200.
country string Код страны, который вы прислали.
days integer Срок, к которому относится цена.
terms array Каждый срок в продаже, в днях.
operators array По объекту на оператора, сначала самая низкая цена.
operators[].operator string Код оператора — передайте его при заказе.
operators[].name string Его название.
operators[].type string Одно из значений: physical, virtual или premium.
operators[].price number Цена всего срока в долларах.

Вызов

request
curl -s "https://smsactivate.io/api/v1/rental-pricing?country=fr&days=30" \
  -H "Authorization: Bearer $SMSACTIVATE_KEY"

Ответ

200 OK
{
  "ok": true,
  "country": "fr",
  "days": 30,
  "terms": [7, 14, 30],
  "operators": [
    { "operator": "fr-lycamobile", "name": "Lycamobile", "type": "virtual",  "price": 14.32 },
    { "operator": "fr-orange",     "name": "Orange",     "type": "physical", "price": 20.76 }
  ]
}

Как отказывает missing_key bad_key unknown_country rate_limited

Разобранные примеры #

Программы, которые работают как есть, а не однострочные обрывки, — включая те два места, на которых спотыкаются.

Shell #

Найти самую дешёвую страну для сервиса, затем убедиться, что баланса на неё хватает.

cheapest.sh
#!/usr/bin/env bash
set -euo pipefail
: "${SMSACTIVATE_KEY:?export your key first}"
API="https://smsactivate.io/api/v1"

auth=(-H "Authorization: Bearer $SMSACTIVATE_KEY")

# The catalogue is already ordered: the first country is the one to take.
best=$(curl -sf "${API}/pricing?service=telegram" "${auth[@]}" \
        | jq -r ".countries[0] | \"\(.country) \(.price)\"")
country=${best% *}
price=${best#* }

balance=$(curl -sf "${API}/balance" "${auth[@]}" | jq -r .balance)

# ⚠️ Compare as numbers, not as strings: "9.5" > "10" is true in a string sort.
if awk "BEGIN{exit !($balance >= $price)}"; then
  echo "ok: $country at \$$price, balance \$$balance"
else
  echo "top up first: need \$$price, have \$$balance" >&2
  exit 1
fi

JavaScript #

То же самое на Node, с корректной обработкой формы ошибки.

pricing.mjs
const API = "https://smsactivate.io/api/v1";
const key = process.env.SMSACTIVATE_KEY;

async function call(path) {
  const r = await fetch(API + path, {
    headers: { Authorization: `Bearer ${key}` },
  });
  const body = await r.json();
  // A non-2xx always carries { ok:false, error }. Branch on `error`, never on
  // the sentence — the string is stable, the wording is not.
  if (!r.ok || !body.ok) {
    if (body.error === "rate_limited") {
      const wait = Number(r.headers.get("Retry-After") || 60);
      await new Promise((s) => setTimeout(s, wait * 1000));
      return call(path);
    }
    throw new Error(body.error ?? `http_${r.status}`);
  }
  return body;
}

const { countries } = await call("/pricing?service=telegram");
const { balance }   = await call("/balance");

const best = countries[0];
console.log(`${best.name}: $${best.price} (${best.stock} in stock)`);
console.log(balance >= best.price ? "balance covers it" : "top up first");

Python #

И на Python, с такой же повторной попыткой по 429.

pricing.py
import os, time, requests

API = "https://smsactivate.io/api/v1"
S = requests.Session()
S.headers["Authorization"] = f"Bearer {os.environ['SMSACTIVATE_KEY']}"

def call(path):
    r = S.get(API + path, timeout=20)
    body = r.json()
    if not r.ok or not body.get("ok"):
        if body.get("error") == "rate_limited":
            time.sleep(int(r.headers.get("Retry-After", 60)))
            return call(path)
        raise RuntimeError(body.get("error", f"http_{r.status_code}"))
    return body

countries = call("/pricing?service=telegram")["countries"]
balance   = call("/balance")["balance"]

best = countries[0]
print(f"{best['name']}: ${best['price']} ({best['stock']} in stock)")
print("balance covers it" if balance >= best["price"] else "top up first")

Чего здесь пока нет #

Сегодня ключ читает аккаунт и каталог. Размещение заказов — следующее, и отвечать оно будет по тому же базовому адресу тому же ключу, поэтому ничто, написанное под эти маршруты, распускать не придётся.

Заказ номера Пока нет Пока нет. Сейчас заказ проходит через сайт.
Опрос кода Пока нет Планируется, вместе с заказом.
Возврат номера Пока нет Планируется, вместе с заказом.
Аренда через API Пока нет В планах.
Вебхуки Пока нет Пока нет — появится вместе с событиями заказа, когда будет что доставлять.

Страница растёт вместе с ними: то, что здесь есть, остаётся на месте, а новое появляется в разделе точек входа.

Что менялось #

  • Первый публичный выпуск: ключи API, GET /balance, GET /pricing.