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
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
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.
[$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);
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", ""))
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 Gonedesactiva 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?
¡Gracias! Nos alegra que te haya ayudado.