← Blog
Developer playbook · 16 min de leitura · Published abril 2026 · Author Serhat Dogan

Guia de Migração do SMS-Activate 2026: Checklist de Desenvolvedor, Mapeamento de API e Comparação de Reembolso

Guia de Migração do SMS-Activate 2026: Checklist de Desenvolvedor, Mapeamento de API e Comparação de Reembolso

If you are still carrying handler_api.php calls in your repo pointed at sms-activate.org, this is the hub you open at 9pm on a Friday and close with a working integration before midnight. Real endpoint mapping, real code diffs, refund policy comparison, and the gotchas that will bite you between the line you change and the alert that wakes you up on Monday morning.

Por que este guia existe

A maioria das postagens "SMS-Activate morreu, aqui está uma lista de alternativas" perdem a parte que realmente consome horas de desenvolvimento: o código. Cadastrar-se em um novo provedor leva cinco minutos. Reescrever uma integração que está funcionando silenciosamente em produção há anos, com casos de canto não testados e um rastreador de custos anexado a ela, leva mais tempo do que você imagina.

Depois que lançamos nossa camada de compatibilidade em janeiro de 2026, começamos a receber as mesmas três perguntas de cada equipe que a experimentou:

  1. Quais endpoints mapeiam claramente e quais precisam de alterações manuais?
  2. Como mantenho meu rastreamento de custos e fluxo de reembolso funcionando sem uma reescrita?
  3. O que quebra silenciosamente e aparece uma semana depois como uma surpresa na fatura?

Este guia responde a essas três perguntas em ordem e fornece código para copiar e colar que você pode auditar antes de executar.

O resumo de 48 horas: o que realmente aconteceu

SMS-Activate ficou offline em 29 de dezembro de 2025. Não houve banner de manutenção agendada, nenhuma ferramenta de migração e nenhum aviso público. Usuários tentando fazer login encontraram uma única página dizendo que o serviço havia fechado permanentemente. A API retornou resets de conexão em todos os endpoints em poucas horas.

Três coisas aconteceram rapidamente:

As consequências ainda estão se desenrolando. Em abril de 2026, existem casos ativos de pequenas causas na Rússia e pelo menos dois processos comunitários coordenados tentando recuperar saldos congelados. Nada disso ajuda seu código, razão pela qual vamos nos concentrar na parte que você pode realmente consertar.

Parte 1: Mapa de depreciação de API

SMS-Activate lançou um único endpoint público em https://sms-activate.org/stubs/handler_api.php. Cada ação era um parâmetro de string de consulta nesse URL. A tabela abaixo mapeia cada ação principal para seu equivalente VerifySMS. A camada de compatibilidade em https://api.verifysms.app/compat/handler_api.php aceita exatamente a mesma forma de string de consulta.

Ação SMS-ActivatePropósitoCamada de compatibilidade VerifySMSAPI Nativa VerifySMS
getBalanceRetorna o saldo em USD como textoFunciona sem alterações. Retorna ACCESS_BALANCE:X.YYGET /v1/balance retorna JSON
getNumbersStatusDisponibilidade por paísFunciona. Retorna o formato de mapa legadoGET /v1/countries/availability
getNumberAlugar um número para um serviçoFunciona. Retorna ACCESS_NUMBER:id:+phonePOST /v1/rentals
setStatusConfirmar ou cancelar um aluguelFunciona. Códigos de status 1/3/6/8 se comportam de forma idênticaPOST /v1/rentals/{id}/status
getStatusConsultar chegada de SMSFunciona. Retorna STATUS_WAIT_CODE, STATUS_OK:CODE, STATUS_WAIT_RETRYGET /v1/rentals/{id}
getPricesObter tabela de preçosFunciona. Retorna os preços do VerifySMS no formato JSON legadoGET /v1/prices
getCountriesMapa de códigos de paísFunciona. Retorna IDs numéricos legados e códigos ISO-3166GET /v1/countries
getTopCountriesByServicePrincipais países por serviçoRetorna dados em tempo real do VerifySMS em vez de classificações em cache do SMS-ActivateGET /v1/services/{id}/top-countries

