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

Centro de Migración de SMS-Activate 2026: Lista de Verificación para Desarrolladores, Mapeo de API y Comparación de Reembolsos

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 qué existe esta guía

La mayoría de las publicaciones que dicen "SMS-Activate está muerto, aquí hay una lista de alternativas" omiten la parte que realmente quema horas de desarrollo: el código. Registrarse en un nuevo proveedor toma cinco minutos. Reescribir una integración que ha estado ejecutándose silenciosamente en producción durante años, con casos de esquina no probados y un rastreador de costos adjunto, lleva más tiempo de lo que piensas.

Después de que enviamos nuestra capa de compatibilidad en enero de 2026, empezamos a recibir las mismas tres preguntas de cada equipo que la probó:

  1. ¿Cuáles endpoints se mapean limpiamente y cuáles necesitan cambios manuales?
  2. ¿Cómo puedo mantener mi seguimiento de costos y flujo de reembolso funcionando sin una reescritura?
  3. ¿Qué se rompe silenciosamente y aparece una semana después como una sorpresa en la facturación?

Esta guía responde a esas tres preguntas en orden y te proporciona código de copia y pega que puedes auditar antes de ejecutarlo.

El resumen de 48 horas: qué sucedió en realidad

SMS-Activate se apagó el 29 de diciembre de 2025. No hubo un banner de mantenimiento programado, ninguna herramienta de migración y ningún aviso público. Los usuarios que intentaron iniciar sesión se encontraron con una página que decía que el servicio había cerrado permanentemente. La API devolvió restablecimientos de conexión en todos los endpoints en unas pocas horas.

Sucedieron tres cosas rápidamente:

Las consecuencias aún están ocurriendo. A partir de abril de 2026, hay casos de reclamos pequeños activos en Rusia y al menos dos demandas coordinadas por la comunidad que intentan recuperar saldos congelados. Nada de eso ayuda a tu código, que es por lo que nos enfocaremos en la parte que puedes arreglar en realidad.

Parte 1: Mapa de deprecación de API

SMS-Activate envió un único endpoint público en https://sms-activate.org/stubs/handler_api.php. Cada acción era un parámetro de cadena de consulta en esa URL. La tabla siguiente mapea cada acción importante a su equivalente de VerifySMS. La capa de compatibilidad en https://api.verifysms.app/compat/handler_api.php acepta exactamente la misma forma de cadena de consulta.

Acción de SMS-ActivatePropósitoCapa de compatibilidad de VerifySMSAPI nativa de VerifySMS
getBalanceDevolver saldo en USD como textoFunciona sin cambios. Devuelve ACCESS_BALANCE:X.YYGET /v1/balance devuelve JSON
getNumbersStatusDisponibilidad por paísFunciona. Devuelve el formato de mapa heredadoGET /v1/countries/availability
getNumberAlquilar un número para un servicioFunciona. Devuelve ACCESS_NUMBER:id:+phonePOST /v1/rentals
setStatusConfirmar o cancelar un alquilerFunciona. Los códigos de estado 1/3/6/8 se comportan de manera idénticaPOST /v1/rentals/{id}/status
getStatusSondear para la llegada de SMSFunciona. Devuelve STATUS_WAIT_CODE, STATUS_OK:CODE, STATUS_WAIT_RETRYGET /v1/rentals/{id}
getPricesObtener la tabla de preciosFunciona. Devuelve precios de VerifySMS en la forma JSON heredadaGET /v1/prices
getCountriesMapa de códigos de paísFunciona. Devuelve tanto IDs numéricos heredados como códigos ISO-3166GET /v1/countries
getTopCountriesByServicePaíses principales por servicioDevuelve datos de VerifySMS en tiempo real en lugar de rangos de SMS-Activate en cachéGET /v1/services/{id}/top-countries

Un puñado de acciones de SMS-Activate menos utilizadas no se mapean de uno a uno. getRentServicesAndCountries y la API de alquiler de larga duración eran específicas de SMS-Activate y no tienen una capa de compatibilidad. Si tu integración utilizó esas, deberías cambiar a la endpoint de alquiler de larga duración nativa de VerifySMS en POST /v1/rentals/long, que está documentada por separado.

Parte 2: Recorrido de migración de código

Los siguientes fragmentos son exactamente la forma que probé contra nuestro entorno de pruebas en enero. Los he mantenido deliberadamente aburridos para que puedas leerlos contra tu propio código sin cambiar de contexto.

Python (requests)

El único cambio requerido es la URL base. Si ya has envuelto la API en un pequeño módulo de cliente, el diff es una sola línea.

import os
import requests

# ANTES
# BASE_URL = "https://sms-activate.org/stubs/handler_api.php"
# DESPUÉS
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"respuesta 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 no utilizado para obtener el reembolso
    requests.get(BASE_URL, params={
        "api_key": API_KEY,
        "action": "setStatus",
        "status": 8,
        "id": rental_id,
    }, timeout=15)
    raise TimeoutError(f"no hay código después de {deadline_seconds}s")

