RelySMS
API · protocolo handler_api.php

Números para recibir SMS, desde tu propio software

Si tu software ya funciona con un servicio de activaciones mediante handler_api.php, funciona con RelySMS: cambia la dirección del servidor y la clave. Mismas acciones, mismas respuestas, nuestros precios y reembolsos.

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

Inicio rápido

  1. Entra en tu cuenta y abre Saldo → API → Crear clave. La clave se muestra una sola vez: guárdala.
  2. Recarga hasta $20 o más: las compras por API solo pasan con ese saldo. Puedes tener la clave con saldo cero.
  3. Configura en tu software el servidor https://relysms.pro/stubs/handler_api.php y tu clave en lugar de la del servicio anterior.
  4. Compra un número (getNumber) y consulta el estado cada 5–10 segundos (getStatus) hasta recibir STATUS_OK con el código.
  5. Termina el pedido (setStatus=6). Si no llega código, cancela a los 2 minutos (setStatus=8) o deja que termine la ventana: el dinero vuelve solo.

Reglas y límites

  • Las compras por API requieren un saldo de al menos $20. Por debajo, getNumber responde NO_BALANCE; los demás métodos funcionan.
  • El número es tuyo 20 minutos. Sin código, el pedido se cierra solo y el dinero vuelve a tu saldo.
  • Puedes cancelar 2 minutos después de comprar si no ha llegado código. El dinero vuelve al instante.
  • Con el primer código el pedido queda pagado y no se reembolsa. Mientras la ventana siga abierta pueden llegar más códigos.
  • Hasta 20 peticiones y 5 compras por segundo por clave; hasta 50 pedidos abiertos a la vez.
  • El precio se fija al comprar. maxPrice evita comprar por encima de tu límite.
  • Se aplican las condiciones del servicio: prohibidos el spam, el fraude y los registros masivos con esos fines.

Métodos

Cada petición es un GET o POST a una sola dirección, con parámetros en la URL o en un formulario. La clave va en api_key y la acción en action.

getBalance

El saldo de la cuenta en dólares.

Solo api_key y action.

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

Respuesta

ACCESS_BALANCE:25.00

getNumber

Comprar un número para un servicio en un país. Se cobra al momento; se reembolsa si no llega el código. Respuesta: ACCESS_NUMBER:número_de_pedido:teléfono.

ParámetroObligatorioDescripción
servicesíCódigo del servicio (getServicesList), p. ej. tg.
countrysíCódigo del país (getCountries).
maxPricenoPrecio máximo en dólares. Si es más caro: WRONG_MAX_PRICE con el precio actual, sin cobro.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getNumber&service=tg&country=187&maxPrice=0.80

Respuesta

ACCESS_NUMBER:1042:15550001111

Errores posibles: BAD_SERVICE, BAD_COUNTRY, NO_NUMBERS, NO_BALANCE, WRONG_MAX_PRICE:0.59, LIMIT_ACTIVATIONS, RATE_LIMIT, BANNED

getNumberV2

Igual que getNumber, con respuesta JSON que incluye el precio y los tiempos de la ventana.

ParámetroObligatorioDescripción
servicesíCódigo del servicio.
countrysíCódigo del país.
maxPricenoPrecio máximo en dólares.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getNumberV2&service=tg&country=187&maxPrice=0.80

Respuesta

{
  "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"
}

Errores posibles: BAD_SERVICE, BAD_COUNTRY, NO_NUMBERS, NO_BALANCE, WRONG_MAX_PRICE:0.59, LIMIT_ACTIVATIONS, RATE_LIMIT

getStatus

Estado del pedido: esperando código, código recibido (con el código) o cancelado.

ParámetroObligatorioDescripción
idsíNúmero de pedido de getNumber.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getStatus&id=1042

Respuesta

STATUS_OK:48213

Errores posibles: NO_ACTIVATION

setStatus

Actuar sobre un pedido: listo, otro código, terminar, cancelar (ver Estados).