Um punhado de ações menos usadas do SMS-Activate não têm um mapeamento direto. getRentServicesAndCountries e a API de aluguel de longo prazo eram específicas do SMS-Activate e não possuem camada de compatibilidade. Se sua integração usou essas, você deve migrar para o endpoint nativo de longo prazo do VerifySMS em POST /v1/rentals/long, que é documentado separadamente.

Parte 2: Tutoriais de migração de código

Os trechos a seguir são exatamente como testei em nosso próprio ambiente de staging em janeiro. Mantive-os deliberadamente simples para que você possa lê-los em comparação com seu próprio código sem troca de contexto.

Python (requests)

A única alteração necessária é a URL base. Se você já encapsulou a API em um pequeno módulo cliente, a diferença é uma única linha.

import os
import requests

# ANTES
# BASE_URL = "https://sms-activate.org/stubs/handler_api.php"
# DEPOIS
BASE_URL = "https://api.verifysms.app/compat/handler_api.php"
API_KEY = os.environ["SMS_API_KEY"]

def get_number(service: str, country: int) -> tuple[str, str]:
    resp = requests.get(BASE_URL, params={
        "api_key": API_KEY,
        "action": "getNumber",
        "service": service,
        "country": country,
    }, timeout=30)
    resp.raise_for_status()
    # ACCESS_NUMBER:12345:+441234567890
    status, rental_id, phone = resp.text.split(":", 2)
    if status != "ACCESS_NUMBER":
        raise RuntimeError(f"resposta inesperada: {resp.text}")
    return rental_id, phone

def wait_for_code(rental_id: str, deadline_seconds: int = 180) -> str:
    import time
    start = time.monotonic()
    while time.monotonic() - start < deadline_seconds:
        resp = requests.get(BASE_URL, params={
            "api_key": API_KEY,
            "action": "getStatus",
            "id": rental_id,
        }, timeout=15).text
        if resp.startswith("STATUS_OK:"):
            return resp.split(":", 1)[1]
        time.sleep(4)
    # Marcar como não utilizado para que obtenhamos o reembolso
    requests.get(BASE_URL, params={
        "api_key": API_KEY,
        "action": "setStatus",
        "status": 8,
        "id": rental_id,
    }, timeout=15)
    raise TimeoutError(f"sem código após {deadline_seconds}s")

Node.js (axios)

import axios from "axios";

// ANTES
// const BASE_URL = "https://sms-activate.org/stubs/handler_api.php";
// DEPOIS
const BASE_URL = "https://api.verifysms.app/compat/handler_api.php";
const API_KEY = process.env.SMS_API_KEY;

export async function getNumber(service, country) {
  const { data } = await axios.get(BASE_URL, {
    params: { api_key: API_KEY, action: "getNumber", service, country },
    timeout: 30_000,
  });
  const [status, rentalId, phone] = data.split(":");
  if (status !== "ACCESS_NUMBER") {
    throw new Error(`resposta inesperada: ${data}`);
  }
  return { rentalId, phone };
}

export async function waitForCode(rentalId, deadlineMs = 180_000) {
  const start = Date.now();
  while (Date.now() - start < deadlineMs) {
    const { data } = await axios.get(BASE_URL, {
      params: { api_key: API_KEY, action: "getStatus", id: rentalId },
      timeout: 15_000,
    });
    if (data.startsWith("STATUS_OK:")) return data.split(":")[1];
    await new Promise((r) => setTimeout(r, 4000));
  }
  await axios.get(BASE_URL, {
    params: { api_key: API_KEY, action: "setStatus", status: 8, id: rentalId },
    timeout: 15_000,
  });
  throw new Error(`sem código após ${deadlineMs}ms`);
}

PHP (curl)

