RelySMS
API · протокол handler_api.php

Номера для приёма SMS — из вашего софта

Если ваш софт уже работает с сервисом активаций через handler_api.php, он заработает с RelySMS: поменяйте адрес сервера и ключ. Те же действия, те же ответы, наши цены и возвраты.

https://relysms.pro/stubs/handler_api.php

Быстрый старт

  1. Войдите в кабинет и откройте «Баланс» → «API» → «Создать ключ». Ключ показывается один раз — сохраните его.
  2. Пополните баланс до $20 или больше: покупки через API проходят только при таком балансе. Держать ключ можно и с нулевым балансом.
  3. Укажите в софте адрес сервера https://relysms.pro/stubs/handler_api.php и ваш ключ вместо ключа прежнего сервиса.
  4. Купите номер (getNumber), опрашивайте статус раз в 5–10 секунд (getStatus), пока не придёт STATUS_OK с кодом.
  5. Завершите заказ (setStatus=6). Если код не пришёл — отмените через 2 минуты (setStatus=8) или просто дождитесь конца окна: деньги вернутся сами.

Правила и лимиты

  • Покупки через API — только при балансе от $20. Ниже порога getNumber отвечает NO_BALANCE; остальные методы работают.
  • Номер ваш 20 минут. Код не пришёл — заказ закрывается сам, деньги возвращаются на баланс.
  • Отменить заказ можно через 2 минуты после покупки, если код ещё не пришёл. Деньги возвращаются сразу.
  • После первого кода заказ оплачен и не возвращается. Пока окно открыто, на номер могут прийти и следующие коды.
  • До 20 запросов в секунду и до 5 покупок в секунду на ключ; до 50 открытых заказов одновременно.
  • Цена фиксируется в момент покупки. maxPrice защищает от покупки дороже вашего лимита.
  • Правила использования те же, что в условиях сервиса: спам, мошенничество и массовые регистрации с этой целью запрещены.

Методы

Все запросы — GET или POST на один адрес, параметры в строке запроса или в теле формы. Ключ передаётся в параметре api_key, действие — в action.

getBalance

Баланс аккаунта в долларах.

Только api_key и action.

GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getBalance

Ответ

ACCESS_BALANCE:25.00

getNumber

Купить номер для сервиса в стране. Деньги списываются сразу; если код не придёт — вернутся. Ответ: ACCESS_NUMBER:номер_заказа:телефон.

ПараметрОбязательныйОписание
serviceдаКод сервиса (getServicesList), например tg.
countryдаКод страны (getCountries).
maxPriceнетМаксимальная цена в долларах. Дороже — WRONG_MAX_PRICE с текущей ценой, ничего не списано.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getNumber&service=tg&country=187&maxPrice=0.80

Ответ

ACCESS_NUMBER:1042:15550001111

Возможные ошибки: BAD_SERVICE, BAD_COUNTRY, NO_NUMBERS, NO_BALANCE, WRONG_MAX_PRICE:0.59, LIMIT_ACTIVATIONS, RATE_LIMIT, BANNED

getNumberV2

То же, что getNumber, но ответ в JSON с ценой и временем окна.

ПараметрОбязательныйОписание
serviceдаКод сервиса.
countryдаКод страны.
maxPriceнетМаксимальная цена в долларах.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getNumberV2&service=tg&country=187&maxPrice=0.80

Ответ

{
  "activationId": 1042,
  "phoneNumber": "15550001111",
  "activationCost": 0.59,
  "countryCode": "187",
  "canGetAnotherSms": true,
  "activationTime": "2026-10-27T10:00:00.000Z",
  "activationEndTime": "2026-10-27T10:20:00.000Z"
}

Возможные ошибки: BAD_SERVICE, BAD_COUNTRY, NO_NUMBERS, NO_BALANCE, WRONG_MAX_PRICE:0.59, LIMIT_ACTIVATIONS, RATE_LIMIT

getStatus

Статус заказа: ждём код, код пришёл (с кодом) или отменён.

ПараметрОбязательныйОписание
idдаНомер заказа из getNumber.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getStatus&id=1042