ParámetroObligatorioDescripción
idsíNúmero de pedido.
statussí1, 3, 6 u 8.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=setStatus&id=1042&status=6

Respuesta

ACCESS_ACTIVATION

Errores posibles: NO_ACTIVATION, BAD_STATUS, EARLY_CANCEL_DENIED, ERROR_SQL

getActiveActivations

Todos los pedidos abiertos de la clave: número, estado, códigos y textos recibidos.

Solo api_key y action.

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

Respuesta

{
  "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

Nuestros precios en dólares y cuántos números hay aproximadamente. Sin parámetros: todo lo que está a la venta.

ParámetroObligatorioDescripción
servicenoSolo este servicio.
countrynoSolo este país.
GET https://relysms.pro/stubs/handler_api.php?api_key=KEY&action=getPrices&service=tg&country=187

Respuesta

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

Errores posibles: BAD_SERVICE, BAD_COUNTRY

getCountries

Países con códigos del protocolo y nombres en ruso e inglés.

Solo api_key y action.

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

Respuesta

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

getServicesList

Servicios con códigos del protocolo.

Solo api_key y action.

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

Respuesta

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

Estados

Valores de status en setStatus:

  • status=1 → ACCESS_READY — El número está introducido en el servicio; esperando código. No cambia nada; se mantiene por compatibilidad.
  • status=3 → ACCESS_RETRY_GET — Pedir otro código al mismo número: después del primer código y mientras el pedido siga abierto. Gratis. Hasta que llegue, getStatus responde STATUS_WAIT_RETRY.
  • status=6 → ACCESS_ACTIVATION — Terminar el pedido tras el código. No llegarán más SMS al número.
  • status=8 → ACCESS_CANCEL — Cancelar un pedido sin código (no antes de 2 minutos). El dinero vuelve a tu saldo.

Respuestas de getStatus:

  • STATUS_WAIT_CODE — Aún no hay código: vuelve a preguntar en 5–10 segundos.
  • STATUS_OK:48213 — Llegó el código; tras los dos puntos va el código (o el texto del SMS si no lo contiene).
  • STATUS_WAIT_RETRY:48213 — Se pidió otro código y aún no llegó; tras los dos puntos va el código anterior.
  • STATUS_CANCEL — Cancelado o cerrado sin código; el dinero ya está en tu saldo.

Errores

Los errores llegan como texto plano, como es habitual en este protocolo. Todos, salvo RATE_LIMIT, llegan con estado 200.

NO_KEYFalta api_key.
BAD_KEYClave incorrecta o desactivada, o cuenta bloqueada.
BAD_ACTIONAcción desconocida.
BAD_SERVICENo existe ese código de servicio.
BAD_COUNTRYNo existe ese código de país.
NO_NUMBERSAhora no hay números para esa combinación; no se cobró nada.
NO_BALANCEMenos de $20 de saldo (umbral de la API) o menos que el precio.
WRONG_MAX_PRICEEl precio supera maxPrice; tras los dos puntos va el precio actual.
LIMIT_ACTIVATIONSDemasiados pedidos abiertos: termina o cancela algunos.
RATE_LIMITDemasiado frecuente; HTTP 429. Reintenta en un segundo.
BANNEDLa cuenta está bloqueada: contacta con soporte.
NO_ACTIVATIONNo hay ningún pedido con ese número para esta clave.
BAD_STATUSEsa acción no está disponible ahora para el pedido (p. ej., terminar sin código).
EARLY_CANCEL_DENIEDSolo se puede cancelar 2 minutos después de la compra.
ERROR_SQLError temporal de nuestro lado: repite la solicitud en un minuto.

Códigos de servicios y países

Los códigos son los estándar del protocolo: tg — Telegram, wa — WhatsApp, etc.; el país 187 — EE. UU. getServicesList y getCountries devuelven las listas completas: toma los códigos de ahí, no de tablas antiguas, porque servicios y países cambian con el stock.

REST API v1

Los mismos números y las mismas reglas que handler_api.php, en JSON: servicios por nombre (telegram), países por código ISO (US), estados HTTP y códigos de error con los que un programa puede decidir. Úsala para código nuevo; deja handler_api.php para el software que ya lo usa.

https://relysms.pro/api/v1

Clave

Envía la clave en un encabezado: Authorization: Bearer <clave> (o X-Api-Key: <clave>). Nunca en la URL: las URL acaban en los logs. Los límites, el mínimo de $20 y el catálogo son los mismos que en handler_api.php.

Reintentos sin compras dobles

Añade el encabezado Idempotency-Key con un valor propio (un UUID, hasta 255 caracteres) en POST /orders y /orders/batch. Si se corta la conexión y repites la petición con la misma clave, recibes la primera respuesta (con el encabezado Idempotent-Replayed: true) y no se compra nada dos veces. La misma clave con otro cuerpo se rechaza; una repetición que llega mientras la primera sigue en curso recibe idempotency_in_progress. Las respuestas correctas se guardan 24 horas; una compra fallida no cobró nada y puede repetirse con la misma clave.

Varios números a la vez

POST /orders/batch compra hasta 20 números de un servicio y país en una sola petición: es la forma de comprar más de 5 por segundo. Las compras van una tras otra; la primera que falla detiene el lote, y la respuesta trae lo comprado y el motivo en stoppedBy. Si no se compró nada, la respuesta es ese error.

Páginas

GET /orders devuelve primero los más nuevos. Si next no es null, pásalo como before para obtener la página siguiente.

Webhooks

En lugar de consultar GET /orders/{id}, define una dirección HTTPS con PUT /webhook y te enviaremos un POST cuando algo le pase a un pedido comprado por la API. El cuerpo trae el pedido tal como está al enviarse. Responde con cualquier 2xx en 10 segundos; un pedido puede generar varios eventos y el mismo evento puede llegar dos veces tras un reintento, así que usa el id de la entrega.

  • order.code_received — Llegó un código (cada nuevo lo envía otra vez).
  • order.finished — El pedido se terminó: por ti, o al acabarse su tiempo después de un código.
  • order.cancelled — Cancelado sin código; el dinero volvió al saldo.
  • order.expired — Se acabó el tiempo sin código; el dinero volvió al saldo.
  • ping — Una prueba de POST /webhook/test; order es 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", … }], … }
}