<?php
// ANTES
// const BASE_URL = "https://sms-activate.org/stubs/handler_api.php";
// DEPOIS
const BASE_URL = "https://api.verifysms.app/compat/handler_api.php";

function sms_call(array $params): string {
    $params["api_key"] = getenv("SMS_API_KEY");
    $url = BASE_URL . "?" . http_build_query($params);
    $ch  = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    $body = curl_exec($ch);
    curl_close($ch);
    return $body;
}

function get_number(string $service, int $country): array {
    $resp = sms_call(["action" => "getNumber", "service" => $service, "country" => $country]);
    [$status, $id, $phone] = explode(":", $resp, 3);
    if ($status !== "ACCESS_NUMBER") {
        throw new RuntimeException("inesperado: $resp");
    }
    return ["id" => $id, "phone" => $phone];
}

Go (net/http)

package sms

import (
    "errors"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
    "strings"
    "time"
)

// ANTES
// const baseURL = "https://sms-activate.org/stubs/handler_api.php"
// DEPOIS
const baseURL = "https://api.verifysms.app/compat/handler_api.php"

func call(params url.Values) (string, error) {
    params.Set("api_key", os.Getenv("SMS_API_KEY"))
    req, _ := http.NewRequest("GET", baseURL+"?"+params.Encode(), nil)
    client := &http.Client{Timeout: 30 * time.Second}
    resp, err := client.Do(req)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    return string(body), nil
}

func GetNumber(service string, country int) (id, phone string, err error) {
    body, err := call(url.Values{
        "action":  {"getNumber"},
        "service": {service},
        "country": {fmt.Sprint(country)},
    })
    if err != nil {
        return "", "", err
    }
    parts := strings.SplitN(body, ":", 3)
    if len(parts) != 3 || parts[0] != "ACCESS_NUMBER" {
        return "", "", errors.New("inesperado: " + body)
    }
    return parts[1], parts[2], nil
}

O exemplo em Go é deliberadamente escrito sem nenhum cliente de terceiros para que você possa inseri-lo em um serviço mínimo sem adicionar dependências. O mesmo padrão se aplica em todas as outras linguagens: troque a URL, mantenha o resto e deixe seu tratamento de erro existente assumir.

Parte 3: Armadilhas que vão te pegar

Estes são os lugares onde a camada de compatibilidade é fiel às peculiaridades do SMS-Activate, mas as próprias peculiaridades o surpreenderão se você não mexeu nesse código há algum tempo.

IDs de país não são códigos ISO

SMS-Activate numerou os países em sua própria ordem: Rússia era 0, EUA era 187, Indonésia era 6, e assim por diante. Se sua integração tem esses números mágicos codificados, eles ainda funcionam na camada de compatibilidade. Se você está escrevendo código novo, prefira a forma alfanumérica ISO-3166 (RU, US, ID) que a camada de compatibilidade também aceita. Não misture os dois estilos no mesmo local de chamada, pois a depuração futura será dolorosa.

Código de status 3 versus 6

O código de ação 3 do setStatus significava "solicitar outro SMS" no mundo do SMS-Activate, e o código 6 significava "aceitar o código como válido". Esses dois códigos são fáceis de trocar com pressa e têm resultados de faturamento opostos: 3 mantém você cobrado, 6 confirma a verificação bem-sucedida. A camada de compatibilidade se comporta da mesma maneira. Procure seu código por setStatus e certifique-se de que o branch que aceita o código 6 só é executado depois que você tem certeza de que a verificação foi bem-sucedida.

Timeouts e disjuntores

SMS-Activate sob carga às vezes retornava um 200 com um corpo vazio em vez de um erro HTTP. Clientes defensivos encapsulam a chamada em um timeout e tratam o corpo vazio como um sinal de nova tentativa. VerifySMS nunca retorna um corpo vazio na camada de compatibilidade. Se seu cliente ainda trata o corpo vazio como uma nova tentativa, ele queimará orçamento em uma rede instável porque a nova tentativa atingirá um ID de aluguel diferente. O padrão mais seguro é verificar os prefixos de resposta conhecidos (ACCESS_, STATUS_, BAD_) e tratar qualquer outra coisa como uma falha grave, não transitória.