Ответ

STATUS_OK:48213

Возможные ошибки: NO_ACTIVATION

setStatus

Действие с заказом: готов, ещё код, завершить, отменить (см. «Статусы»).

ПараметрОбязательныйОписание
idдаНомер заказа.
statusда1, 3, 6 или 8.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=setStatus&id=1042&status=6

Ответ

ACCESS_ACTIVATION

Возможные ошибки: NO_ACTIVATION, BAD_STATUS, EARLY_CANCEL_DENIED, ERROR_SQL

getActiveActivations

Все открытые заказы ключа: номер, статус, пришедшие коды и тексты.

Только api_key и action.

GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getActiveActivations

Ответ

{
  "status": "success",
  "activeActivations": [
    {
      "activationId": 1042,
      "serviceCode": "tg",
      "phoneNumber": "15550001111",
      "activationCost": 0.59,
      "activationStatus": "2",
      "smsCode": ["48213"],
      "smsText": ["Telegram code: 48213"],
      "activationTime": "2026-10-27T10:00:00.000Z",
      "countryCode": "187"
    }
  ]
}

getPrices

Наши цены в долларах и примерное количество номеров. Без параметров — всё, что продаётся.

ПараметрОбязательныйОписание
serviceнетТолько этот сервис.
countryнетТолько эта страна.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getPrices&service=tg&country=187

Ответ

{ "187": { "tg": { "cost": 0.59, "count": 1000 } } }

Возможные ошибки: BAD_SERVICE, BAD_COUNTRY

getCountries

Список стран с кодами протокола и названиями на русском и английском.

Только api_key и action.

GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getCountries

Ответ

{ "187": { "id": 187, "rus": "США", "eng": "United States", "visible": 1 } }

getServicesList

Список сервисов с кодами протокола.

Только api_key и action.

GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getServicesList

Ответ

{ "status": "success", "services": [{ "code": "tg", "name": "Telegram" }] }

Статусы

Значения status в setStatus:

  • status=1 → ACCESS_READY — Номер введён в сервис, ждём код. Ничего не меняет, оставлен для совместимости.
  • status=3 → ACCESS_RETRY_GET — Попросить ещё один код на тот же номер — после первого кода, пока заказ открыт. Бесплатно. До нового кода getStatus отвечает STATUS_WAIT_RETRY.
  • status=6 → ACCESS_ACTIVATION — Завершить заказ после кода. Новые SMS на номер больше не придут.
  • status=8 → ACCESS_CANCEL — Отменить заказ без кода (не раньше чем через 2 минуты). Деньги возвращаются на баланс.

Ответы getStatus:

  • STATUS_WAIT_CODE — Код ещё не пришёл — спросите снова через 5–10 секунд.
  • STATUS_OK:48213 — Код пришёл; после двоеточия — сам код (или текст SMS, если кода в нём нет).
  • STATUS_WAIT_RETRY:48213 — Запрошен ещё один код, он пока не пришёл; после двоеточия — предыдущий код.
  • STATUS_CANCEL — Заказ отменён или закрыт без кода; деньги уже на балансе.

Ошибки

Ошибки приходят строкой, как принято в этом протоколе. Всё, кроме RATE_LIMIT, отвечает со статусом 200.

NO_KEYНе передан api_key.
BAD_KEYКлюч неверный, выключен или аккаунт заблокирован.
BAD_ACTIONНеизвестное действие.
BAD_SERVICEНет такого кода сервиса.
BAD_COUNTRYНет такого кода страны.
NO_NUMBERSНомеров для этой пары сейчас нет; деньги не списаны.
NO_BALANCEНа балансе меньше $20 (порог API) или меньше цены номера.
WRONG_MAX_PRICEЦена выше maxPrice; после двоеточия — текущая цена.
LIMIT_ACTIVATIONSСлишком много открытых заказов — завершите или отмените часть.
RATE_LIMITСлишком часто; HTTP 429. Повторите через секунду.
BANNEDАккаунт заблокирован — напишите в поддержку.
NO_ACTIVATIONНет заказа с таким номером у этого ключа.
BAD_STATUSЭто действие сейчас недоступно для заказа (например, завершить без кода).
EARLY_CANCEL_DENIEDОтменить можно только через 2 минуты после покупки.
ERROR_SQLВременная ошибка на нашей стороне — повторите запрос через минуту.

