1 Elige una plataforma 1.304 servicios respondiendo

Selecciona un servicio

2 Elige un país 145 países

Selecciona un país

3 Operador y tarifa

Indica una plataforma y un país, en cualquier orden. Aquí aparecen el operador y la tarifa.

Para desarrolladores

Referencia de la API

Lee el saldo y el precio vigente de cualquier servicio en cualquier país desde tu propio código. Una clave en una cabecera, y JSON de vuelta.

Dirección base

https://smsactivate.io/api/v1
Generar una clave

Primera solicitud #

JSON sobre HTTPS de principio a fin, autenticado con una clave que generas tú. Nada que instalar, nada que firmar, ningún entorno de pruebas que haya que conceder: bastan una clave y curl.

  1. 1 Genera una clave Menú de la cuenta, luego clave API, luego crear. Aparece una sola vez y de ella solo se guarda la huella, así que después no hay dónde consultarla.
  2. 2 Preséntala como token bearer Cada llamada lleva una cabecera Authorization. No hay una segunda vía de entrada: ni parámetro de consulta, ni cookie, ni sesión.
  3. 3 Lee la respuesta Cada respuesta es un objeto JSON con un campo ok. Cuando ok vale false, un campo error nombra la causa con una cadena estable, pensada para tu código.

Cómo presentar la clave #

Una clave por cuenta. Cualquier vía que no sea la cabecera de abajo no está admitida, y es a propósito: una clave en la cadena de consulta acaba en los registros de acceso, en el historial del navegador y en las cabeceras de referencia, así que se rechaza de plano en lugar de aceptarla y filtrarla en silencio.

request
Authorization: Bearer sk_your_key_here

Esta clave gasta dinero Hoy lee un saldo; la misma clave hará pedidos en cuanto los pedidos existan. Trátala como una contraseña: nunca en un repositorio, nunca en una captura de pantalla, se sustituye en vez de circular. Generar una sustituta retira la anterior en el acto.

Formatos y convenciones #

Formatos y convenciones
Dirección base https://smsactivate.io/api/v1
Transporte Solo por HTTPS: una llamada por HTTP plano recibe una redirección, y esa redirección pierde tu cabecera Authorization.
Formato JSON en ambos sentidos. Lo que vuelve es siempre un objeto: un array suelto nunca es una respuesta válida.
Éxito HTTP 200, con "ok" en true.
Fallo Un estado 4xx o 5xx, "ok" en false y una cadena "error" cuya grafía no cambia nunca.
Importes Los importes son números en dólares estadounidenses: ni cadenas ni centavos. 0.84 son ochenta y cuatro centavos.
Campos desconocidos Cualquier respuesta puede ganar campos con el tiempo. Sáltate los que no reconozcas en lugar de tratarlos como error.

Cuando algo falla #

Ramifica según la cadena error y nada más. La frase que la acompaña existe para ti, no para tu código, y puede reescribirse en cualquier momento; la cadena no.

Cuando algo falla
Estado error Causa
401 missing_key No llegó ninguna cabecera Authorization, o lo que llegó no era un token bearer.
401 bad_key La clave no es una que conozcamos, o ya se retiró o se sustituyó.
400 unknown_service Ningún servicio responde a ese código. Los códigos salen del catálogo, nunca del nombre que aparece en pantalla.
404 no_stock En este momento no hay nada libre para esa combinación de servicio y país.
404 unknown_country Ningún país responde a ese código para este producto. Los catálogos no cubren el mismo terreno.
400 unknown_tech Esa generación de red no se ofrece en este país. Solo Estados Unidos se vende por ciudad.
429 rate_limited Demasiadas llamadas. La cabecera Retry-After indica la espera, en segundos.

Hasta dónde puedes apretar #

600 llamadas por minuto, contadas por cuenta y no por dirección. Una clave está pensada para vivir en un solo servidor — una sola dirección — así que contar por dirección penalizaría el uso normal y dejaría a una clave robada trabajando libremente desde cualquier otro sitio. Superado el tope, recibes un 429 con Retry-After en segundos.

Rutas #

Lecturas de la cuenta y del catálogo. Cada ruta nombra todos los parámetros que acepta, todos los campos que devuelve y todas las formas en que puede negarse.

Lo que hay en la cuenta #

GET /api/v1/balance

El crédito disponible ahora mismo, y cuántas activaciones cubre al precio más bajo que hay en el catálogo.

Qué devuelve

Lo que hay en la cuenta — Qué devuelve
Clave Tipo Significado
ok boolean Presente y true siempre que el estado sea 200.
balance number Los dólares del saldo, al centavo.
currency string Fijo en "USD"; se envía para que no haya que suponer nada.
codes_at_cheapest integer Cuántos códigos cubriría el saldo al precio más bajo del catálogo. Una estimación para hacerse una idea de la escala, no una cotización; null cuando el catálogo está vacío.
cheapest_code number Ese precio más bajo en sí, por si quieres recalcular la estimación contra otra cifra.

Llamada

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

Respuesta

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

Formas de negarse missing_key bad_key rate_limited

Un servicio en un país #

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

Precio y líneas libres en vivo para una sola combinación. Ambos se mueven: el precio sigue al operador más barato que tenga ese servicio allí, y el recuento es lo que el operador declara en ese instante.

Qué acepta

Un servicio en un país — Qué acepta
Nombre Significado
service obligatorio El código del servicio, telegram por ejemplo: en minúsculas, tal como está escrito en el catálogo.
country se puede omitir El código del país, england por ejemplo. Omítelo y vuelven todos los países en una sola llamada; véase más abajo.