Limites de taxa mudam de por chave para por IP

Os limites de taxa do SMS-Activate eram associados ao token da API. Os limites de taxa do VerifySMS são associados à combinação do token da API e do endereço IP de origem, pois vemos muitos abusos de scripts de raspagem compartilhando uma chave em uma botnet. Para tráfego de produção normal de um único servidor ou um pool balanceado de carga, isso é invisível. Se você executar trabalhos de CI distribuídos que compartilham uma chave de staging, poderá ver um 429 na primeira vez que toda a frota aquecer junta. A correção é deixar o canário rodar de um nó por um dia antes de expandir.

O tempo de reembolso parece instantâneo porque é realmente instantâneo

Esta não é uma armadilha tanto quanto uma surpresa agradável. Onde os reembolsos do SMS-Activate levavam algumas horas para aparecer em seu saldo, os reembolsos do VerifySMS aparecem em 60 segundos. Se o seu rastreador de custos lê o saldo em uma programação, ele registrará o reembolso como um crédito que o sistema antigo teria perdido. Painéis de reconciliação às vezes sinalizam isso como uma anomalia no primeiro dia.

Parte 4: Realidade da comparação de preços

Antes do desligamento, SMS-Activate era o piso do mercado. Números russos custavam de US$ 0,03 a US$ 0,05 por verificação, e compradores de grande volume pagavam ainda menos. Esse piso se foi. É aqui que os provedores restantes se situam em abril de 2026 para os serviços mais comuns, retirados da página de preços públicos de cada provedor em :

Serviço5simTextVerifiedSMSPVASMS-MANVerifySMS
WhatsApp / Rússia$0.014$0.05$0.035$0.10
WhatsApp / EUA$0.27$0.25$0.28$0.22$0.18
Telegram / Rússia$0.016$0.05$0.04$0.10
Telegram / EUA$0.35$0.40$0.38$0.30$0.20
Google / Indonésia$0.07$0.08$0.06$0.10

O padrão é simples: 5sim e SMS-MAN vencem nos preços russos mais baixos, TextVerified é o nível premium dos EUA, e VerifySMS fica no meio com uma base de US$ 0,10 para tudo, exceto os números não-VoIP mais caros dos EUA. Se seu orçamento foi ajustado aos preços mínimos do SMS-Activate, espere pagar de duas a cinco vezes mais por verificação, independentemente do substituto que você escolher.

Duas notas sobre esta tabela. Primeiro, todos os provedores (incluindo VerifySMS) aumentam e diminuem os preços individuais de países em resposta aos custos das operadoras, portanto, confirme o preço atual em seu próprio painel antes de comprometer um orçamento. Segundo, o preço efetivo por verificação bem-sucedida depende da taxa de reembolso. Um provedor com um preço de etiqueta de US$ 0,08 e uma taxa de sucesso de 70% custa mais por sucesso do que um provedor de US$ 0,10 com reembolsos automáticos e uma taxa de sucesso de 90%.

Parte 5: O checklist de migração de 10 passos