Node.js (axios)

import axios from "axios";

// ANTES
// const BASE_URL = "https://sms-activate.org/stubs/handler_api.php";
// DESPUÉS
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(`respuesta 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(`no hay código después de ${deadlineMs}ms`);
}

PHP (curl)

<?php
// ANTES
// const BASE_URL = "https://sms-activate.org/stubs/handler_api.php";
// DESPUÉS
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"
// DESPUÉS
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
}

El ejemplo de Go está escrito deliberadamente sin ningún cliente de terceros para que puedas insertarlo en un servicio mínimo sin agregar dependencias. El mismo patrón se aplica en todos los demás lenguajes: intercambia la URL, mantén el resto y deja que tu manejo de errores existente se haga cargo.

Parte 3: Problemas que te quemarán

Estos son los lugares donde la capa de compatibilidad es fiel a los caprichos de SMS-Activate, pero los caprichos en sí te sorprenderán si no has tocado este código en un tiempo.

Los IDs de país no son códigos ISO

SMS-Activate numeraba países en su propio orden: Rusia era 0, EE. UU. era 187, Indonesia era 6, y así sucesivamente. Si tu integración tiene estos números mágicos codificados, aún funcionan en la capa de compatibilidad. Si estás escribiendo código nuevo, prefiere la forma alfa-2 de ISO-3166 (RU, US, ID) que la capa de compatibilidad también acepta. No mezcles ambos estilos en el mismo sitio de llamada, porque la depuración futura será dolorosa.

Código de estado 3 versus 6

La acción setStatus código 3 significaba "solicitar otro SMS" en el mundo de SMS-Activate, y el código 6 significaba "aceptar el código como válido". Estos dos códigos son fáciles de intercambiar en un apuro y tienen resultados de facturación opuestos: 3 te mantiene facturado, 6 confirma la verificación exitosa. La capa de compatibilidad se comporta de la misma manera. Busca en tu código setStatus y asegúrate de que la rama que toma el código 6 solo se ejecute después de que estés seguro de que la verificación ha tenido éxito.

Timeouts y disyuntores

SMS-Activate bajo carga a veces devolvía un 200 con un cuerpo vacío en lugar de un error HTTP. Los clientes defensivos envuelven la llamada en un tiempo de espera y tratan el cuerpo vacío como una señal de reintento. VerifySMS nunca devuelve un cuerpo vacío en la capa de compatibilidad. Si tu cliente aún trata el vacío como un reintento, quemará presupuesto en una red flaky porque el reintento golpeará un ID de alquiler diferente. El patrón más seguro es verificar los prefijos de respuesta conocidos (ACCESS_, STATUS_, BAD_) y tratar cualquier otra cosa como un fallo duro, no un fallo transitorio.

Los límites de velocidad se mueven de por clave a por IP

Los límites de velocidad de SMS-Activate estaban vinculados a la token de API. Los límites de velocidad de VerifySMS están vinculados a la combinación de la token de API y la dirección IP de origen, porque vemos mucho abuso de scripts de raspado que comparten una clave entre una botnet. Para el tráfico de producción normal de un solo servidor o un grupo equilibrado, esto es invisible. Si ejecutas trabajos de CI distribuidos que comparten una clave de prueba, puedes ver un 429 la primera vez que la flota se calienta junta. La solución es dejar que el canario se ejecute desde un nodo durante un día antes de expandirse.

El tiempo de reembolso parece instantáneo porque en realidad es instantáneo

Esto no es una trampa tanto como una sorpresa agradable. Donde los reembolsos de SMS-Activate tardaban unas horas en aparecer en tu saldo, los reembolsos de VerifySMS aparecen dentro de los 60 segundos. Si tu rastreador de costos lee el saldo en un horario, registrará el reembolso como un crédito que el sistema antiguo habría perdido. Los paneles de reconciliación a veces marcan esto como una anomalía en el primer día.

Parte 4: Verificación de la realidad de la comparación de precios

Antes del cierre, SMS-Activate era el piso del mercado. Los números rusos costaban entre $0.03 y $0.05 por verificación, y los compradores de gran volumen pagaban aún menos. Ese piso ha desaparecido. Aquí es donde se encuentran los proveedores restantes en abril de 2026 para los servicios más comunes, extraído de la página de precios pública de cada proveedor el :

Servicio5simTextVerifiedSMSPVASMS-MANVerifySMS
WhatsApp / Rusia$0.014$0.05$0.035$0.10
WhatsApp / EE. UU.$0.27$0.25$0.28$0.22$0.18
Telegram / Rusia$0.016$0.05$0.04$0.10
Telegram / EE. UU.$0.35$0.40$0.38$0.30$0.20
Google / Indonesia$0.07$0.08$0.06$0.10

El patrón es simple: 5sim y SMS-MAN ganan en precios rusos de bajo costo, TextVerified es la categoría premium de EE. UU. y VerifySMS se encuentra en el medio con una línea base de $0.10 para todo excepto los números de EE. UU. no VoIP más caros. Si su presupuesto estaba ajustado a los precios de piso de SMS-Activate, espere pagar dos a cinco veces más por verificación independientemente de qué reemplazo elija.

Dos notas sobre esta tabla. Primero, cada proveedor (incluido VerifySMS) aumenta y disminuye los precios de países individuales en respuesta a los costos de los operadores, por lo que confirme el precio actual en su propio panel de control antes de comprometerse con un presupuesto. Segundo, el precio efectivo por verificación exitosa depende de la relación de reembolso. Un proveedor con un precio de $0.08 y una tasa de éxito del 70% le cuesta más por éxito que un proveedor con un precio de $0.10 y reembolsos automáticos y una tasa de éxito del 90%.

Parte 5: Lista de verificación de migración de 10 pasos

Esta es la secuencia real que seguimos con nuestros propios usuarios en enero. Asume un solo desarrollador con acceso al repositorio, un servicio de producción y un entorno de pruebas. Escale los porcentajes de canario si está ejecutando varios servicios o un monorepo.

  1. Inventario de todos los sitios de llamada. Ejecute git grep -n 'sms-activate\.org\|handler_api\.php\|getNumber\|setStatus' y liste todos los archivos que golpean la API antigua. Si encuentra más de una docena, elija un módulo de envoltura y centralice las llamadas primero antes de migrar.
  2. Obtenga una clave de API de VerifySMS. Regístrese, agregue una pequeña cantidad de saldo y genere una clave con alcance para pruebas. Mantenga la clave de producción fuera del repositorio.
  3. Cambie la URL base. Reemplace el host de SMS-Activate con api.verifysms.app/compat/handler_api.php. No cambie la cadena de consulta. Confirme esto solo para que la diferencia sea limpia.
  4. Ejecute sus pruebas existentes. Si las pruebas golpean la API real, apúntalas a pruebas y observe las discrepancias de forma. Si simulan la API, ejecútelas contra el punto final de pruebas en vivo también para detectar la deriva del contrato.
  5. Reconfirme los ID de país. Examine su código en busca de constantes de país. Si está utilizando los ID numéricos heredados, todavía funcionan. Si tiene la oportunidad, reemplácelos con códigos ISO-3166 porque el próximo desarrollador que toque este archivo lo agradecerá.
  6. Conecte las reclamaciones de reembolso. Confirme que su ruta de tiempo de espera llama a setStatus con status=8. Sin esto, aún obtendrá reembolsos (los reembolsos automáticos de arrendamientos expirados), pero su rastreador de costos se retrasará con respecto a la realidad.
  7. Actualice su rastreador de costos. Lea el costo de la cabecera de respuesta X-VerifySMS-Cost en lugar de extraerlo de la tabla de precios. Este solo cambio hace que su panel de control financiero sea preciso al centavo.
  8. Monitoreo. Agregue alertas de tasa de éxito, latencia p95 y relación de reembolso contra su línea base existente. Elija umbrales que pueda defender, no aquellos que piense que serán "bien".
  9. Canario 5 por ciento durante 24 horas. Enrute una pequeña porción del tráfico de producción a través del punto final nuevo. Observe el panel de control, no solo las alertas.
  10. Corte el resto. Una vez que la ventana de canario esté limpia, mueva el 95 por ciento restante y deje el código de cliente antiguo comentado (no eliminado) durante un ciclo de liberación para tener una reversión rápida.

Elimine el código antiguo en la próxima liberación después de eso. No deje sitios de llamada muertos alrededor durante más de una semana porque la próxima persona que toque el módulo los pegará de nuevo en una nueva integración por accidente.

Preguntas frecuentes

¿La capa de compatibilidad de SMS-Activate es una API real o solo un stub?

Es un punto final real en api.verifysms.app/compat/handler_api.php que acepta cada acción importante desde la documentación pública de SMS-Activate: getBalance, getNumber, getStatus, setStatus, getPrices y getCountries. Las solicitudes se proxean a nuestra API nativa debajo del capó, por lo que obtiene precios de VerifySMS, cobertura y comportamiento de reembolso sin cambios de código en su lado.

¿Funcionará mi antigua clave de API?

No. Las claves de API de SMS-Activate dejaron de autenticar el día que el servicio cerró. Necesita una nueva clave de VerifySMS. Regístrese, agregue una pequeña cantidad de saldo y genere una clave desde el panel de control. El formato de la clave es idéntico en longitud para que pueda pegarla en la misma variable de entorno.

¿Cómo funcionan los reembolsos en comparación con SMS-Activate?

SMS-Activate requería que llamara a setStatus con código de estado 8 dentro de los 20 minutos para marcar un número como no utilizado, y los reembolsos se procesaban manualmente dentro de unas pocas horas. VerifySMS acepta la misma llamada a setStatus y reembolsa el monto total a su saldo dentro de los 60 segundos. Si olvida llamar a setStatus por completo, nuestro sistema aún reembolsa automáticamente cualquier número que nunca recibió un SMS después de que la ventana de arrendamiento expire.

¿Qué países están soportados?

VerifySMS cubre más de 200 países. Todos los países que ofrecía SMS-Activate están disponibles en VerifySMS, incluidos Rusia, Indonesia, Vietnam, Nigeria y EE. UU. Puede mantener su mapeo de ID de país existente o migrar a códigos alfa-2 de ISO-3166 cuando quiera.

¿Es el mismo precio?

No. Los precios de piso de $0.03 a $0.05 por verificación para números rusos de SMS-Activate han desaparecido del mercado abierto. Los precios actuales del mercado varían desde $0.10 para servicios comunes hasta $0.25 para números de EE. UU. no VoIP en plataformas más estrictas. VerifySMS cobra $0.10 como línea base y publica precios por país en el panel de control.

¿Necesito cambiar mi lógica de sondeo?

No. La llamada a getStatus devuelve STATUS_WAIT_CODE y STATUS_OK en el mismo formato que usaba SMS-Activate. Los intervalos de sondeo de 3 a 5 segundos aún funcionan. El único comportamiento nuevo es que VerifySMS también expone una URL de webhook en el panel de control, por lo que puede dejar de sondear por completo si prefiere un flujo impulsado por eventos.

¿Qué sucede si la capa de compatibilidad se deprecia alguna vez?

La capa de compatibilidad se considera una interfaz pública permanente. Si alguna vez cambiamos su comportamiento, publicaremos una ventana de deprecación mínima de seis meses con una nota de migración completa. La API JSON nativa de VerifySMS también está documentada, por lo que puede migrar fuera de la capa de compatibilidad a su propio ritmo cuando tenga sentido.

¿Cómo pruebo sin gastar dinero?

El panel de control de VerifySMS expone un modo de sandbox que devuelve números de teléfono simulados y códigos SMS enlatados sin debitar su saldo. Active la bandera de sandbox en el panel de control o envíe la cabecera X-Sandbox-Mode con cualquier solicitud para ejercitar sus rutas de código antes de salir en vivo.

¿Puedo migrar desde otros servicios también?

Sí. Esta guía de reproducción está escrita alrededor de la API de SMS-Activate porque ahí es donde vive la mayoría del código varado, pero la misma lista de verificación se aplica a migraciones desde 5sim, SMS-MAN o cualquier otro servicio compatible con handler_api. La capa de compatibilidad reconoce los parámetros de handler_api.php independientemente de qué servicio estaba llamando anteriormente.

¿Cuánto tiempo toma una migración real?

Para una integración de servicio único con unas pocas docenas de sitios de llamada, planee dos a cuatro horas de trabajo enfocado, más una ventana de canario de 24 horas antes de cortar el tráfico completo. Las migraciones de varios servicios más grandes con manejo de errores personalizado, análisis y reintentos pueden durar más, pero aún suelen terminar dentro de un solo día laboral.

¿Pierdo mis datos históricos?

La historia de verificación de SMS-Activate se desconectó cuando el servicio cerró y no es recuperable. VerifySMS mantiene un registro de auditoría completo de cada intento de verificación en su cuenta durante 12 meses, accesible desde el panel de control y a través de la extensión /compat/handler_api.php?action=getHistory.

¿Afecta esto mi postura de GDPR o cumplimiento?

VerifySMS está registrado en el Reino Unido y sigue el GDPR del Reino Unido. Publicamos nuestra política de retención de datos, subprocesadores y DPA en la página de privacidad. Si su configuración anterior requería un DPA con SMS-Activate, contáctenos y contrafirmaremos el mismo acuerdo dentro de un día hábil.

Próximos pasos

Si ha leído hasta aquí, ya tiene las piezas que necesita. Comience con el paso de inventario, obtenga el intercambio de URL base frente a un compañero para revisión y ejecute el canario durante la noche. La guía de reproducción es pequeña a propósito; la parte difícil es la disciplina de detenerse después de la ventana de canario en lugar de cortar todo en un solo compromiso.

Lectura relacionada en el resto del sitio:

¿Está listo para cortar la migración en una sola noche?

Crear una clave de API de VerifySMS →

Modo de sandbox incluido · Garantía de reembolso automático · 200+ países · Capa de compatibilidad de SMS-Activate en /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