Коды сервисов и стран

Коды — стандартные для протокола: tg — Telegram, wa — WhatsApp и так далее; страна 187 — США. Полные списки отдают getServicesList и getCountries — берите коды оттуда, а не из старых таблиц: набор сервисов и стран меняется вместе с наличием.

REST API v1

Те же номера и те же правила, что в handler_api.php, но в JSON: сервисы по названию (telegram), страны по ISO-коду (US), HTTP-статусы и коды ошибок, по которым программе удобно ветвиться. Для нового кода — сюда; софт, который уже говорит на handler_api.php, оставьте как есть.

https://relysms.pro/api/v1

Ключ

Ключ передаётся в заголовке: Authorization: Bearer <ключ> (или X-Api-Key: <ключ>). Не в адресе — адреса попадают в логи. Лимиты, порог $20 и каталог те же, что у handler_api.php.

Повторы без двойных покупок

К POST /orders и /orders/batch добавляйте заголовок Idempotency-Key со своим значением (UUID, до 255 символов). Если связь оборвалась и вы повторили запрос с тем же ключом, придёт первый ответ (с заголовком Idempotent-Replayed: true), и ничего не купится дважды. Тот же ключ с другим телом запроса отклоняется; повтор, пришедший, пока первый ещё выполняется, получит idempotency_in_progress. Успешные ответы хранятся 24 часа; неудачная покупка ничего не списала, её можно повторить с тем же ключом.

Несколько номеров сразу

POST /orders/batch покупает до 20 номеров одного сервиса и страны за один запрос — так можно покупать быстрее 5 в секунду. Покупки идут по очереди; первая неудачная останавливает пачку, и в ответе будет то, что купилось, а причина — в stoppedBy. Если не купилось ничего, ответом будет сама ошибка.

Страницы

GET /orders отдаёт сначала новые. Если next не null, передайте его в before — получите следующую страницу.

Вебхуки

Вместо опроса GET /orders/{id} задайте HTTPS-адрес через PUT /webhook — мы пришлём на него POST, когда с заказом, купленным через API, что-то произойдёт. В теле — заказ в том виде, в каком он был в момент отправки. Отвечайте любым 2xx в течение 10 секунд; у одного заказа может быть несколько событий, а одно событие после повтора может прийти дважды — ориентируйтесь на id доставки.

  • order.code_received — Пришёл код (каждый новый код — снова это событие).
  • order.finished — Заказ завершён — вами или по окончании времени после кода.
  • order.cancelled — Отменён без кода; деньги вернулись на баланс.
  • order.expired — Время вышло без кода; деньги вернулись на баланс.
  • ping — Проверка из POST /webhook/test; order — null.
POST /relysms-hook HTTP/1.1
Content-Type: application/json
X-RelySMS-Event: order.code_received
X-RelySMS-Delivery: cm…
X-RelySMS-Signature: t=1793095272,v1=5f2b…

{
  "id": "cm…",
  "event": "order.code_received",
  "createdAt": "2026-10-27T10:01:12.000Z",
  "order": { "id": 1042, "status": "received", "codes": [{ "code": "48213", … }], … }
}

В каждом запросе есть заголовок X-RelySMS-Signature: t=<unix-время>,v1=<подпись>. Подпись — HMAC-SHA256 строки «t.тело» (тело как есть, байт в байт) с секретом вебхука, в hex. Проверьте её и что t не старше 5 минут, прежде чем доверять телу.

Python

import hashlib, hmac, time

def verify(secret: str, body: bytes, header: str, tolerance=300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t, sig = parts.get("t", ""), parts.get("v1", "")
    if not t.isdigit() or abs(time.time() - int(t)) > tolerance:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, sig)

Node.js

