KDEFY SMS API v1.0 Base URL: https://kdefy-sms.com/api/v1 API REST para comprar números virtuais e receber SMS. Usa o mesmo saldo e as mesmas ativações da sua conta no site. 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 (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. 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 =============== 1. GET /services?country=73: serviços do país e preço inicial. 2. GET /offers?country=73&service=wa (opcional): faixas de preço e estoque. 3. GET /number/get?country=73&service=wa&request_id=...: compra e devolve phone e id. 4. GET /number/status?id=ID a cada 5 s, até code vir preenchido. 5. 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 (JavaScript) ============================= 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."); } EXEMPLO COMPLETO (Python) ========================= # 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.") BOAS 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. ROTAS ===== [Conta] Saldo GET https://kdefy-sms.com/api/v1/balance Saldo e totais da conta. Campos da resposta: - balance_brl (number): Saldo disponível. - total_spent_brl (number): Total gasto na conta. - total_recharged_brl (number): Total recarregado. - currency (string): Sempre "BRL". Resposta de exemplo: { "status": "success", "balance_brl": 25.4, "total_spent_brl": 12.1, "total_recharged_brl": 37.5, "currency": "BRL" } cURL: curl "https://kdefy-sms.com/api/v1/balance" \ -H "X-API-Key: $KDEFY_API_KEY" [Conta] Perfil GET https://kdefy-sms.com/api/v1/profile Usuário, saldo e data de criação. Campos da resposta: - username (string): Usuário. - balance_brl (number): Saldo disponível. - created_at (string): Criação da conta (ISO 8601). Resposta de exemplo: { "status": "success", "username": "maria", "balance_brl": 25.4, "created_at": "2026-09-01T12:00:00.000Z" } cURL: curl "https://kdefy-sms.com/api/v1/profile" \ -H "X-API-Key: $KDEFY_API_KEY" [Catálogo] Países GET https://kdefy-sms.com/api/v1/countries Lista de países. Use o id em country. Campos da resposta: - countries[].id (integer): ID do país. Use em country. - countries[].name (string): Nome. - countries[].dial_code (string | null): DDI, ex.: +55. Resposta de exemplo: { "status": "success", "countries": [ { "id": 73, "name": "Brasil", "dial_code": "+55" } ] } cURL: curl "https://kdefy-sms.com/api/v1/countries" \ -H "X-API-Key: $KDEFY_API_KEY" [Catálogo] Serviços GET https://kdefy-sms.com/api/v1/services Serviços de um país, com estoque e preço inicial. Use code em service. Parâmetros: - country (obrigatório): ID do país. Campos da resposta: - 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: pais_invalido Resposta de exemplo: { "status": "success", "country": 73, "services": [ { "code": "wa", "name": "WhatsApp", "available": 1240, "from_price_brl": 7.1 } ] } cURL: curl "https://kdefy-sms.com/api/v1/services?country=73" \ -H "X-API-Key: $KDEFY_API_KEY" [Catálogo] Operadoras GET https://kdefy-sms.com/api/v1/operators Operadoras de um país. Uso opcional em operator na compra. Parâmetros: - country (obrigatório): ID do país. Campos da resposta: - country (integer): País consultado. - operators[].id (string): ID da operadora. Use em operator. - operators[].name (string): Nome. Erros: pais_invalido Resposta de exemplo: { "status": "success", "country": 73, "operators": [ { "id": "vivo", "name": "vivo" } ] } cURL: curl "https://kdefy-sms.com/api/v1/operators?country=73" \ -H "X-API-Key: $KDEFY_API_KEY" [Catálogo] Ofertas GET https://kdefy-sms.com/api/v1/offers 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: - country (obrigatório): ID do país. - service (obrigatório): Código do serviço. Campos da resposta: - offers[].price_brl (number): Preço da faixa. - offers[].available (integer): Estoque da faixa. Erros: pais_invalido, servico_invalido, sem_numeros_disponiveis Resposta de exemplo: { "status": "success", "country": 73, "service": "wa", "offers": [ { "price_brl": 7.1, "available": 12 }, { "price_brl": 8.4, "available": 340 } ] } cURL: curl "https://kdefy-sms.com/api/v1/offers?country=73&service=wa" \ -H "X-API-Key: $KDEFY_API_KEY" [Números] Comprar número GET|POST https://kdefy-sms.com/api/v1/number/get 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: - 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. Nota: Lote e repetição segura: veja Compra em lote e Idempotência em Guias. Campos da resposta: - 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: 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 Resposta de exemplo: { "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 } cURL: curl "https://kdefy-sms.com/api/v1/number/get?country=73&service=wa&request_id=pedido-0001" \ -H "X-API-Key: $KDEFY_API_KEY" [Números] Status e código GET https://kdefy-sms.com/api/v1/number/status Estado da ativação e códigos recebidos. Parâmetros: - id (obrigatório): ID da ativação, vem da compra. Campos da resposta: - 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: id_invalido, ativacao_nao_encontrada Resposta de exemplo: { "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 } cURL: curl "https://kdefy-sms.com/api/v1/number/status?id=1842" \ -H "X-API-Key: $KDEFY_API_KEY" [Números] Cancelar GET|POST https://kdefy-sms.com/api/v1/number/cancel 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: - id (obrigatório): ID da ativação. Campos da resposta: - id (string): ID da ativação. - state (string): Sempre "cancelled". - refunded_brl (number): Valor devolvido. - balance_brl (number): Saldo depois do reembolso. Erros: id_invalido, ativacao_nao_encontrada, ativacao_nao_cancelavel, cancelamento_muito_cedo, falha_temporaria Resposta de exemplo: { "status": "success", "id": "1842", "state": "cancelled", "refunded_brl": 8.4, "balance_brl": 25.4 } cURL: curl "https://kdefy-sms.com/api/v1/number/cancel?id=1842" \ -H "X-API-Key: $KDEFY_API_KEY" [Números] Finalizar GET|POST https://kdefy-sms.com/api/v1/number/finish Encerra a ativação depois do código. Para de esperar códigos extras. Sem reembolso. Parâmetros: - id (obrigatório): ID da ativação. Campos da resposta: - id (string): ID da ativação. - state (string): Sempre "completed". Erros: id_invalido, ativacao_nao_encontrada, ativacao_nao_finalizavel Resposta de exemplo: { "status": "success", "id": "1842", "state": "completed" } cURL: curl "https://kdefy-sms.com/api/v1/number/finish?id=1842" \ -H "X-API-Key: $KDEFY_API_KEY" [Histórico] Listar ativações GET https://kdefy-sms.com/api/v1/activations Suas ativações, inclusive as do site, da mais nova para a mais antiga. Parâmetros: - state (opcional): "active" lista só as em andamento. - limit (opcional): Máximo de itens. Padrão 50, máx. 100. Campos da resposta: - activations[] (array): Ativações, com os mesmos campos de /number/status. Resposta de exemplo: { "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 } ] } cURL: curl "https://kdefy-sms.com/api/v1/activations?state=active" \ -H "X-API-Key: $KDEFY_API_KEY" [Histórico] Extrato GET https://kdefy-sms.com/api/v1/transactions Recargas, compras e reembolsos. Parâmetros: - limit (opcional): Máximo de itens. Padrão 50, máx. 200. Campos da resposta: - 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). Resposta de exemplo: { "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" } ] } cURL: curl "https://kdefy-sms.com/api/v1/transactions?limit=20" \ -H "X-API-Key: $KDEFY_API_KEY" ERROS (HTTP | código | 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 ==================== P: Quanto o código demora? R: 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. P: Dei timeout na compra. E agora? R: 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. P: Posso cancelar logo depois de comprar? R: Não. O cancelamento libera 2 min após a compra. cancel_in_seconds mostra quanto falta. P: sem_numeros_disponiveis com saldo. Por quê? R: A faixa de preço está sem estoque agora. Suba max_price_brl, troque o país ou veja onde há estoque em /offers. P: O preço muda entre a consulta e a compra? R: Pode mudar. Vale o price_brl da resposta da compra, e max_price_brl impede que passe do seu teto. P: Preciso de request_id? R: Não é obrigatória, mas use em qualquer automação. Sem ela, repetir a chamada por engano compra duas vezes. P: Dá para comprar mais de 50 números? R: Não numa requisição, e o teto é 50 por minuto por conta. Acima disso a API responde limite_de_numeros. P: Por que a resposta vem em português? R: 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. P: Como recarrego o saldo? R: Pelo site, com PIX. O saldo da API é o mesmo do site. P: O token vazou. R: Gere outro em API, no site. O antigo para de funcionar na hora. Se viu uso estranho, fale com o suporte. REGRAS ====== - 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.