Seguridad de Endpoints
Vincent Depassier · 30 de agosto de 2026
Un endpoint es una URL pública sin API key adelante. Cualquiera que averigüe la dirección puede hacerle POST. Esta página es sobre asegurarte de que solo quien vos quisiste pueda hacer que algo pase.
Por dónde pasa un request
En orden, y cada paso lo puede detener:
Llega el POST
│
├─ ¿el endpoint existe y está Activo? no → 404
├─ ¿origen permitido, si hay reglas? no → 403
├─ ¿cuerpo dentro del límite del plan? no → 413
├─ ¿firma válida, si está configurada? no → 401
│
▼
se guarda el evento, después corre la automatizaciónDos cosas del orden. La verificación de origen ocurre antes de leer el cuerpo, así que un origen rechazado no cuesta nada. Y el evento se guarda después de validar, así que tu historial de eventos es una lista de requests legítimos — una avalancha de llamadas falsificadas no lo llena.
Verificación de firma
La autenticación real. Quien manda calcula un HMAC del cuerpo con un secreto que ambos tienen, lo pone en un header, y el gateway lo recalcula y compara.
Configurás tres cosas:
Ajuste | Ejemplo |
Nombre del header |
|
Algoritmo |
|
Secreto | El secreto compartido, guardado cifrado |
El secreto no se vuelve a mostrar después de definirlo, y se puede regenerar desde el menú del endpoint — que es además cómo se rota.
Dos formatos, porque la industria tiene dos
Default — firma el cuerpo crudo. El header lleva el digest en hex, opcionalmente con prefijo sha256= o sha512=. Es lo que hacen GitHub y la mayoría de los webhooks genéricos.
X-Hub-Signature-256: sha256=7d38cdd689735b008b3c702edd92eea23791c5f6Timestamp-punto-payload — firma "{timestamp}.{cuerpo}", y el header lleva ambos:
Stripe-Signature: t=1614556823,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bdEs la forma de Stripe y Slack. Elegí la que documente quien te manda; equivocarse produce un desajuste de firma que se ve exactamente igual que un secreto equivocado.
La comparación es de tiempo constante, así que una firma incorrecta no revela cuán incorrecta era.
`None` significa que cualquiera lo puede llamar. Un endpoint sin firma configurada acepta cualquier POST de cualquiera que sepa la URL. A veces es justo lo que querés — un formulario de contacto público cuya automatización solo inserta una fila — pero debería ser una decisión, no un descuido. Si la automatización escribe algo que importa, o cuesta plata correrla, configurá una firma.
El handshake de challenge
Algunos servicios verifican que la URL es tuya antes de mandarte nada. Las plataformas de Meta hacen esto: te hacen GET con hub.mode, hub.verify_token y hub.challenge, y esperan que devuelvas el challenge como texto plano.
Definí un verify token en el endpoint y el gateway responde ese handshake por vos:
GET /{workspaceId}/endpoint/{endpointId}?hub.mode=subscribe
&hub.verify_token=tu-token
&hub.challenge=1158201444
→ 200 1158201444Un token que no coincide responde 403, y también lo hace un GET a un endpoint sin verify token configurado — el handshake está apagado salvo que lo enciendas.
Reglas de origen
Una regla de origen restringe desde qué sitios web puede llamarse un endpoint. Importa para una forma puntual: un endpoint Sync llamado por JavaScript de tu propio sitio.
Patrón | Coincide con |
| exactamente ese origen |
| cualquier subdominio de |
| desarrollo local |
Un endpoint sin reglas de origen acepta todos los orígenes. Es el único lugar del gateway que falla abierto en vez de cerrado, y la razón es que la mayoría de los endpoints los llaman servidores, que no mandan header Origin — negar por defecto habría roto todos los webhooks el día que existió la funcionalidad.
De ahí la limitación que conviene decir sin vueltas: las reglas de origen son un control de navegador, no una frontera de seguridad. El header Origin lo pone el navegador y cualquier cosa que no sea un navegador puede omitirlo o falsificarlo. Evitan que tu endpoint sea llamado desde la página web de otro; no evitan que lo llame un curl. Para eso está la firma.
Los orígenes se validan al guardarlos, tienen un tope de cantidad según tu plan, y se de-duplican.
La otra lista de orígenes
Las credenciales tienen su propia lista, separada:
Lista | Restringe |
Orígenes del endpoint | qué sitios pueden hacerle POST a ese endpoint |
Orígenes de la credencial | qué sitios pueden usar esa API key |
Se configuran en lugares distintos y ninguna implica la otra. La de credencial es la que usás para atar una key pk_live_ a tu propio dominio, para que una copia sacada de tu bundle no funcione desde la página de otro. Aplica la misma advertencia: restringe navegadores, no servidores.
Recomendaciones prácticas
Configurá siempre una firma en un endpoint cuya automatización escriba. La URL va a terminar en un log, un archivo de configuración o un ticket de soporte tarde o temprano.
Rotá regenerando el secreto y después actualizá a quien manda. Hay una ventana entre ambos pasos donde las llamadas fallan — hacelo cuando unos minutos de reintentos sean aceptables, que para la mayoría de los emisores lo son.
Usá reglas de origen en endpoints Sync que llame tu sitio, y no dependas de ellas para nada más.
Desactivá en vez de eliminar un endpoint que retirás, así sobrevive el historial de eventos.
Mirá la lista de eventos primero cuando algo se rompe. Distingue "nunca llegó" de "llegó y falló", y esas dos cosas tienen causas completamente distintas.
Siguiente
Endpoints — modos, el nodo Response, timeouts y caché.
Credenciales y Principales — dónde viven las reglas de origen de credencial.