Elegir un idioma

Webhooks

Recibe en tu servidor los eventos de activación en tiempo real, verifica la cabecera SmsGrab-Signature y entiende los reintentos, los envíos de prueba y la desactivación automática.

En esta página
  1. Eventos
  2. Crear un webhook
  3. Cómo es un envío
  4. Verifica la firma
  5. Responde rápido
  6. Reintentos
  7. Desactivación automática
  8. Probar y reenviar

Los webhooks envían eventos a tu servidor en el momento en que ocurren, para que no tengas que consultar sin parar. Un webhook pertenece a una clave de API. Recibe los eventos de los números comprados con esa clave y los avisos de saldo bajo de tu cuenta.

Eventos

Evento Cuándo
activation.created Se compró un número
activation.code_received Con cada SMS nuevo, incluyendo todos los mensajes anteriores
activation.completed Terminado por ti, o se acabó el tiempo después de un código
activation.cancelled Cancelado antes de un código, reembolsado
activation.expired Ningún código a tiempo, reembolsado
activation.refunded Cualquier reembolso del cargo
balance.low Tu saldo bajó del umbral que fijaste
webhook.test Un envío de prueba que iniciaste tú

Crear un webhook

En Cuenta > Desarrolladores, abre una clave y añade un webhook con su URL, los eventos que quieres y una descripción opcional. Cada clave puede tener hasta 3 webhooks.

La URL debe:

  • empezar por https://;
  • usar un nombre de host, no una dirección IP;
  • apuntar a una dirección pública. Se rechazan redes privadas, localhost y rangos similares.

Recibes un secreto de firma que empieza por whsec_. Igual que una clave de API, solo se muestra una vez. Más adelante puedes renovarlo, lo que también te pide la contraseña.

Cómo es un envío

HTTP
POST /your/endpoint HTTP/1.1
Content-Type: application/json
User-Agent: SmsGrab-Webhooks/1.0
SmsGrab-Event: activation.code_received
SmsGrab-Delivery: 9f7d6c1e-2b44-4c1a-8f0e-6a3d2c1b0e9f
SmsGrab-Signature: t=1790503200,v1=3b9a0c…

{ "id": "evt_4e1f…", "type": "activation.code_received", "created_at": "2026-09-27T10:06:12.004Z",
  "api_version": "2026-09-27", "data": { "activation": { "id": "5c1d0c2e-…", "status": "CODE_RECEIVED" } } }

Verifica la firma

SmsGrab-Signature contiene una marca de tiempo t y v1, el HMAC-SHA256 de t, un punto y el cuerpo original de la petición, calculado con tu secreto. Rechaza los envíos cuya marca de tiempo se aleje más de 300 segundos de tu reloj y compara las firmas en tiempo constante.

PHP
[$t, $v1] = (function (string $h): array {
    parse_str(str_replace(',', '&', $h), $p);
    return [(int) ($p['t'] ?? 0), (string) ($p['v1'] ?? '')];
})($_SERVER['HTTP_SMSGRAB_SIGNATURE'] ?? '');
$body = file_get_contents('php://input');
$expected = hash_hmac('sha256', $t.'.'.$body, getenv('SMSGRAB_WEBHOOK_SECRET'));
$ok = abs(time() - $t) <= 300 && hash_equals($expected, $v1);
Python
import hmac, hashlib, time

def verify(header: str, body: bytes, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    expected = hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).hexdigest()
    return abs(time.time() - t) <= 300 and hmac.compare_digest(expected, parts.get("v1", ""))
JavaScript
import crypto from 'node:crypto';

export function verify(header, rawBody, secret) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const t = Number(parts.t ?? 0);
  const expected = crypto.createHmac('sha256', secret).update(`${t}.`).update(rawBody).digest('hex');
  const given = Buffer.from(parts.v1 ?? '', 'utf8');
  return Math.abs(Date.now() / 1000 - t) <= 300 && given.length === expected.length
    && crypto.timingSafeEqual(Buffer.from(expected, 'utf8'), given);
}

Verifica siempre el cuerpo exactamente como lo recibiste, antes de interpretar el JSON.

Responde rápido

Responde con cualquier estado 2xx en menos de 10 segundos y haz el trabajo lento después, por ejemplo en una cola. Las redirecciones no se siguen.

Reintentos

Un envío fallido se reintenta a los 1 minuto, 5 minutos, 15 minutos, 1 hora, 3 horas, 6 horas, 12 horas y 24 horas. Un reintento repite el mismo id de evento, así que guarda los identificadores que ya procesaste y descarta los duplicados. Los eventos de una misma activación llegan en orden.

Desactivación automática

  • Responder 410 Gone desactiva el webhook al instante.
  • Tras 50 intentos fallidos seguidos durante al menos 24 horas, el webhook se desactiva y recibes una notificación. Corrige tu endpoint y vuelve a activarlo.
  • Revocar una clave desactiva sus webhooks.

Probar y reenviar

Envía un evento webhook.test desde la página del webhook para ver al momento el código de estado, el tiempo de respuesta y cualquier error. La lista de envíos guarda cada envío durante 30 días y puedes reenviar cualquiera.

¿Te ha resultado útil este artículo?

¿Sigues necesitando ayuda?

Escríbenos. Respondemos a todos los mensajes, normalmente en pocas horas.

O escríbenos a support@smsgrab.com