Esta é a sequência real que percorremos com nossos próprios usuários em janeiro. Ela assume um único desenvolvedor com acesso ao repositório, um serviço de produção e um ambiente de staging. Aumente as porcentagens do canário se você estiver executando vários serviços ou um monorepo.

  1. Inventarie todos os locais de chamada. Execute git grep -n 'sms-activate\.org\|handler_api\.php\|getNumber\|setStatus' e liste todos os arquivos que acessam a API antiga. Se encontrar mais de uma dúzia, escolha um módulo wrapper e centralize as chamadas primeiro antes de migrar.
  2. Obtenha uma chave de API VerifySMS. Cadastre-se, adicione um pequeno saldo e gere uma chave com escopo para staging. Mantenha a chave de produção fora do repositório.
  3. Altere a URL base. Substitua o host do SMS-Activate por api.verifysms.app/compat/handler_api.php. Não altere a string de consulta. Confirme isso sozinho para que a diferença seja limpa.
  4. Execute seus testes existentes. Se os testes acessarem a API real, aponte-os para staging e observe as incompatibilidades de formato. Se eles mockarem a API, execute-os contra o endpoint de staging ativo também para capturar desvios de contrato.
  5. Reconfirme os IDs de país. Verifique seu código em busca de constantes de país. Se você estiver usando os IDs numéricos legados, eles ainda funcionam. Se tiver a chance, substitua-os por códigos ISO-3166 porque o próximo desenvolvedor a mexer neste arquivo agradecerá.
  6. Conecte as reivindicações de reembolso. Confirme se seu caminho de timeout chama setStatus com status=8. Sem isso, você ainda receberá reembolsos (nós reembolsamos automaticamente aluguéis expirados), mas seu rastreador de custos ficará atrasado em relação à realidade.
  7. Atualize seu rastreador de custos. Leia o custo do cabeçalho de resposta X-VerifySMS-Cost em vez de analisá-lo na tabela de preços. Esta única alteração torna seu painel financeiro preciso até o centavo.
  8. Monitoramento. Adicione alertas de taxa de sucesso, latência p95 e taxa de reembolso contra sua linha de base existente. Escolha limites que você possa defender, não aqueles que você acha que serão "bons".
  9. Canário de 5 por cento por 24 horas. Direcione uma pequena fatia do tráfego de produção através do novo endpoint. Observe o painel, não apenas os alertas.
  10. Corte o restante. Uma vez que a janela do canário esteja limpa, mova os 95 por cento restantes e deixe o código do cliente antigo comentado (não excluído) por um ciclo de lançamento para que você tenha um rollback rápido.

Exclua o código antigo no próximo lançamento depois desse. Não deixe locais de chamada mortos por mais de uma semana, pois a próxima pessoa a mexer no módulo os colará acidentalmente em uma nova integração.

Perguntas frequentes

A camada de compatibilidade SMS-Activate é uma API real ou apenas um stub?

É um endpoint real em api.verifysms.app/compat/handler_api.php que aceita todas as principais ações da documentação pública do SMS-Activate: getBalance, getNumber, getStatus, setStatus, getPrices e getCountries. As solicitações são encaminhadas para nossa API nativa nos bastidores, para que você obtenha os preços, cobertura e comportamento de reembolso do VerifySMS sem alterações no código de seu lado.

Minha chave de API antiga funcionará?

Não. As chaves de API do SMS-Activate pararam de autenticar no dia em que o serviço foi desativado. Você precisa de uma nova chave do VerifySMS. Cadastre-se, adicione um pequeno saldo e gere uma chave no painel. O formato da chave é idêntico em comprimento, para que você possa colá-la na mesma variável de ambiente.

Como funcionam os reembolsos em comparação com o SMS-Activate?

SMS-Activate exigia que você chamasse setStatus com o código de status 8 dentro de 20 minutos para marcar um número como não utilizado, e os reembolsos eram processados manualmente em poucas horas. VerifySMS aceita a mesma chamada setStatus e reembolsa o valor total para seu saldo em 60 segundos. Se você esquecer de chamar setStatus completamente, nosso sistema ainda reembolsa automaticamente qualquer número que nunca recebeu um SMS após o término da janela de aluguel.

Quais países são suportados?

VerifySMS cobre mais de 200 países. Todos os países que o SMS-Activate ofereceu estão disponíveis no VerifySMS, incluindo Rússia, Indonésia, Vietnã, Nigéria e EUA. Você pode manter seu mapeamento de ID de país existente ou migrar para códigos ISO-3166 alpha-2 sempre que quiser.

O preço é o mesmo?

