Para desenvolvedores
Referência da API
Leia o saldo e a tarifa vigente de qualquer serviço em qualquer país direto do seu próprio código. Uma chave, levada em um cabeçalho, e JSON como resposta.
Primeira requisição #
JSON sobre HTTPS do começo ao fim, autenticado por uma chave que você mesmo gera. Nada para instalar, nada para assinar, nenhum ambiente de testes a ser liberado — bastam uma chave e o curl.
- 1 Gere uma chave Menu da conta, depois chave de API, depois criar. Ela aparece uma única vez e só o hash dela é guardado, então depois não há onde consultá-la.
- 2 Apresente-a como token bearer Cada chamada leva um cabeçalho Authorization. Não existe uma segunda porta de entrada: nem parâmetro de consulta, nem cookie, nem sessão.
- 3 Leia a resposta Toda resposta é um objeto JSON com um campo ok. Quando ok é false, um campo error nomeia a causa com uma string estável, feita para o seu código.
Como apresentar a chave #
Uma chave por conta. Qualquer caminho que não seja o cabeçalho abaixo não é suportado, e isso é proposital: uma chave na query string acaba nos logs de acesso, no histórico do navegador e nos cabeçalhos de referência, então ela é recusada de saída em vez de ser aceita e vazada em silêncio.
Authorization: Bearer sk_your_key_here
Esta chave gasta dinheiro Hoje ela lê um saldo; a mesma chave fará pedidos assim que pedidos existirem. Trate-a como uma senha: nunca num repositório, nunca numa captura de tela, substituída em vez de repassada. Gerar uma substituta aposenta a anterior na hora.
Formatos e convenções #
| Endereço base | https://smsactivate.io/api/v1 |
|---|---|
| Transporte | Só por HTTPS: uma chamada em HTTP simples recebe um redirecionamento, e esse redirecionamento perde o seu cabeçalho Authorization. |
| Formato | JSON nos dois sentidos. O que volta é sempre um objeto — um array solto nunca é uma resposta válida. |
| Sucesso | HTTP 200, com "ok" em true. |
| Falha | Um status 4xx ou 5xx, "ok" em false e uma string "error" cuja grafia nunca muda. |
| Valores | Os valores são números em dólares americanos — nem strings, nem centavos: 0.84 são oitenta e quatro centavos. |
| Campos desconhecidos | Qualquer resposta pode ganhar campos com o tempo. Pule os que você não reconhecer em vez de tratá-los como erro. |
Quando algo falha #
Ramifique pela string error e por mais nada. A frase ao lado existe para você, não para o seu código, e pode ser reescrita a qualquer momento; a string não.
| Status | error | Causa |
|---|---|---|
| 401 | missing_key |
Nenhum cabeçalho Authorization chegou, ou o que chegou não era um token bearer. |
| 401 | bad_key |
A chave não é uma que conhecemos, ou já foi aposentada ou substituída. |
| 400 | unknown_service |
Nenhum serviço responde a esse código. Os códigos saem do catálogo, nunca do nome exibido na tela. |
| 404 | no_stock |
Não há nada livre para essa combinação de serviço e país neste momento. |
| 404 | unknown_country |
Nenhum país responde a esse código para este produto. Os catálogos não cobrem o mesmo terreno. |
| 400 | unknown_tech |
Essa geração de rede não é oferecida neste país. Só os Estados Unidos são vendidos por região. |
| 429 | rate_limited |
Chamadas demais. O cabeçalho Retry-After indica a espera, em segundos. |
Até onde dá para forçar #
600 chamadas por minuto, contadas por conta e não por endereço. Uma chave é feita para viver num único servidor — um único endereço — então contar por endereço puniria o uso normal e deixaria uma chave roubada livre para trabalhar de qualquer outro lugar. Passado o teto, você recebe um 429 com Retry-After em segundos.
Rotas #
Leituras de conta e de catálogo. Cada rota lista todos os parâmetros que aceita, todos os campos que devolve, e todas as formas como pode recusar.
O que a conta tem #
GET
/api/v1/balance
O crédito disponível agora, e quantas ativações isso cobre ao menor preço do catálogo.
O que volta
| Campo | Tipo | Significado |
|---|---|---|
ok |
boolean | Presente e true sempre que o status for 200. |
balance |
number | Os dólares do saldo, até o centavo. |
currency |
string | Fixo em "USD"; é enviado para que nada precise ser presumido. |
codes_at_cheapest |
integer | Quantos códigos o saldo cobriria ao menor preço do catálogo. Uma estimativa para dar noção de escala, não uma cotação; null quando o catálogo está vazio. |
cheapest_code |
number | Esse menor preço em si, caso você queira refazer a estimativa contra outro número. |
Chamada
curl -s "https://smsactivate.io/api/v1/balance" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Resposta
{
"ok": true,
"balance": 42.5,
"currency": "USD",
"codes_at_cheapest": 425,
"cheapest_code": 0.1
}
Como ela recusa missing_key bad_key rate_limited
Um serviço num país #
GET
/api/v1/pricing?service={service}&country={country}
Preço e contagem de linhas livres ao vivo para uma única combinação. Os dois oscilam: o preço acompanha a operadora mais barata que tem aquele serviço ali, e a contagem é o que a operadora informa naquele instante.
O que recebe
| Nome | Significado | |
|---|---|---|
service |
obrigatório | O código do serviço, telegram por exemplo — em minúsculas, como está escrito no catálogo. |
country |
pode ser omitido | O código do país, england por exemplo. Omita-o e todos os países voltam numa única chamada — veja abaixo. |
O que volta
| Campo | Tipo | Significado |
|---|---|---|
ok |
boolean | Presente e true sempre que o status for 200. |
service |
string | O código do serviço, devolvido sem alteração. |
country |
string | O código do país, devolvido sem alteração. |
price |
number | O preço em dólares de um código na operadora mais barata que o tenha. |
stock |
integer | A quantidade de números que as operadoras informam como livres agora — uma leitura ao vivo, que muda de minuto a minuto. |
Chamada
curl -s "https://smsactivate.io/api/v1/pricing?service=telegram&country=england" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Resposta
{
"ok": true,
"service": "telegram",
"country": "england",
"price": 0.84,
"stock": 61213
}
Como ela recusa missing_key bad_key unknown_service no_stock rate_limited
Um serviço, todos os países #
GET
/api/v1/pricing?service={service}
Omita o país e voltam todos os países que levam aquele serviço. A ordenação é a do próprio site — primeiro o que de fato entrega, e dentro disso o mais barato — e não o preço puro, que jogaria para o topo um número de dois centavos em que ninguém recebe nada.
O que recebe
| Nome | Significado | |
|---|---|---|
service |
obrigatório | O código do serviço, telegram por exemplo. |
O que volta
| Campo | Tipo | Significado |
|---|---|---|
ok |
boolean | Presente e true sempre que o status for 200. |
service |
string | O código do serviço que você enviou. |
name |
string | O nome exibido no site, "Telegram" por exemplo. |
countries |
array | Um objeto por país, na ordem explicada acima. |
countries[].country |
string | O código do país, pronto para passar à chamada do par. |
countries[].name |
string | O nome dele em inglês. |
countries[].price |
number | O preço em dólares de um código. |
countries[].stock |
integer | Números livres neste momento. |
Chamada
curl -s "https://smsactivate.io/api/v1/pricing?service=telegram" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Resposta
{
"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 }
]
}
Como ela recusa missing_key bad_key unknown_service rate_limited
Preços das sessões móveis #
GET
/api/v1/proxy-pricing?country={country}&tech={tech}
Sem país indicado você recebe os quatro onde mantemos modems, cada um com uma contagem de operadoras e um preço inicial. Indique um e você recebe todas as operadoras de lá com o custo de cada prazo. Os prazos vêm em dias: 1, 7, 30, 365.
O que recebe
| Nome | Significado | |
|---|---|---|
country |
pode ser omitido | O código do país, us por exemplo. Omita-o e, em vez disso, os países são listados. |
tech |
pode ser omitido | A geração, 4g ou 5g. Só os Estados Unidos oferecem as duas; em qualquer outro lugar o campo é desconsiderado e a única faixa disponível é devolvida. |
O que volta
| Campo | Tipo | Significado |
|---|---|---|
ok |
boolean | Presente e true sempre que o status for 200. |
country |
string | O código do país que você enviou. |
tech |
string | A geração a que o preço se aplica, depois de escolhido o padrão. |
techs |
array | Cada geração à venda naquele país. |
terms |
array | Os prazos oferecidos, em dias. |
carriers |
array | Um objeto por operadora. |
carriers[].carrier |
string | O código da operadora, para passar na hora do pedido. |
carriers[].name |
string | O nome de exibição da operadora, "T-Mobile" por exemplo. |
carriers[].prices |
object | O preço em dólares de cada prazo, indexado pela duração em dias. |
Chamada
curl -s "https://smsactivate.io/api/v1/proxy-pricing?country=us" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Resposta
{
"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 } }
]
}
Como ela recusa missing_key bad_key unknown_country unknown_tech rate_limited
Preços dos prazos #
GET
/api/v1/rental-pricing?country={country}&days={days}
Sem país indicado você recebe todos os países onde é possível manter um número, cada um com seu preço inicial. Indique um e você recebe todas as operadoras de lá e quanto custa nelas o prazo sobre o qual você perguntou.
O que recebe
| Nome | Significado | |
|---|---|---|
country |
pode ser omitido | O código do país, fr por exemplo. Omita-o e, em vez disso, os países são listados. |
days |
pode ser omitido | A duração em dias — 7, 14 ou 30. Qualquer outro valor é tratado como o prazo mais curto. |
O que volta
| Campo | Tipo | Significado |
|---|---|---|
ok |
boolean | Presente e true sempre que o status for 200. |
country |
string | O código do país que você enviou. |
days |
integer | O prazo a que o preço se aplica. |
terms |
array | Cada prazo à venda, em dias. |
operators |
array | Um objeto por operadora, o menor preço primeiro. |
operators[].operator |
string | O código da operadora, para passar na hora do pedido. |
operators[].name |
string | O nome exibido. |
operators[].type |
string | Um destes valores: physical, virtual ou premium. |
operators[].price |
number | O preço em dólares do prazo inteiro. |
Chamada
curl -s "https://smsactivate.io/api/v1/rental-pricing?country=fr&days=30" \
-H "Authorization: Bearer $SMSACTIVATE_KEY"
Resposta
{
"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 }
]
}
Como ela recusa missing_key bad_key unknown_country rate_limited
Exemplos completos #
Programas que funcionam do jeito que estão, e não fragmentos de uma linha só — incluindo as duas partes que mais confundem.
Shell #
Encontra o país mais barato para um serviço e confirma que o saldo dá.
#!/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 #
O mesmo em Node, tratando direito o formato do erro.
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 #
E em Python, repetindo a chamada diante de um 429 do mesmo jeito.
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")
O que ainda não está aqui #
Hoje a chave lê a conta e o catálogo. Fazer pedidos é o próximo passo, e vai responder no mesmo endereço base com a mesma chave — então nada do que você escrever contra estas rotas precisará ser desfeito quando chegar.
| Pedir um número | Ainda não Ainda não. Por enquanto, o pedido é feito no site. |
|---|---|
| Consultar o código em loop | Ainda não Previsto, junto com os pedidos. |
| Liberar um número | Ainda não Previsto, junto com os pedidos. |
| Aluguel pela API | Ainda não Previsto. |
| Webhooks | Ainda não Ainda não — chega junto com os eventos de pedido, quando houver algum a entregar. |
Esta página cresce junto: o que já está aqui fica onde está, e o que for novo aparece em Endpoints.
O que mudou #
- Primeira versão pública: chaves de API, GET /balance, GET /pricing.