Cada petición trae X-RelySMS-Signature: t=<hora unix>,v1=<firma>. La firma es HMAC-SHA256 de la cadena "t.cuerpo" (el cuerpo tal cual, byte a byte) con el secreto del webhook, en hex. Verifícala, y que t no tenga más de 5 minutos, antes de confiar en el cuerpo.

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));
}

Si tu servidor no responde 2xx, reintentamos a los 10 segundos, 1 minuto, 5 minutos, 30 minutos, 2 horas y 6 horas —7 intentos en total— y luego lo dejamos. GET /webhook/deliveries muestra qué se envió y qué falló.

Endpoints

GET /balance

El saldo en dólares y si alcanza para comprar por la API.

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

Respuesta

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

GET /services

Todos los servicios a la venta: nuestro id, el nombre y el código de handler_api.php.

ParámetroObligatorioDescripción
lang querynoIdioma de los nombres: en (por defecto), ru, uk, zh, es, pt, id, vi, tr, ar, fr.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/services?lang=en"

Respuesta

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

GET /countries

Todos los países a la venta: código ISO, nombre y código de handler_api.php.

ParámetroObligatorioDescripción
lang querynoIdioma de los nombres: en (por defecto), ru, uk, zh, es, pt, id, vi, tr, ar, fr.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/countries?lang=en"

Respuesta

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

GET /prices

Nuestros precios en dólares y cuántos números hay aproximadamente. Sin parámetros, todo lo que está a la venta.

