API de activación SMS

Dos opciones: un endpoint compatible con el protocolo sms-activate, para que el software existente cambie modificando la URL y la clave, y una API REST JSON para nuevas integraciones. Ambas usan la misma clave API de tu panel.

Consigue tu clave API

Crea una cuenta, abre el panel y genera una clave en Acceso API. Mantenla en secreto: quien tenga la clave puede gastar tu saldo.

Registrarse

Flujo típico

  1. Llama a getNumber con un servicio y un país.
  2. Usa el número en la app de destino.
  3. Consulta getStatus cada pocos segundos hasta recibir STATUS_OK.
  4. Llama a setStatus con 6 para terminar, o con 8 para cancelar si no llegó ningún código.

Endpoint compatible con sms-activate

Envía peticiones GET o POST con los parámetros api_key y action. Las respuestas son texto plano, igual que en sms-activate.

https://smsrota.com/stubs/handler_api.php?api_key=KEY&action=getNumber&service=wa&country=187

Acciones

AcciónParámetrosRespuesta
getBalance—ACCESS_BALANCE:12.5000
getPricesservice?, country?{"187":{"wa":{"cost":0.4,"count":1563}}}
getNumberservice, country, maxPrice?ACCESS_NUMBER:48151623:15550123456
getStatusidSTATUS_WAIT_CODE · STATUS_WAIT_RETRY:code · STATUS_OK:code · STATUS_CANCEL
setStatusid, statusACCESS_RETRY_GET · ACCESS_ACTIVATION · ACCESS_CANCEL
getRentNumberservice, country, rent_time (4/24/72/168/720){"status":"success","phone":{"id":31,"endDate":"…","number":"447700900001"}}
getRentStatusid{"status":"success","quantity":"1","values":{"0":{"phoneFrom":"WhatsApp","text":"…"}}}
setRentStatusid, status (1 = finish, 2 = cancel){"status":"success"}
continueRentNumberid, rent_time{"status":"success","phone":{…}}

Valores de setStatus

3
Pedir otro código en el mismo número
6
Finalizar la activación
8
Cancelar y reembolsar (posible dos minutos después de comprar)

API REST JSON

Envía la clave en la cabecera Authorization como "Bearer KEY". Los importes son cadenas en dólares estadounidenses con cuatro decimales.

GET   https://smsrota.com/v1/balance
GET   https://smsrota.com/v1/prices?service=wa
POST  https://smsrota.com/v1/activations  {"service":"wa","country":"187"}
GET   https://smsrota.com/v1/activations/:id
POST  https://smsrota.com/v1/activations/:id/retry
POST  https://smsrota.com/v1/activations/:id/complete
POST  https://smsrota.com/v1/activations/:id/cancel
GET   https://smsrota.com/v1/rent/prices?service=wa&hours=24
POST  https://smsrota.com/v1/rentals  {"service":"full","country":"16","hours":24}
GET   https://smsrota.com/v1/rentals/:id
POST  https://smsrota.com/v1/rentals/:id/extend  {"hours":24}
POST  https://smsrota.com/v1/rentals/:id/finish
POST  https://smsrota.com/v1/rentals/:id/cancel
POST  https://smsrota.com/v1/rentals/:id/dispute  {"reason":"no_sms"}
PUT   https://smsrota.com/v1/webhook  {"url":"https://example.com/sms-webhook"}
POST  https://smsrota.com/v1/webhook/test
GET   https://smsrota.com/v1/webhook/events

Webhooks

Indica una URL en Acceso API de tu panel. Enviamos un POST con cuerpo JSON por cada evento. Responde con cualquier estado 2xx en 10 segundos; si no, lo reintentamos tras 1, 5, 30, 120, 360 y 720 minutos.

activation.sms_received
Llegó un código para un número que compraste.
activation.cancelled
Un número se canceló o caducó y el dinero volvió a tu saldo.
rental.sms_received
Llegó un SMS a un número alquilado.
rental.ended
Un alquiler terminó o se canceló.

Cuerpo de ejemplo

{
  "id": "evt_1042",
  "type": "activation.sms_received",
  "createdAt": "2026-11-01T10:00:00.000Z",
  "data": {
    "activationId": 48151623,
    "service": "wa",
    "country": "187",
    "phone": "15550123456",
    "code": "123456"
  }
}

Comprobar la firma

Cada petición lleva una cabecera X-Webhook-Signature como t=1730000000,v1=…, donde v1 es el HMAC-SHA256 en hexadecimal de "t.body" calculado con tu secreto de firma. Rechaza la petición si la firma no coincide o si t tiene más de 5 minutos.

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

// rawBody: the request body exactly as received, before JSON parsing.
function verify(rawBody, header, secret) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")));
  const expected = createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(t)) < 300;
  return fresh && v1.length === expected.length && timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

Errores

BAD_KEY
La clave API es incorrecta o fue sustituida.
NO_NUMBERS
Ahora mismo no hay stock para este servicio y país.
NO_BALANCE
Tu saldo no alcanza para este número.
EARLY_CANCEL_DENIED
Se puede cancelar dos minutos después de comprar.
NO_ACTIVATION
El id de activación no existe o no es tuyo.