KDEFY SMS API
API REST para comprar números virtuais e receber SMS. Usa o mesmo saldo e as mesmas ativações da sua conta no site.
https://kdefy-sms.com/api/v1X-API-KeyTodas as rotas
| GET | /balance | Saldo e totais da conta. |
| GET | /profile | Usuário, saldo e data de criação. |
| GET | /countries | Lista de países. |
| GET | /services | Serviços de um país, com estoque e preço inicial. |
| GET | /operators | Operadoras de um país. |
| GET | /offers | Faixas de preço e estoque de um serviço num país. |
| GET POST | /number/get | Compra um número, ou vários com quantity. |
| GET | /number/status | Estado da ativação e códigos recebidos. |
| GET POST | /number/cancel | Cancela e devolve o valor. |
| GET POST | /number/finish | Encerra a ativação depois do código. |
| GET | /activations | Suas ativações, inclusive as do site, da mais nova para a mais antiga. |
| GET | /transactions | Recargas, compras e reembolsos. |
Integrar com IA
Cole o texto abaixo no ChatGPT, Claude ou Gemini e diga o que quer montar. O prompt já traz rotas, regras e erros da API.
# TAREFA
Escreva o código de integração com a KDEFY SMS API: compra de números virtuais e leitura de SMS.
Use só o que está neste documento. Se faltar informação, pergunte. Não invente rota, campo ou código de erro.
# ANTES DE CODAR
Faça as perguntas abaixo numa única mensagem e espere a resposta. Pule o que eu já tiver dito.
1. Linguagem e framework (com versão).
2. O que o código faz (cadastro automático, revenda, painel...).
3. Onde roda e onde fica o token.
4. Volume esperado (números por minuto) e se precisa de compra em lote.
# COMO RESPONDER
1. Plano em até 3 linhas.
2. Código completo e executável.
3. Como rodar e testar.
4. Limites e riscos que o código trata.
# API
Base URL: https://kdefy-sms.com/api/v1
Auth: header X-API-Key: <TOKEN> em toda requisição. O token vem de variável de ambiente (KDEFY_API_KEY). Nunca no front-end, nunca em log.
Métodos: tudo é GET. /number/get, /number/cancel e /number/finish também aceitam POST.
Resposta: JSON. Sucesso { "status": "success", ... }. Erro { "status": "error", "error": "codigo", "message": "texto" }.
Decida sempre por "error". "message" muda com o idioma.
Limites: 120 requisições por minuto por conta. Compra: até 50 números por requisição e 50 por minuto. Acima disso: limite_de_numeros.
# ROTAS (* = obrigatório)
GET /balance
Saldo e totais da conta.
params: nenhum
retorna: balance_brl, total_spent_brl, total_recharged_brl, currency
GET /profile
Usuário, saldo e data de criação.
params: nenhum
retorna: username, balance_brl, created_at
GET /countries
Lista de países.
params: nenhum
retorna: countries[].id, countries[].name, countries[].dial_code
GET /services
Serviços de um país, com estoque e preço inicial.
params: country*
retorna: country, services[].code, services[].name, services[].available, services[].from_price_brl
erros: pais_invalido
GET /operators
Operadoras de um país.
params: country*
retorna: country, operators[].id, operators[].name
erros: pais_invalido
GET /offers
Faixas de preço e estoque de um serviço num país.
params: country*, service*
retorna: offers[].price_brl, offers[].available
erros: pais_invalido, servico_invalido, sem_numeros_disponiveis
GET|POST /number/get
Compra um número, ou vários com quantity.
params: country*, service*, max_price_brl, operator, quantity, request_id
retorna: id, service, service_name, country, country_name, phone, state, state_label, code, codes, price_brl, seconds_left, cancel_in_seconds, balance_brl, requested, purchased, failed, numbers, errors
erros: pais_invalido, servico_invalido, quantidade_invalida, preco_invalido, operador_invalido, request_id_invalido, request_id_reutilizada, requisicao_em_andamento, saldo_insuficiente, sem_numeros_disponiveis, preco_abaixo_do_minimo, limite_de_numeros, falha_temporaria
GET /number/status
Estado da ativação e códigos recebidos.
params: id*
retorna: id, service, service_name, country, country_name, phone, state, state_label, code, codes, price_brl, seconds_left, cancel_in_seconds
erros: id_invalido, ativacao_nao_encontrada
GET|POST /number/cancel
Cancela e devolve o valor.
params: id*
retorna: id, state, refunded_brl, balance_brl
erros: id_invalido, ativacao_nao_encontrada, ativacao_nao_cancelavel, cancelamento_muito_cedo, falha_temporaria
GET|POST /number/finish
Encerra a ativação depois do código.
params: id*
retorna: id, state
erros: id_invalido, ativacao_nao_encontrada, ativacao_nao_finalizavel
GET /activations
Suas ativações, inclusive as do site, da mais nova para a mais antiga.
params: state, limit
retorna: activations[]
GET /transactions
Recargas, compras e reembolsos.
params: limit
retorna: transactions[].type, transactions[].amount_brl, transactions[].balance_after_brl, transactions[].description, transactions[].created_at
Exemplo, /number/get:
{
"id": "1842",
"service": "wa",
"service_name": "WhatsApp",
"country": 73,
"country_name": "Brasil",
"phone": "5511999999999",
"state": "waiting",
"state_label": "Aguardando código",
"code": null,
"codes": [],
"price_brl": 8.4,
"seconds_left": 1200,
"cancel_in_seconds": 120,
"status": "success",
"balance_brl": 17
}
Exemplo, /number/status com código:
{
"status": "success",
"id": "1842",
"service": "wa",
"service_name": "WhatsApp",
"country": 73,
"country_name": "Brasil",
"phone": "5511999999999",
"state": "code_received",
"state_label": "Código recebido",
"code": "123456",
"codes": [
{
"code": "123456",
"received_at": "2026-10-19T14:02:11.000Z"
}
],
"price_brl": 8.4,
"seconds_left": 1103,
"cancel_in_seconds": 0
}
# ESTADOS (campo state)
waiting: Esperando o primeiro código.
code_received: Código recebido. Códigos novos entram em codes enquanto a ativação estiver aberta.
completed: Finalizada por você (/number/finish).
cancelled: Cancelada. Valor devolvido.
expired: Sem código em 20 min. Valor devolvido automaticamente.
waiting → code_received → completed
waiting → cancelled (cancel, só sem código e após 2 min)
waiting → expired (automático, com reembolso)
# ERROS E O QUE FAZER
401 token_nao_informado / token_invalido
→ Corrija o token. Não repita.
403 conta_bloqueada / token_suspenso
→ Fale com o suporte.
400 pais_invalido / servico_invalido / id_invalido / quantidade_invalida / preco_invalido / operador_invalido / request_id_invalido
→ Corrija a chamada.
402 saldo_insuficiente
→ Recarregue no site.
404 sem_numeros_disponiveis / oferta_indisponivel
→ Suba max_price_brl, troque o país ou tente depois.
404 ativacao_nao_encontrada
→ Confira o id.
409 requisicao_em_andamento
→ Espere e repita a mesma chamada.
409 cancelamento_muito_cedo
→ Espere retry_in_seconds.
409 ativacao_nao_cancelavel / ativacao_nao_finalizavel
→ Consulte /number/status.
422 request_id_reutilizada
→ Use uma request_id nova.
422 preco_abaixo_do_minimo
→ Suba para min_price_brl ou mais.
429 limite_de_requisicoes / limite_de_numeros
→ Espere retry_in_seconds.
502 falha_temporaria
→ Repita com espera crescente, mesma request_id.
# REGRAS DO CÓDIGO
1. Compra nova = request_id nova (UUID). Repetição da mesma compra = mesma request_id. Nunca gere request_id nova para repetir.
2. Repita a compra só em timeout, erro de rede, 502 ou requisicao_em_andamento. Máximo 4 tentativas, esperando 2 s, 4 s, 6 s.
3. saldo_insuficiente e sem_numeros_disponiveis não se repetem. Devolva o erro a quem chamou.
4. Espere o código com /number/status a cada 5 s, com prazo máximo de 20 min. Pare em code preenchido ou state cancelled, expired ou completed.
5. Vários números ao mesmo tempo: uma chamada a /activations?state=active por ciclo, não uma por número.
6. Com código usado: /number/finish. Sem código e desistindo: /number/cancel. Se vier cancelamento_muito_cedo, espere retry_in_seconds e tente de novo. Se vier ativacao_nao_cancelavel, já chegou código: consulte /number/status.
7. Lote (quantity): leia purchased e failed. Compra parcial é normal.
8. 429: espere retry_in_seconds.
9. Timeout de rede de 20 s por chamada.
10. Log com request_id e id da ativação. Nunca com o token.
# EXEMPLO DE REFERÊNCIA (JavaScript)
```js
// Node 18+. Rode com: KDEFY_API_KEY=seu_token node kdefy.mjs
import { randomUUID } from "node:crypto";
const BASE = "https://kdefy-sms.com/api/v1";
const KEY = process.env.KDEFY_API_KEY;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function api(path, params = {}) {
const qs = new URLSearchParams(params).toString();
const res = await fetch(`${BASE}${path}${qs ? "?" + qs : ""}`, {
headers: { "X-API-Key": KEY },
signal: AbortSignal.timeout(20000),
});
const body = await res.json();
if (body.status !== "success") {
const err = new Error(body.message);
err.code = body.error;
err.http = res.status;
err.retryIn = body.retry_in_seconds;
throw err;
}
return body;
}
async function buy(country, service) {
const requestId = randomUUID(); // uma por compra
for (let attempt = 1; attempt <= 4; attempt++) {
try {
return await api("/number/get", { country, service, request_id: requestId });
} catch (e) {
const transient = e.name === "TimeoutError" || e.name === "TypeError" || e.http === 502 || e.code === "requisicao_em_andamento";
if (!transient || attempt === 4) throw e;
await sleep(2000 * attempt); // repete com a mesma request_id
}
}
}
async function waitForCode(id, maxMinutes = 20) {
const deadline = Date.now() + maxMinutes * 60_000;
while (Date.now() < deadline) {
const s = await api("/number/status", { id });
if (s.code || ["cancelled", "expired", "completed"].includes(s.state)) return s;
await sleep(5000);
}
return null;
}
const number = await buy(73, "wa");
console.log("Número:", number.phone);
const result = await waitForCode(number.id);
if (result?.code) {
console.log("Código:", result.code);
await api("/number/finish", { id: number.id });
} else {
try {
await api("/number/cancel", { id: number.id });
} catch (e) {
if (e.code !== "cancelamento_muito_cedo") throw e;
await sleep((e.retryIn + 1) * 1000);
await api("/number/cancel", { id: number.id });
}
console.log("Cancelado e reembolsado.");
}
```
# CHECKLIST ANTES DE ENTREGAR
- Token só de variável de ambiente.
- Toda compra tem request_id, e a repetição reaproveita a mesma.
- Polling de 5 s com prazo máximo.
- Decisões por "error", nunca por "message".
- Cancelamento trata cancelamento_muito_cedo.
- Testes ou passos de teste para: compra ok, repetição com a mesma request_id, saldo_insuficiente, cancelar antes de 2 min.
# MAIS DETALHES
Docs completas em texto: https://kdefy-sms.com/api/v1/docs.txt
Docs completas em JSON: https://kdefy-sms.com/api/v1/docs.json
OpenAPI 3: https://kdefy-sms.com/api/v1/openapi.json
Console de teste
Gerar ou ver meu token →Estes valores valem para todos os testes da página. O token fica só nesta aba. Comprar debita saldo de verdade.
Autenticação
Gere o token em API, no menu do site, e mande no header X-API-Key em toda requisição. Authorization: Bearer e ?api_key= também funcionam, mas a query string vai parar em logs de proxy e no histórico do navegador. Gerar outro token invalida o anterior na hora. Não use o token em front-end.
curl "https://kdefy-sms.com/api/v1/balance" -H "X-API-Key: SEU_TOKEN"curl "https://kdefy-sms.com/api/v1/balance" -H "Authorization: Bearer SEU_TOKEN"curl "https://kdefy-sms.com/api/v1/balance?api_key=SEU_TOKEN"
Respostas e idioma
- Toda resposta é JSON. Sucesso: { "status": "success", ... }. Erro: { "status": "error", "error": "codigo", "message": "texto" }.
- Decida pelo campo error. Ele é estável. message é texto para humano e pode mudar.
- message e state_label seguem o idioma da conta (pt ou en). Para forçar: ?lang=pt ou ?lang=en.
- As chaves do JSON e os valores de state não mudam com o idioma.
- Valores em BRL com ponto decimal. Datas em ISO 8601 (UTC).
Estados
| state | Significado |
|---|---|
waiting | Esperando o primeiro código. |
code_received | Código recebido. Códigos novos entram em codes enquanto a ativação estiver aberta. |
completed | Finalizada por você (/number/finish). |
cancelled | Cancelada. Valor devolvido. |
expired | Sem código em 20 min. Valor devolvido automaticamente. |
Limites
- 120 requisições por minuto por conta.
- Compra: até 50 números por requisição e 50 por minuto. Acima disso: limite_de_numeros.
- Status: consulte a cada 5 s. Mais rápido não antecipa o código.
Fluxo de compra
- GET /services?country=73: serviços do país e preço inicial.
- GET /offers?country=73&service=wa (opcional): faixas de preço e estoque.
- GET /number/get?country=73&service=wa&request_id=...: compra e devolve phone e id.
- GET /number/status?id=ID a cada 5 s, até code vir preenchido.
- Com código: GET /number/finish?id=ID. Sem código: GET /number/cancel?id=ID (libera 2 min após a compra) e o valor volta ao saldo.
Esperando o código
Consulte /number/status a cada 5 s e pare quando code vier preenchido ou state virar cancelled, expired ou completed.
- Defina um prazo máximo no seu código (20 min).
- Com vários números, use /activations?state=active. Uma chamada traz todas as ativas.
- Uma ativação pode receber mais de um código. Leia codes[].
Compra em lote
quantity=N compra N números numa chamada, até 50. Compra parcial é normal: se o estoque ou o saldo acabar no meio, o resto não é cobrado.
- A resposta traz numbers[], requested, purchased e failed.
- errors lista o motivo das falhas, quando houver.
- Limite de 50 números por minuto por conta.
curl "https://kdefy-sms.com/api/v1/number/get?country=73&service=wa&quantity=3&request_id=pedido-0001" \
-H "X-API-Key: $KDEFY_API_KEY"
Idempotência (request_id)
Mande request_id em toda compra. Se der timeout e você não sabe se a compra saiu, repita a mesma chamada com a mesma request_id. A API devolve a resposta original, com o header Idempotent-Replay: true, e não cobra de novo.
- Compra nova, request_id nova.
- 8 a 80 caracteres (letras, números, _ . : -). O header Idempotency-Key também vale.
- A chave dura 24 h e só é salva quando a compra deu certo. Compra que falhou pode ser repetida.
- Mesma chave com parâmetros diferentes: request_id_reutilizada.
Exemplo completo
Compra, espera o código e finaliza. Se o código não chega, cancela. A compra usa request_id, então repetir a chamada não duplica.
// Node 18+. Rode com: KDEFY_API_KEY=seu_token node kdefy.mjs
import { randomUUID } from "node:crypto";
const BASE = "https://kdefy-sms.com/api/v1";
const KEY = process.env.KDEFY_API_KEY;
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
async function api(path, params = {}) {
const qs = new URLSearchParams(params).toString();
const res = await fetch(`${BASE}${path}${qs ? "?" + qs : ""}`, {
headers: { "X-API-Key": KEY },
signal: AbortSignal.timeout(20000),
});
const body = await res.json();
if (body.status !== "success") {
const err = new Error(body.message);
err.code = body.error;
err.http = res.status;
err.retryIn = body.retry_in_seconds;
throw err;
}
return body;
}
async function buy(country, service) {
const requestId = randomUUID(); // uma por compra
for (let attempt = 1; attempt <= 4; attempt++) {
try {
return await api("/number/get", { country, service, request_id: requestId });
} catch (e) {
const transient = e.name === "TimeoutError" || e.name === "TypeError" || e.http === 502 || e.code === "requisicao_em_andamento";
if (!transient || attempt === 4) throw e;
await sleep(2000 * attempt); // repete com a mesma request_id
}
}
}
async function waitForCode(id, maxMinutes = 20) {
const deadline = Date.now() + maxMinutes * 60_000;
while (Date.now() < deadline) {
const s = await api("/number/status", { id });
if (s.code || ["cancelled", "expired", "completed"].includes(s.state)) return s;
await sleep(5000);
}
return null;
}
const number = await buy(73, "wa");
console.log("Número:", number.phone);
const result = await waitForCode(number.id);
if (result?.code) {
console.log("Código:", result.code);
await api("/number/finish", { id: number.id });
} else {
try {
await api("/number/cancel", { id: number.id });
} catch (e) {
if (e.code !== "cancelamento_muito_cedo") throw e;
await sleep((e.retryIn + 1) * 1000);
await api("/number/cancel", { id: number.id });
}
console.log("Cancelado e reembolsado.");
}# Python 3.9+. pip install requests
# Rode com: KDEFY_API_KEY=seu_token python kdefy.py
import os, time, uuid, requests
BASE = "https://kdefy-sms.com/api/v1"
HEADERS = {"X-API-Key": os.environ["KDEFY_API_KEY"]}
class ApiError(Exception):
def __init__(self, body, http):
super().__init__(body.get("message"))
self.code = body.get("error")
self.http = http
self.retry_in = body.get("retry_in_seconds")
def api(path, **params):
r = requests.get(BASE + path, params=params, headers=HEADERS, timeout=20)
body = r.json()
if body.get("status") != "success":
raise ApiError(body, r.status_code)
return body
def buy(country, service):
request_id = str(uuid.uuid4()) # uma por compra
for attempt in range(1, 5):
try:
return api("/number/get", country=country, service=service, request_id=request_id)
except requests.RequestException:
pass
except ApiError as e:
if not (e.http == 502 or e.code == "requisicao_em_andamento"):
raise
if attempt == 4:
raise RuntimeError("não foi possível comprar agora")
time.sleep(2 * attempt) # repete com a mesma request_id
def wait_for_code(activation_id, max_minutes=20):
deadline = time.time() + max_minutes * 60
while time.time() < deadline:
s = api("/number/status", id=activation_id)
if s["code"] or s["state"] in ("cancelled", "expired", "completed"):
return s
time.sleep(5)
return None
number = buy(73, "wa")
print("Número:", number["phone"])
result = wait_for_code(number["id"])
if result and result["code"]:
print("Código:", result["code"])
api("/number/finish", id=number["id"])
else:
try:
api("/number/cancel", id=number["id"])
except ApiError as e:
if e.code != "cancelamento_muito_cedo":
raise
time.sleep((e.retry_in or 5) + 1)
api("/number/cancel", id=number["id"])
print("Cancelado e reembolsado.")<?php
// PHP 8+ com ext-curl. Rode com: KDEFY_API_KEY=seu_token php kdefy.php
const BASE = "https://kdefy-sms.com/api/v1";
function api(string $path, array $params = []): array {
$ch = curl_init(BASE . $path . ($params ? "?" . http_build_query($params) : ""));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$raw = curl_exec($ch);
if ($raw === false) throw new RuntimeException("rede: " . curl_error($ch));
$body = json_decode($raw, true);
if (($body["status"] ?? null) !== "success") {
$e = new RuntimeException($body["error"] ?? "erro_desconhecido");
$e->retryIn = $body["retry_in_seconds"] ?? 0;
throw $e;
}
return $body;
}
$requestId = bin2hex(random_bytes(16)); // uma por compra
$n = api("/number/get", ["country" => 73, "service" => "wa", "request_id" => $requestId]);
echo "Número: {$n['phone']}\n";
$deadline = time() + 20 * 60;
while (time() < $deadline) {
$s = api("/number/status", ["id" => $n["id"]]);
if (!empty($s["code"]) || in_array($s["state"], ["cancelled", "expired", "completed"], true)) break;
sleep(5);
}
if (!empty($s["code"])) {
echo "Código: {$s['code']}\n";
api("/number/finish", ["id" => $n["id"]]);
} else {
api("/number/cancel", ["id" => $n["id"]]);
echo "Cancelado e reembolsado.\n";
}# Ruby 3+. Rode com: KDEFY_API_KEY=seu_token ruby kdefy.rb
require "net/http"
require "json"
require "securerandom"
BASE = "https://kdefy-sms.com/api/v1"
def api(path, params = {})
uri = URI(BASE + path)
uri.query = URI.encode_www_form(params) unless params.empty?
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |h| h.request(req) }
body = JSON.parse(res.body)
raise "#{body['error']}: #{body['message']}" unless body["status"] == "success"
body
end
n = api("/number/get", country: 73, service: "wa", request_id: SecureRandom.uuid) # uma por compra
puts "Número: #{n['phone']}"
deadline = Time.now + 20 * 60
s = nil
while Time.now < deadline
s = api("/number/status", id: n["id"])
break if s["code"] || %w[cancelled expired completed].include?(s["state"])
sleep 5
end
if s && s["code"]
puts "Código: #{s['code']}"
api("/number/finish", id: n["id"])
else
api("/number/cancel", id: n["id"])
puts "Cancelado e reembolsado."
end#!/usr/bin/env bash
# Requer curl e jq. Rode com: KDEFY_API_KEY=seu_token bash kdefy.sh
set -euo pipefail
BASE="https://kdefy-sms.com/api/v1"
api() { # api /rota chave=valor ...
local path="$1"; shift
local args=(); for kv in "$@"; do args+=(--data-urlencode "$kv"); done
curl -sS --max-time 20 -G "$BASE$path" -H "X-API-Key: $KDEFY_API_KEY" "${args[@]}"
}
num=$(api /number/get country=73 service=wa "request_id=$(uuidgen)") # uma por compra
[ "$(jq -r .status <<<"$num")" = success ] || { jq . <<<"$num"; exit 1; }
id=$(jq -r .id <<<"$num")
echo "Número: $(jq -r .phone <<<"$num")"
for _ in $(seq 240); do # 240 x 5 s = 20 min
st=$(api /number/status "id=$id")
code=$(jq -r '.code // empty' <<<"$st")
state=$(jq -r .state <<<"$st")
[ -n "$code" ] && break
case "$state" in cancelled|expired|completed) break ;; esac
sleep 5
done
if [ -n "${code:-}" ]; then
echo "Código: $code"
api /number/finish "id=$id" >/dev/null
else
api /number/cancel "id=$id" >/dev/null
echo "Cancelado e reembolsado."
fiBoas práticas
- Token em variável de ambiente. Nunca no código, no front-end ou em repositório.
- request_id em toda compra. Repetiu a chamada? Mesma request_id.
- Polling de 5 s, com prazo máximo.
- Vários números: /activations?state=active em vez de um /number/status por ativação.
- Trate error, não message.
- 429: espere retry_in_seconds. 502: tente de novo com espera crescente (2 s, 4 s, 6 s).
- Use max_price_brl como teto. Preço e estoque mudam, então consulte /offers antes de lotes grandes.
- Confira /balance antes de lotes grandes.
- Guarde request_id e id da ativação nos logs.
- Cancele só o que não vai usar. Depois do primeiro código não há reembolso.
Conta
/api/v1/balance
Saldo
Saldo e totais da conta.
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
balance_brl | number | Saldo disponível. |
total_spent_brl | number | Total gasto na conta. |
total_recharged_brl | number | Total recarregado. |
currency | string | Sempre "BRL". |
Exemplo
curl "https://kdefy-sms.com/api/v1/balance" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/balance", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/balance",
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/balance");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/balance")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/balance" \
-H "X-API-Key: $KDEFY_API_KEY" | jq .Resposta
{
"status": "success",
"balance_brl": 25.4,
"total_spent_brl": 12.1,
"total_recharged_brl": 37.5,
"currency": "BRL"
}
Testar
/api/v1/profile
Perfil
Usuário, saldo e data de criação.
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
username | string | Usuário. |
balance_brl | number | Saldo disponível. |
created_at | string | Criação da conta (ISO 8601). |
Exemplo
curl "https://kdefy-sms.com/api/v1/profile" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/profile", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/profile",
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/profile");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/profile")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/profile" \
-H "X-API-Key: $KDEFY_API_KEY" | jq .Resposta
{
"status": "success",
"username": "maria",
"balance_brl": 25.4,
"created_at": "2026-09-01T12:00:00.000Z"
}
Testar
Catálogo
/api/v1/countries
Países
Lista de países. Use o id em country.
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
countries[].id | integer | ID do país. Use em country. |
countries[].name | string | Nome. |
countries[].dial_code | string | null | DDI, ex.: +55. |
Exemplo
curl "https://kdefy-sms.com/api/v1/countries" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/countries", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/countries",
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/countries");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/countries")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/countries" \
-H "X-API-Key: $KDEFY_API_KEY" | jq .Resposta
{
"status": "success",
"countries": [
{
"id": 73,
"name": "Brasil",
"dial_code": "+55"
}
]
}
Testar
/api/v1/services
Serviços
Serviços de um país, com estoque e preço inicial. Use code em service.
Parâmetros
| Nome | Descrição | |
|---|---|---|
country | obrigatório | ID do país. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
country | integer | País consultado. |
services[].code | string | Código. Use em service. |
services[].name | string | Nome. |
services[].available | integer | Estoque. |
services[].from_price_brl | number | null | Preço da oferta mais barata. |
Erros
Exemplo
curl "https://kdefy-sms.com/api/v1/services?country=73" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/services?country=73", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/services",
params={"country": 73},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/services?country=73");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/services?country=73")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/services" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "country=73" | jq .Resposta
{
"status": "success",
"country": 73,
"services": [
{
"code": "wa",
"name": "WhatsApp",
"available": 1240,
"from_price_brl": 7.1
}
]
}
Testar
/api/v1/operators
Operadoras
Operadoras de um país. Uso opcional em operator na compra.
Parâmetros
| Nome | Descrição | |
|---|---|---|
country | obrigatório | ID do país. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
country | integer | País consultado. |
operators[].id | string | ID da operadora. Use em operator. |
operators[].name | string | Nome. |
Erros
Exemplo
curl "https://kdefy-sms.com/api/v1/operators?country=73" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/operators?country=73", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/operators",
params={"country": 73},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/operators?country=73");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/operators?country=73")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/operators" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "country=73" | jq .Resposta
{
"status": "success",
"country": 73,
"operators": [
{
"id": "vivo",
"name": "vivo"
}
]
}
Testar
/api/v1/offers
Ofertas
Faixas de preço e estoque de um serviço num país. Faixas baratas têm pouco estoque; as mais caras tendem a ter número.
Parâmetros
| Nome | Descrição | |
|---|---|---|
country | obrigatório | ID do país. |
service | obrigatório | Código do serviço. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
offers[].price_brl | number | Preço da faixa. |
offers[].available | integer | Estoque da faixa. |
Erros
Exemplo
curl "https://kdefy-sms.com/api/v1/offers?country=73&service=wa" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/offers?country=73&service=wa", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/offers",
params={"country": 73, "service": "wa"},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/offers?country=73&service=wa");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/offers?country=73&service=wa")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/offers" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "country=73" \
--data-urlencode "service=wa" | jq .Resposta
{
"status": "success",
"country": 73,
"service": "wa",
"offers": [
{
"price_brl": 7.1,
"available": 12
},
{
"price_brl": 8.4,
"available": 340
}
]
}
Testar
Números
/api/v1/number/get
Comprar número
Compra um número, ou vários com quantity. Debita na hora. Se o número cancelar ou expirar sem código, o valor volta ao saldo.
Parâmetros
| Nome | Descrição | |
|---|---|---|
country | obrigatório | ID do país. |
service | obrigatório | Código do serviço. |
max_price_brl | opcional | Teto de preço. Usa a faixa mais cara que couber nele. Sem isso, usa a mais barata. |
operator | opcional | Operadora. Padrão: qualquer. Restringe o estoque. |
quantity | opcional | Quantidade, de 1 a 50. Sem isso compra 1 e a resposta vem no formato simples. |
request_id | opcional | Chave anti-duplicação, 8 a 80 caracteres. O header Idempotency-Key também vale. Recomendada. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID da ativação. Vai em /number/status, /number/cancel e /number/finish. |
service | string | Código do serviço. |
service_name | string | Nome do serviço. Vem do provedor, não é traduzido. |
country | integer | ID do país. |
country_name | string | Nome do país. |
phone | string | Número com DDI, só dígitos (5511999999999). |
state | string | Estado da ativação (veja Estados). Valor fixo em inglês; use este na lógica. |
state_label | string | Estado em texto, no idioma da conta. Só para exibir. |
code | string | null | Último código recebido. null enquanto não chegou. |
codes | array | Todos os códigos, [{ code, received_at }], do mais antigo ao mais novo. |
price_brl | number | Valor cobrado, em reais. |
seconds_left | integer | Segundos até a ativação expirar. |
cancel_in_seconds | integer | Segundos até liberar o cancelamento. 0 = já pode. |
balance_brl | number | Saldo depois da compra. |
| com quantity | ||
requested | integer | Quantidade pedida. |
purchased | integer | Quantidade comprada. |
failed | integer | Quantidade não comprada (não é cobrada). |
numbers | array | Ativações, com os mesmos campos acima. |
errors | array | Códigos de erro das compras que falharam (compra parcial). |
Erros
Exemplo
curl "https://kdefy-sms.com/api/v1/number/get?country=73&service=wa&request_id=pedido-0001" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/number/get?country=73&service=wa&request_id=pedido-0001", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/number/get",
params={"country": 73, "service": "wa", "request_id": "pedido-0001"},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/number/get?country=73&service=wa&request_id=pedido-0001");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/number/get?country=73&service=wa&request_id=pedido-0001")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/number/get" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "country=73" \
--data-urlencode "service=wa" \
--data-urlencode "request_id=pedido-0001" | jq .Resposta
{
"id": "1842",
"service": "wa",
"service_name": "WhatsApp",
"country": 73,
"country_name": "Brasil",
"phone": "5511999999999",
"state": "waiting",
"state_label": "Aguardando código",
"code": null,
"codes": [],
"price_brl": 8.4,
"seconds_left": 1200,
"cancel_in_seconds": 120,
"status": "success",
"balance_brl": 17
}
Resposta com quantity=2
{
"status": "success",
"requested": 2,
"purchased": 2,
"failed": 0,
"numbers": [
{
"id": "1842",
"service": "wa",
"service_name": "WhatsApp",
"country": 73,
"country_name": "Brasil",
"phone": "5511999999999",
"state": "waiting",
"state_label": "Aguardando código",
"code": null,
"codes": [],
"price_brl": 8.4,
"seconds_left": 1200,
"cancel_in_seconds": 120
},
{
"id": "1843",
"service": "wa",
"service_name": "WhatsApp",
"country": 73,
"country_name": "Brasil",
"phone": "5511988887777",
"state": "waiting",
"state_label": "Aguardando código",
"code": null,
"codes": [],
"price_brl": 8.4,
"seconds_left": 1200,
"cancel_in_seconds": 120
}
],
"balance_brl": 8.6
}
Testar
/api/v1/number/status
Status e código
Estado da ativação e códigos recebidos.
Parâmetros
| Nome | Descrição | |
|---|---|---|
id | obrigatório | ID da ativação, vem da compra. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID da ativação. Vai em /number/status, /number/cancel e /number/finish. |
service | string | Código do serviço. |
service_name | string | Nome do serviço. Vem do provedor, não é traduzido. |
country | integer | ID do país. |
country_name | string | Nome do país. |
phone | string | Número com DDI, só dígitos (5511999999999). |
state | string | Estado da ativação (veja Estados). Valor fixo em inglês; use este na lógica. |
state_label | string | Estado em texto, no idioma da conta. Só para exibir. |
code | string | null | Último código recebido. null enquanto não chegou. |
codes | array | Todos os códigos, [{ code, received_at }], do mais antigo ao mais novo. |
price_brl | number | Valor cobrado, em reais. |
seconds_left | integer | Segundos até a ativação expirar. |
cancel_in_seconds | integer | Segundos até liberar o cancelamento. 0 = já pode. |
Erros
Exemplo
curl "https://kdefy-sms.com/api/v1/number/status?id=1842" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/number/status?id=1842", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/number/status",
params={"id": "1842"},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/number/status?id=1842");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/number/status?id=1842")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/number/status" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "id=1842" | jq .Resposta
{
"status": "success",
"id": "1842",
"service": "wa",
"service_name": "WhatsApp",
"country": 73,
"country_name": "Brasil",
"phone": "5511999999999",
"state": "code_received",
"state_label": "Código recebido",
"code": "123456",
"codes": [
{
"code": "123456",
"received_at": "2026-10-19T14:02:11.000Z"
}
],
"price_brl": 8.4,
"seconds_left": 1103,
"cancel_in_seconds": 0
}
Testar
/api/v1/number/cancel
Cancelar
Cancela e devolve o valor. Só sem código e 2 min após a compra; antes disso responde cancelamento_muito_cedo com retry_in_seconds. Na API não há multa por cancelamentos seguidos.
Parâmetros
| Nome | Descrição | |
|---|---|---|
id | obrigatório | ID da ativação. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID da ativação. |
state | string | Sempre "cancelled". |
refunded_brl | number | Valor devolvido. |
balance_brl | number | Saldo depois do reembolso. |
Erros
Exemplo
curl "https://kdefy-sms.com/api/v1/number/cancel?id=1842" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/number/cancel?id=1842", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/number/cancel",
params={"id": "1842"},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/number/cancel?id=1842");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/number/cancel?id=1842")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/number/cancel" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "id=1842" | jq .Resposta
{
"status": "success",
"id": "1842",
"state": "cancelled",
"refunded_brl": 8.4,
"balance_brl": 25.4
}
Testar
/api/v1/number/finish
Finalizar
Encerra a ativação depois do código. Para de esperar códigos extras. Sem reembolso.
Parâmetros
| Nome | Descrição | |
|---|---|---|
id | obrigatório | ID da ativação. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
id | string | ID da ativação. |
state | string | Sempre "completed". |
Erros
Exemplo
curl "https://kdefy-sms.com/api/v1/number/finish?id=1842" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/number/finish?id=1842", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/number/finish",
params={"id": "1842"},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/number/finish?id=1842");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/number/finish?id=1842")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/number/finish" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "id=1842" | jq .Resposta
{
"status": "success",
"id": "1842",
"state": "completed"
}
Testar
Histórico
/api/v1/activations
Listar ativações
Suas ativações, inclusive as do site, da mais nova para a mais antiga.
Parâmetros
| Nome | Descrição | |
|---|---|---|
state | opcional | "active" lista só as em andamento. |
limit | opcional | Máximo de itens. Padrão 50, máx. 100. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
activations[] | array | Ativações, com os mesmos campos de /number/status. |
Exemplo
curl "https://kdefy-sms.com/api/v1/activations?state=active" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/activations?state=active", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/activations",
params={"state": "active"},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/activations?state=active");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/activations?state=active")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/activations" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "state=active" | jq .Resposta
{
"status": "success",
"activations": [
{
"id": "1842",
"service": "wa",
"service_name": "WhatsApp",
"country": 73,
"country_name": "Brasil",
"phone": "5511999999999",
"state": "waiting",
"state_label": "Aguardando código",
"code": null,
"codes": [],
"price_brl": 8.4,
"seconds_left": 1200,
"cancel_in_seconds": 120
}
]
}
Testar
/api/v1/transactions
Extrato
Recargas, compras e reembolsos.
Parâmetros
| Nome | Descrição | |
|---|---|---|
limit | opcional | Máximo de itens. Padrão 50, máx. 200. |
Campos da resposta
| Campo | Tipo | Descrição |
|---|---|---|
transactions[].type | string | Tipo (PURCHASE, REFUND...). |
transactions[].amount_brl | number | Valor. |
transactions[].balance_after_brl | number | Saldo depois. |
transactions[].description | string | Descrição. |
transactions[].created_at | string | Data (ISO 8601). |
Exemplo
curl "https://kdefy-sms.com/api/v1/transactions?limit=20" \
-H "X-API-Key: $KDEFY_API_KEY"const res = await fetch("https://kdefy-sms.com/api/v1/transactions?limit=20", {
headers: { "X-API-Key": process.env.KDEFY_API_KEY },
});
const data = await res.json();
if (data.status !== "success") throw new Error(data.error);
console.log(data);import os, requests
r = requests.get(
"https://kdefy-sms.com/api/v1/transactions",
params={"limit": 20},
headers={"X-API-Key": os.environ["KDEFY_API_KEY"]},
timeout=20,
)
data = r.json()
if data["status"] != "success":
raise RuntimeError(data["error"])
print(data)<?php
$ch = curl_init("https://kdefy-sms.com/api/v1/transactions?limit=20");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 20,
CURLOPT_HTTPHEADER => ["X-API-Key: " . getenv("KDEFY_API_KEY")],
]);
$data = json_decode(curl_exec($ch), true);
if (($data["status"] ?? null) !== "success") {
throw new RuntimeException($data["error"] ?? "erro_desconhecido");
}
print_r($data);require "net/http"
require "json"
uri = URI("https://kdefy-sms.com/api/v1/transactions?limit=20")
req = Net::HTTP::Get.new(uri, "X-API-Key" => ENV.fetch("KDEFY_API_KEY"))
res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https", read_timeout: 20) { |http| http.request(req) }
data = JSON.parse(res.body)
abort(data["error"]) unless data["status"] == "success"
puts JSON.pretty_generate(data)#!/usr/bin/env bash
curl -sS --max-time 20 -G "https://kdefy-sms.com/api/v1/transactions" \
-H "X-API-Key: $KDEFY_API_KEY" \
--data-urlencode "limit=20" | jq .Resposta
{
"status": "success",
"transactions": [
{
"type": "PURCHASE",
"amount_brl": 8.4,
"balance_after_brl": 17,
"description": "Compra WhatsApp · Brasil (API)",
"created_at": "2026-10-19T14:00:00.000Z"
}
]
}
Testar
Erros
Formato: { "status": "error", "error": "saldo_insuficiente", "message": "..." }. Decida pelo campo error.
| HTTP | error | Quando | O que fazer |
|---|---|---|---|
| 401 | token_nao_informado token_invalido | Token ausente, inválido ou revogado. | Corrija o token. Não repita. |
| 403 | conta_bloqueada token_suspenso | Conta banida ou API suspensa pelo admin. | Fale com o suporte. |
| 400 | pais_invalido servico_invalido id_invalido quantidade_invalida preco_invalido operador_invalido request_id_invalido | Parâmetro ausente ou inválido. | Corrija a chamada. |
| 402 | saldo_insuficiente | Saldo menor que o preço. | Recarregue no site. |
| 404 | sem_numeros_disponiveis oferta_indisponivel | Sem estoque nessa faixa agora. | Suba max_price_brl, troque o país ou tente depois. |
| 404 | ativacao_nao_encontrada | ID inexistente ou de outra conta. | Confira o id. |
| 409 | requisicao_em_andamento | A request_id ainda está sendo processada. | Espere e repita a mesma chamada. |
| 409 | cancelamento_muito_cedo | Menos de 2 min desde a compra. | Espere retry_in_seconds. |
| 409 | ativacao_nao_cancelavel ativacao_nao_finalizavel | O estado atual não permite a ação. | Consulte /number/status. |
| 422 | request_id_reutilizada | Mesma request_id com parâmetros diferentes. | Use uma request_id nova. |
| 422 | preco_abaixo_do_minimo | max_price_brl menor que a oferta mais barata. | Suba para min_price_brl ou mais. |
| 429 | limite_de_requisicoes limite_de_numeros | Passou do limite. | Espere retry_in_seconds. |
| 502 | falha_temporaria | Instabilidade. Você não é cobrado. | Repita com espera crescente, mesma request_id. |
Perguntas frequentes
Quanto o código demora?
Em geral segundos, mas depende do serviço. A ativação espera até 20 min. Sem código nesse prazo, expira e o valor volta ao saldo.
Dei timeout na compra. E agora?
Repita a mesma chamada com a mesma request_id: a resposta original volta e nada é cobrado de novo. Se você não usou request_id, liste /activations?state=active antes de comprar outra vez.
Posso cancelar logo depois de comprar?
Não. O cancelamento libera 2 min após a compra. cancel_in_seconds mostra quanto falta.
sem_numeros_disponiveis com saldo. Por quê?
A faixa de preço está sem estoque agora. Suba max_price_brl, troque o país ou veja onde há estoque em /offers.
O preço muda entre a consulta e a compra?
Pode mudar. Vale o price_brl da resposta da compra, e max_price_brl impede que passe do seu teto.
Preciso de request_id?
Não é obrigatória, mas use em qualquer automação. Sem ela, repetir a chamada por engano compra duas vezes.
Dá para comprar mais de 50 números?
Não numa requisição, e o teto é 50 por minuto por conta. Acima disso a API responde limite_de_numeros.
Por que a resposta vem em português?
message e state_label seguem o idioma da conta. Force com ?lang=pt ou ?lang=en. Chaves do JSON, state e códigos de erro são sempre os mesmos.
Como recarrego o saldo?
Pelo site, com PIX. O saldo da API é o mesmo do site.
O token vazou.
Gere outro em API, no site. O antigo para de funcionar na hora. Se viu uso estranho, fale com o suporte.
Regras de uso
- Cada ativação espera o código por até 20 min. Sem código, expira e o valor volta ao saldo.
- Depois do primeiro código não há reembolso.
- Você só enxerga e opera as suas ativações.
- Recarga de saldo é pelo site (PIX).
- Toda requisição fica registrada na conta. O admin consulta o uso do token.
- Abuso ou fraude pode bloquear a conta.