ParámetroObligatorioDescripción
service querynoId del servicio de /services, p. ej. telegram.
country querynoCódigo ISO del país de /countries, p. ej. US.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/prices?service=telegram"

Respuesta

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

Errores posibles: unknown_service, unknown_country

POST /orders

Comprar un número. Se cobra al instante y se devuelve si no llega el código.

ParámetroObligatorioDescripción
service bodysíId del servicio de /services, p. ej. telegram.
country bodysíCódigo ISO del país de /countries, p. ej. US.
maxPrice bodynoPrecio máximo en dólares, un número. Por encima: price_above_max con el precio actual, sin cobro.
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

Respuesta

{
  "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"
  }
}

Errores posibles: 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

Comprar hasta 20 números de un servicio y país en una sola petición.

ParámetroObligatorioDescripción
service bodysíId del servicio de /services, p. ej. telegram.
country bodysíCódigo ISO del país de /countries, p. ej. US.
quantity bodysíCuántos números, de 1 a 20.
maxPrice bodynoPrecio máximo en dólares, un número. Por encima: price_above_max con el precio actual, sin cobro.
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

Respuesta

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

Errores posibles: 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

Tus pedidos, los más nuevos primero: los abiertos por defecto, o todos.

ParámetroObligatorioDescripción
status querynoopen (por defecto): esperando o con código; all: todos los pedidos.
limit querynoPedidos por página, de 1 a 100 (por defecto 50).
before querynoEl valor next de la página anterior.
curl -H "Authorization: Bearer $KEY" "https://relysms.pro/api/v1/orders?status=all&limit=50"

Respuesta

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

Errores posibles: bad_request

GET /orders/{id}

Un pedido con sus códigos. Consulta cada 5–10 segundos mientras el estado sea waiting.

ParámetroObligatorioDescripción
id pathsíEl id del pedido de la respuesta de compra.
curl -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042

Respuesta

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

Errores posibles: not_found

POST /orders/{id}/finish

Terminar un pedido con código. El número no recibirá más SMS. Repetirlo no hace daño.

ParámetroObligatorioDescripción
id pathsíEl id del pedido de la respuesta de compra.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/finish

Respuesta

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

Errores posibles: not_found, invalid_state

POST /orders/{id}/another-code

Otro código al mismo número: después del primer código y mientras el pedido siga abierto. Gratis. Hasta que llegue, el pedido tiene awaitingAnotherCode = true.

ParámetroObligatorioDescripción
id pathsíEl id del pedido de la respuesta de compra.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/another-code

Respuesta

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

Errores posibles: not_found, invalid_state, try_later

POST /orders/{id}/cancel

Cancelar un pedido sin código, a partir de 2 minutos tras la compra. El dinero vuelve al instante.

ParámetroObligatorioDescripción
id pathsíEl id del pedido de la respuesta de compra.
curl -X POST -H "Authorization: Bearer $KEY" https://relysms.pro/api/v1/orders/1042/cancel

Respuesta

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

Errores posibles: not_found, invalid_state, too_early_to_cancel

GET /webhook

La dirección del webhook y su secreto de firma, o null.

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

Respuesta

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

PUT /webhook

Definir o cambiar la dirección. El secreto se crea una vez y se conserva; rotateSecret crea uno nuevo.

ParámetroObligatorioDescripción
url bodysíDirección HTTPS de tu servidor. Se rechazan direcciones privadas y locales.
rotateSecret bodynotrue: crear un nuevo secreto de firma.
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

Respuesta

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

Errores posibles: bad_request, invalid_webhook_url

DELETE /webhook

Quitar el webhook. Los eventos aún no enviados se descartan.

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

Respuesta

{ "webhook": null }

POST /webhook/test

Enviar un evento ping para comprobar la dirección y la firma.

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

Respuesta

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

Errores posibles: not_found

GET /webhook/deliveries

Las últimas 20 entregas: evento, estado, intentos, última respuesta de tu servidor.

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