Qué devuelve

Un servicio en un país — Qué devuelve
Clave Tipo Significado
ok boolean Presente y true siempre que el estado sea 200.
service string El código del servicio, devuelto sin cambios.
country string El código del país, devuelto sin cambios.
price number El precio en dólares de un código en el operador más barato que lo tenga.
stock integer El número de líneas que los operadores declaran libres ahora mismo: una lectura en vivo que cambia de un minuto a otro.

Llamada

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

Respuesta

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

Formas de negarse missing_key bad_key unknown_service no_stock rate_limited

Un servicio, todos los países #

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

Omite el país y vuelven todos los países que llevan ese servicio. El orden es el del propio sitio — primero lo que de verdad entrega, y dentro de eso lo más barato — y no el precio bruto, que subiría al primer puesto una línea de dos centavos en la que nadie recibe nunca nada.

Qué acepta

Un servicio, todos los países — Qué acepta
Nombre Significado
service obligatorio El código del servicio, telegram por ejemplo.

Qué devuelve

Un servicio, todos los países — Qué devuelve
Clave Tipo Significado
ok boolean Presente y true siempre que el estado sea 200.
service string El código del servicio que enviaste.
name string El nombre que se muestra en el sitio, "Telegram" por ejemplo.
countries array Un objeto por país, en el orden explicado más arriba.
countries[].country string El código del país, listo para pasarlo a la llamada del par.
countries[].name string Su nombre en inglés.
countries[].price number El precio en dólares de un código.
countries[].stock integer Líneas libres en este momento.

Llamada

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

Respuesta

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

Formas de negarse missing_key bad_key unknown_service rate_limited

Precios de las sesiones móviles #

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

Sin país indicado obtienes los cuatro donde tenemos módems, cada uno con un recuento de operadores y un precio de entrada. Indica uno y obtienes todos los operadores de allí con el coste de cada plazo. Los plazos van en días: 1, 7, 30, 365.

Qué acepta

Precios de las sesiones móviles — Qué acepta
Nombre Significado
country se puede omitir El código del país, us por ejemplo. Omítelo y en su lugar se listan los países.
tech se puede omitir La generación, 4g o 5g. Solo Estados Unidos ofrece ambas; en cualquier otro sitio el campo se ignora y se devuelve el único rango disponible.

Qué devuelve

Precios de las sesiones móviles — Qué devuelve
Clave Tipo Significado
ok boolean Presente y true siempre que el estado sea 200.
country string El código del país que enviaste.
tech string La generación a la que se aplica el precio, una vez elegido el valor por defecto.
techs array Cada generación a la venta en ese país.
terms array Los plazos que se ofrecen, en días.
carriers array Un objeto por operador.
carriers[].carrier string El código del operador, para pasarlo al hacer el pedido.
carriers[].name string El nombre visible del operador, "T-Mobile" por ejemplo.
carriers[].prices object El precio en dólares de cada plazo, indexado por su duración en días.

Llamada

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

Respuesta

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

Formas de negarse missing_key bad_key unknown_country unknown_tech rate_limited

Precios de los plazos #

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

Sin país indicado obtienes todos los países donde se puede reservar una línea, cada uno con su precio de entrada. Indica uno y obtienes todos los operadores de allí y lo que cuesta en cada uno el plazo por el que has preguntado.

Qué acepta

Precios de los plazos — Qué acepta
Nombre Significado
country se puede omitir El código del país, fr por ejemplo. Omítelo y en su lugar se listan los países.
days se puede omitir La duración en días: 7, 14 o 30. Cualquier otro valor se trata como el plazo más corto.

Qué devuelve

Precios de los plazos — Qué devuelve
Clave Tipo Significado
ok boolean Presente y true siempre que el estado sea 200.
country string El código del país que enviaste.
days integer El plazo al que se aplica el precio.
terms array Cada plazo a la venta, en días.
operators array Un objeto por operador, el precio más bajo primero.
operators[].operator string El código del operador, para pasarlo al hacer el pedido.
operators[].name string Su nombre visible.
operators[].type string Uno de estos valores: physical, virtual o premium.
operators[].price number El precio en dólares del plazo completo.

Llamada

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

Respuesta

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

Formas de negarse missing_key bad_key unknown_country rate_limited

Ejemplos completos #

Programas que funcionan tal cual en lugar de fragmentos de una línea, con las dos partes que hacen tropezar a la gente incluidas.

Shell #

Localiza el país más barato para un servicio y confirma que el saldo alcanza.

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 #

Lo mismo en Node, tratando bien la forma del error.

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 #

Y en Python, reintentando ante un 429 de la misma manera.

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

Lo que todavía no está aquí #

Hoy la clave lee la cuenta y el catálogo. Hacer pedidos es lo siguiente, y responderá en la misma dirección base con la misma clave, así que nada de lo escrito contra estas rutas habrá que deshacerlo cuando llegue.

Pedir un número Todavía no Todavía no. Por ahora, el pedido se hace en el sitio.
Consultar el código en bucle Todavía no Previsto, junto con los pedidos.
Liberar un número Todavía no Previsto, junto con los pedidos.
Alquiler por API Todavía no Previsto.
Webhooks Todavía no Todavía no: llegará junto con los eventos de pedido, cuando haya alguno que entregar.

Esta página crece con ellos: lo que ya está se queda donde está, y lo nuevo aparece bajo Endpoints.

Qué cambió #

  • Primera versión pública: claves de API, GET /balance, GET /pricing.