import { createHmac, timingSafeEqual } from "node:crypto";

export function verify(secret, rawBody, header, tolerance = 300) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
  const t = Number(parts.t);
  if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > tolerance) return false;
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  return expected.length === parts.v1?.length && timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1));
}

Если ваш сервер не ответил 2xx, мы повторим через 10 секунд, 1 минуту, 5 минут, 30 минут, 2 часа и 6 часов — всего 7 попыток, потом сдаёмся. GET /webhook/deliveries показывает, что ушло и что не дошло.

Методы

GET /balance

Баланс в долларах и хватает ли его для покупок через API.

curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/balance

Ответ

{ "balance": 25, "currency": "USD", "canBuy": true, "apiMinimum": 20 }

GET /services

Все сервисы в продаже: наш id, название и код handler_api.php.

ПараметрОбязательныйОписание
lang queryнетЯзык названий: en (по умолчанию), ru, uk, zh, es, pt, id, vi, tr, ar, fr.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/services?lang=en"

Ответ

{ "services": [{ "id": "telegram", "name": "Telegram", "protocolCode": "tg" }] }

GET /countries

Все страны в продаже: ISO-код, название и код handler_api.php.

ПараметрОбязательныйОписание
lang queryнетЯзык названий: en (по умолчанию), ru, uk, zh, es, pt, id, vi, tr, ar, fr.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/countries?lang=en"

Ответ

{ "countries": [{ "id": "US", "name": "United States", "protocolCode": 187 }] }

GET /prices

Наши цены в долларах и примерное число номеров. Без параметров — всё, что продаётся.

ПараметрОбязательныйОписание
service queryнетId сервиса из /services, например telegram.
country queryнетISO-код страны из /countries, например US.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/prices?service=telegram"

Ответ

{ "prices": [{ "service": "telegram", "country": "US", "price": 0.59, "stock": 1000 }] }

Возможные ошибки: unknown_service, unknown_country

POST /orders

Купить номер. Деньги списываются сразу и возвращаются, если код не придёт.

ПараметрОбязательныйОписание
service bodyдаId сервиса из /services, например telegram.
country bodyдаISO-код страны из /countries, например US.
maxPrice bodyнетМаксимальная цена в долларах, число. Дороже — price_above_max с текущей ценой, ничего не списано.
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c1f0e2a-run-1" \
  -d '{"service":"telegram","country":"US","maxPrice":0.8}' \
  https://relysms.pro/api/v1/orders

Ответ

{
  "order": {
    "id": 1042,
    "service": "telegram",
    "country": "US",
    "phone": "15550001111",
    "price": 0.59,
    "status": "waiting",
    "refunded": false,
    "codes": [],
    "awaitingAnotherCode": false,
    "createdAt": "2026-10-27T10:00:00.000Z",
    "expiresAt": "2026-10-27T10:20:00.000Z",
    "cancelableAt": "2026-10-27T10:02:00.000Z"
  }
}

Возможные ошибки: bad_request, unknown_service, unknown_country, no_numbers, insufficient_balance, below_api_minimum, price_above_max, too_many_open_orders, buying_too_fast, idempotency_key_reused, idempotency_in_progress

POST /orders/batch

Купить до 20 номеров одного сервиса и страны за один запрос.

ПараметрОбязательныйОписание
service bodyдаId сервиса из /services, например telegram.
country bodyдаISO-код страны из /countries, например US.
quantity bodyдаСколько номеров, от 1 до 20.
maxPrice bodyнетМаксимальная цена в долларах, число. Дороже — price_above_max с текущей ценой, ничего не списано.
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7c1f0e2a-batch-1" \
  -d '{"service":"telegram","country":"US","quantity":5}' \
  https://relysms.pro/api/v1/orders/batch

Ответ

{
  "orders": [{ "id": 1043, "phone": "15550001112", … }, { "id": 1044, … }],
  "requested": 5,
  "placed": 2,
  "stoppedBy": { "code": "no_numbers", "message": "…" }
}