Não. Os preços mínimos de mercado do SMS-Activate de US$ 0,03 a US$ 0,05 por verificação para números russos desapareceram do mercado aberto. Os preços atuais de mercado variam de US$ 0,10 para serviços comuns a US$ 0,25 para números não-VoIP dos EUA em plataformas mais rigorosas. VerifySMS cobra US$ 0,10 como base e publica preços por país no painel.

Preciso mudar minha lógica de polling?

Não. A chamada getStatus retorna STATUS_WAIT_CODE e STATUS_OK no mesmo formato que o SMS-Activate usava. Intervalos de polling de 3 a 5 segundos ainda funcionam. O único novo comportamento é que VerifySMS também expõe um URL de webhook no painel, para que você possa parar de fazer polling completamente se preferir um fluxo orientado a eventos.

O que acontece se a camada de compatibilidade for descontinuada?

A camada de compatibilidade é considerada uma interface pública permanente. Se mudarmos seu comportamento, publicaremos uma janela de depreciação de no mínimo seis meses com uma nota de migração completa. A API JSON nativa do VerifySMS também é documentada, para que você possa migrar da camada de compatibilidade no seu próprio ritmo, sempre que fizer sentido.

Como faço para testar sem gastar dinheiro?

O painel VerifySMS expõe um modo sandbox que retorna números de telefone simulados e códigos SMS em cache sem debitar seu saldo. Ative o sinalizador sandbox no painel ou envie o cabeçalho X-Sandbox-Mode com qualquer solicitação para exercitar seus caminhos de código antes de ir para produção.

Posso migrar de outros serviços também?

Sim. Este guia é escrito em torno da API SMS-Activate porque é onde a maioria do código abandonado reside, mas o mesmo checklist se aplica a migrações de 5sim, SMS-MAN ou qualquer outro serviço compatível com handler_api. A camada de compatibilidade reconhece os parâmetros de handler_api.php, independentemente de qual serviço você estava chamando anteriormente.

Quanto tempo leva uma migração real?

Para uma integração de serviço único com algumas dezenas de locais de chamada, planeje de duas a quatro horas de trabalho focado, mais uma janela de canário de 24 horas antes de cortar o tráfego total. Migrações maiores de vários serviços com tratamento de erros personalizado, análises e novas tentativas podem levar mais tempo, mas geralmente terminam dentro de um único dia útil.

Perco meus dados históricos?

O histórico de verificação do SMS-Activate ficou offline quando o serviço foi desativado e não é recuperável. VerifySMS mantém um log de auditoria completo de cada tentativa de verificação em sua conta por 12 meses, acessível no painel e via extensão /compat/handler_api.php?action=getHistory.

Isso afeta minha postura de GDPR ou conformidade?

VerifySMS é registrado no Reino Unido e segue o UK GDPR. Publicamos nossa política de retenção de dados, sub-processadores e DPA na página de privacidade. Se sua configuração anterior exigia um DPA com SMS-Activate, entre em contato conosco e assinaremos o mesmo acordo dentro de um dia útil.

Próximos passos

Se você leu até aqui, já tem as peças que precisa. Comece com a etapa de inventário, apresente a troca da URL base a um colega para revisão e execute o canário durante a noite. O guia é pequeno de propósito; a parte difícil é a disciplina de parar após a janela do canário em vez de cortar tudo em um único commit.

Leitura relacionada no restante do site:

Pronto para cortar a migração em uma única noite?

Crie uma chave de API VerifySMS →

Modo sandbox incluído · Garantia de reembolso automático · Mais de 200 países · Camada de compatibilidade SMS-Activate em /compat/handler_api.php

Next steps

If you have read this far, you already have the pieces you need. Start with the inventory step, get the base URL swap in front of a teammate for review, and run the canary overnight. The playbook is small on purpose; the hard part is the discipline to stop after the canary window instead of cutting everything over in one commit.

Related reading on the rest of the site:

Ready to cut the migration to a single evening?

Create a VerifySMS API key →

Sandbox mode included · Auto-refund guarantee · 200+ countries · SMS-Activate compat layer on /compat/handler_api.php