Respuesta

{
  "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"
  }]
}

Estados del pedido

El campo status de un pedido:

  • waiting — El número es tuyo y aún no llegó ningún código.
  • received — Llegó un código; está en codes. Pueden llegar más mientras el pedido siga abierto.
  • finished — Terminaste el pedido (o se acabó su tiempo después de un código).
  • cancelled — Cancelado sin código; refunded es true y el dinero está en el saldo.
  • expired — Se acabó el tiempo sin código; el dinero volvió al saldo.

Errores

Un error es un estado HTTP y un JSON con code para que el programa decida y message para las personas. Algunos traen campos extra (price, cancelableAt, apiMinimum).

{ "error": { "code": "price_above_max", "message": "The price is above maxPrice.", "price": 0.59 } }
missing_key401No hay clave en Authorization ni en X-Api-Key.
invalid_key401La clave es incorrecta, fue reemplazada o la cuenta está bloqueada.
bad_request400El cuerpo o un parámetro es incorrecto; message dice cuál.
unknown_service400No existe ese id de servicio.
unknown_country400No existe ese código de país.
idempotency_key_invalid400Idempotency-Key está vacío o supera los 255 caracteres.
invalid_webhook_url400La dirección del webhook no es HTTPS, no es una URL o apunta a un servidor privado o local.
insufficient_balance402El saldo es menor que el precio.
below_api_minimum402Menos de $20 de saldo: la API solo compra desde $20.
account_blocked403La cuenta está bloqueada: escribe a soporte.
not_found404No hay pedido con ese id para esta clave.
no_numbers409No hay números para este par ahora; no se cobró nada.
price_above_max409El precio supera maxPrice; price trae el actual.
too_many_open_orders409Demasiados pedidos abiertos: termina o cancela algunos.
invalid_state409No es posible en este estado (p. ej. terminar sin código).
too_early_to_cancel409Se puede cancelar desde cancelableAt, 2 minutos tras la compra.
idempotency_in_progress409Una petición con este Idempotency-Key sigue en curso; repite en un momento.
idempotency_key_reused422Este Idempotency-Key ya se usó para otra petición.
rate_limited429Más de 20 peticiones por segundo; Retry-After indica cuándo repetir.
buying_too_fast429Más de 5 compras por segundo; usa /orders/batch.
try_later503No funcionó por ahora; inténtalo en un minuto.

Ejemplos REST

Comprar un número, esperar el código, terminar el pedido.

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 });
}

Ejemplos

El ciclo completo: comprar un número, esperar el código y terminar el pedido.

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));
}

Preguntas

Mi software usaba otro servicio de activaciones. ¿Qué cambio?

La dirección del servidor, a https://relysms.pro/stubs/handler_api.php; la clave, por la de tu cuenta. Los códigos de servicios y países no cambian.

¿Por qué NO_BALANCE si tengo saldo?

Las compras por API requieren $20 o más de saldo. La cuenta y la Mini App no tienen ese umbral.

¿Qué pasa con el dinero si no llega el código?

Vuelve solo a tu saldo cuando se cierra la ventana, o al momento si cancelas a los 2 minutos.

¿Puedo recibir un segundo código en el mismo número?

Sí, mientras la ventana esté abierta: setStatus=3 y luego getStatus otra vez.

¿Hay modo de pruebas?

No: todas las compras son reales. Empieza con una combinación barata y prueba tu flujo con un número.

Se filtró mi clave. ¿Qué hago?

Cuenta → Saldo → API → Emitir una nueva. La anterior deja de funcionar al instante.

Para asistentes de IA

La documentación completa en un solo texto para ChatGPT, Claude y otros modelos está en /es/developers.md, y un mapa breve en /llms.txt. Pásale el enlace al modelo y pídele que conecte RelySMS a tu código.

Lee https://relysms.pro/es/developers.md y conecta RelySMS a mi script.

developers.md · llms.txt