Возможные ошибки: bad_request, unknown_service, unknown_country, no_numbers, insufficient_balance, below_api_minimum, price_above_max, too_many_open_orders, buying_too_fast, idempotency_key_reused, idempotency_in_progress

GET /orders

Ваши заказы, сначала новые: по умолчанию открытые, или все.

ПараметрОбязательныйОписание
status queryнетopen (по умолчанию) — ждут кода или с кодом; all — все заказы.
limit queryнетЗаказов на странице, от 1 до 100 (по умолчанию 50).
before queryнетЗначение next с предыдущей страницы.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/orders?status=all&limit=50"

Ответ

{ "orders": [{ "id": 1042, … }], "next": "1001" }

Возможные ошибки: bad_request

GET /orders/{id}

Один заказ с кодами. Пока статус waiting — опрашивайте раз в 5–10 секунд.

ПараметрОбязательныйОписание
id pathдаId заказа из ответа на покупку.
curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042

Ответ

{
  "order": {
    "id": 1042,
    "status": "received",
    "codes": [{ "code": "48213", "text": "Telegram code: 48213", "receivedAt": "2026-10-27T10:01:12.000Z" }],
    …
  }
}

Возможные ошибки: not_found

POST /orders/{id}/finish

Завершить заказ с кодом. Новые SMS на номер не придут. Повтор безвреден.

ПараметрОбязательныйОписание
id pathдаId заказа из ответа на покупку.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/finish

Ответ

{ "order": { "id": 1042, "status": "finished", … } }

Возможные ошибки: not_found, invalid_state

POST /orders/{id}/another-code

Ещё один код на тот же номер — после первого кода, пока заказ открыт. Бесплатно. До нового кода в заказе awaitingAnotherCode = true.

ПараметрОбязательныйОписание
id pathдаId заказа из ответа на покупку.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/another-code

Ответ

{ "order": { "id": 1042, "status": "received", "awaitingAnotherCode": true, … } }

Возможные ошибки: not_found, invalid_state, try_later

POST /orders/{id}/cancel

Отменить заказ без кода — через 2 минуты после покупки. Деньги возвращаются сразу.

ПараметрОбязательныйОписание
id pathдаId заказа из ответа на покупку.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/cancel

Ответ

{ "order": { "id": 1042, "status": "cancelled", "refunded": true, … } }

Возможные ошибки: not_found, invalid_state, too_early_to_cancel

GET /webhook

Адрес вебхука и секрет подписи, или null.

curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook

Ответ

{ "webhook": { "url": "https://example.com/relysms-hook", "secret": "whsec_…", "createdAt": "2026-10-27T10:00:00.000Z" } }

PUT /webhook

Задать или сменить адрес. Секрет создаётся один раз и сохраняется; rotateSecret выпускает новый.

ПараметрОбязательныйОписание
url bodyдаHTTPS-адрес вашего сервера. Частные и локальные адреса не принимаются.
rotateSecret bodyнетtrue — выпустить новый секрет подписи.
curl -X PUT -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/relysms-hook"}' \
  https://relysms.pro/api/v1/webhook

Ответ

{ "webhook": { "url": "https://example.com/relysms-hook", "secret": "whsec_…", "createdAt": "2026-10-27T10:00:00.000Z" } }

Возможные ошибки: bad_request, invalid_webhook_url

DELETE /webhook

Удалить вебхук. Ещё не отправленные события отбрасываются.

curl -X DELETE -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook

Ответ

{ "webhook": null }

POST /webhook/test

Отправить событие ping — проверить адрес и подпись.

curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook/test

Ответ

{ "delivery": { "id": "cm…" } }

Возможные ошибки: not_found

GET /webhook/deliveries

Последние 20 доставок: событие, статус, попытки, последний ответ вашего сервера.

curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/webhook/deliveries

Ответ

{
  "deliveries": [{
    "id": "cm…", "event": "order.code_received", "orderId": 1042,
    "status": "pending", "attempts": 2, "lastHttpStatus": 502, "lastError": "HTTP 502",
    "createdAt": "2026-10-27T10:01:12.000Z", "deliveredAt": null, "nextAttemptAt": "2026-10-27T10:02:22.000Z"
  }]
}

