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.
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 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 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 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.
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 #
| 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.
| 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
| 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
curl -s "https://smsactivate.io/api/v1/balance" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Respuesta
{
"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
| 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
| 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
curl -s "https://smsactivate.io/api/v1/pricing?service=telegram&country=england" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Respuesta
{
"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
| Nombre | Significado | |
|---|---|---|
service |
obligatorio | El código del servicio, telegram por ejemplo. |
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
curl -s "https://smsactivate.io/api/v1/pricing?service=telegram" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Respuesta
{
"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
| 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
| 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
curl -s "https://smsactivate.io/api/v1/proxy-pricing?country=us" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Respuesta
{
"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
| 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
| 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
curl -s "https://smsactivate.io/api/v1/rental-pricing?country=fr&days=30" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Respuesta
{
"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.
#!/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.
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.
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.