Статусы заказа

Поле status заказа:

  • waiting — Номер ваш, кода ещё нет.
  • received — Код пришёл, он в codes. Пока заказ открыт, могут прийти ещё коды.
  • finished — Вы завершили заказ (или после кода закончилось время).
  • cancelled — Отменён без кода; refunded — true, деньги на балансе.
  • expired — Время вышло без кода; деньги вернулись на баланс.

Ошибки

Ошибка — это HTTP-статус и JSON с полем code, по которому удобно ветвиться, и message для людей. У некоторых есть доп. поля (price, cancelableAt, apiMinimum).

{ "error": { "code": "price_above_max", "message": "The price is above maxPrice.", "price": 0.59 } }
missing_key401Нет ключа в Authorization или X-Api-Key.
invalid_key401Ключ неверный, заменён новым, или аккаунт заблокирован.
bad_request400Ошибка в теле или параметре; в message сказано, где.
unknown_service400Нет сервиса с таким id.
unknown_country400Нет страны с таким кодом.
idempotency_key_invalid400Idempotency-Key пустой или длиннее 255 символов.
invalid_webhook_url400Адрес вебхука не HTTPS, не адрес вовсе или ведёт на частный или локальный сервер.
insufficient_balance402На балансе меньше цены номера.
below_api_minimum402На балансе меньше $20 — API покупает только от $20.
account_blocked403Аккаунт заблокирован — напишите в поддержку.
not_found404Нет заказа с таким id у этого ключа.
no_numbers409Номеров для этой пары сейчас нет; ничего не списано.
price_above_max409Цена выше maxPrice; текущая — в поле price.
too_many_open_orders409Слишком много открытых заказов — завершите или отмените часть.
invalid_state409В этом статусе так нельзя (например, завершить без кода).
too_early_to_cancel409Отменить можно с момента cancelableAt — через 2 минуты после покупки.
idempotency_in_progress409Запрос с этим Idempotency-Key ещё выполняется; повторите чуть позже.
idempotency_key_reused422Этот Idempotency-Key уже использован для другого запроса.
rate_limited429Больше 20 запросов в секунду; когда повторить — в Retry-After.
buying_too_fast429Больше 5 покупок в секунду; используйте /orders/batch.
try_later503Временно не получилось — повторите через минуту.

Примеры REST

Купить номер, дождаться кода, завершить заказ.

Python

import time, uuid, requests

BASE = "https://relysms.pro/api/v1"
S = requests.Session()
S.headers["Authorization"] = "Bearer rs_your_key"

r = S.post(f"{BASE}/orders",
           json={"service": "telegram", "country": "US", "maxPrice": 0.8},
           headers={"Idempotency-Key": str(uuid.uuid4())}, timeout=30)
if r.status_code != 201:
    raise SystemExit(r.json()["error"])   # no_numbers, below_api_minimum, …
order = r.json()["order"]
print("number:", order["phone"])

while order["status"] == "waiting":       # up to 20 minutes
    time.sleep(10)
    order = S.get(f"{BASE}/orders/{order['id']}", timeout=30).json()["order"]

if order["status"] == "received":
    print("code:", order["codes"][-1]["code"])
    S.post(f"{BASE}/orders/{order['id']}/finish", timeout=30)
# "expired" or "cancelled": the money is back on the balance

Node.js

const BASE = "https://relysms.pro/api/v1";
const headers = { Authorization: "Bearer rs_your_key", "Content-Type": "application/json" };

const res = await fetch(`${BASE}/orders`, {
  method: "POST",
  headers: { ...headers, "Idempotency-Key": crypto.randomUUID() },
  body: JSON.stringify({ service: "telegram", country: "US", maxPrice: 0.8 }),
});
if (res.status !== 201) throw new Error((await res.json()).error.code);
let { order } = await res.json();
console.log("number:", order.phone);

while (order.status === "waiting") {
  await new Promise((r) => setTimeout(r, 10_000));
  ({ order } = await (await fetch(`${BASE}/orders/${order.id}`, { headers })).json());
}
if (order.status === "received") {
  console.log("code:", order.codes.at(-1).code);
  await fetch(`${BASE}/orders/${order.id}/finish`, { method: "POST", headers });
}

Примеры

Полный цикл: купить номер, дождаться кода, завершить заказ.

curl

KEY=rs_your_key
BASE=https://relysms.pro/stubs/handler_api.php

curl "$BASE?api_key=$KEY&action=getBalance"
curl "$BASE?api_key=$KEY&action=getNumber&service=tg&country=187&maxPrice=0.80"
# → ACCESS_NUMBER:1042:15550001111
curl "$BASE?api_key=$KEY&action=getStatus&id=1042"
# → STATUS_WAIT_CODE … then STATUS_OK:48213
curl "$BASE?api_key=$KEY&action=setStatus&id=1042&status=6"

Python

import time, requests

BASE = "https://relysms.pro/stubs/handler_api.php"
KEY = "rs_your_key"

def call(action, **params):
    r = requests.get(BASE, params={"api_key": KEY, "action": action, **params}, timeout=30)
    r.raise_for_status()
    return r.text

answer = call("getNumber", service="tg", country="187", maxPrice="0.80")
if not answer.startswith("ACCESS_NUMBER"):
    raise SystemExit(answer)          # NO_NUMBERS, NO_BALANCE, …
_, order_id, phone = answer.split(":")
print("number:", phone)

for _ in range(120):                  # up to 20 minutes, every 10 s
    status = call("getStatus", id=order_id)
    if status.startswith("STATUS_OK:"):
        print("code:", status.split(":", 1)[1])
        call("setStatus", id=order_id, status=6)
        break
    if status == "STATUS_CANCEL":
        break                         # refunded automatically
    time.sleep(10)

Node.js

const BASE = "https://relysms.pro/stubs/handler_api.php";
const KEY = "rs_your_key";

async function call(action, params = {}) {
  const url = new URL(BASE);
  url.search = new URLSearchParams({ api_key: KEY, action, ...params });
  const res = await fetch(url);
  return res.text();
}

const answer = await call("getNumber", { service: "tg", country: "187", maxPrice: "0.80" });
if (!answer.startsWith("ACCESS_NUMBER")) throw new Error(answer);
const [, id, phone] = answer.split(":");
console.log("number:", phone);

for (let i = 0; i < 120; i++) {
  const status = await call("getStatus", { id });
  if (status.startsWith("STATUS_OK:")) {
    console.log("code:", status.slice("STATUS_OK:".length));
    await call("setStatus", { id, status: "6" });
    break;
  }
  if (status === "STATUS_CANCEL") break; // refunded automatically
  await new Promise((r) => setTimeout(r, 10_000));
}

Вопросы

Мой софт работал с другим сервисом активаций. Что поменять?

Адрес сервера — на https://relysms.pro/stubs/handler_api.php, ключ — на ключ из кабинета. Коды сервисов и стран те же.

Почему NO_BALANCE, если деньги на балансе есть?

Покупки через API работают при балансе от $20. В кабинете и Mini App этого порога нет.

Что с деньгами, если код не пришёл?

Вернутся на баланс сами, когда окно закроется, или сразу — при отмене через 2 минуты.

Можно получить второй код на тот же номер?

Да, пока окно открыто: setStatus=3 и снова getStatus.

Есть тестовый режим?

Нет: все покупки настоящие. Начните с дешёвой пары и проверьте поток на одном номере.

Ключ утёк. Что делать?

Кабинет → «Баланс» → «API» → «Выпустить новый». Старый перестаёт работать сразу.

Для ИИ-ассистентов

Полная документация одним текстом для ChatGPT, Claude и других моделей лежит в /ru/developers.md (на английском — /developers.md), краткая карта — в /llms.txt. Дайте модели ссылку — и попросите подключить RelySMS к вашему коду.

Прочитай https://relysms.pro/ru/developers.md и подключи RelySMS к моему скрипту.

developers.md · llms.txt