Seguridad de la API
Qué hace We Are Transfers para que tu integración solo vea lo suyo, y qué te toca a ti.
Lo que hace la API
| Medida | Cómo |
|---|---|
| Aislamiento por organización | La clave resuelve la organización en el servidor y toda consulta lleva ese filtro. Ningún parámetro, cabecera, cuerpo ni cursor puede cambiarlo. Un id ajeno es 404, igual que uno inexistente. |
| Claves sin secreto guardado | Solo se guarda el hash SHA-256 de la clave y su prefijo. Ni We Are Transfers puede recuperar una clave: se rota. |
| Sin datos personales por defecto | El pasajero y el dinero van detrás de passengers:read y pricing:read. Las notas, el chat, el cartel y el GPS no están en v1. |
| Sin oráculo | Un 401 no distingue «no existe» de «hash incorrecto»; un 404 no distingue «ajeno» de «inexistente». Solo se dice lo que un consumidor legítimo necesita (revocada, caducada, entorno). |
| Límites y fuerza bruta | Cubos por clave, organización y endpoint; y 60 fallos de autenticación por minuto y por IP antes de mirar la clave. |
| Webhooks firmados | HMAC-SHA256 sobre timestamp + cuerpo, con un secreto por endpoint que se enseña una vez y se guarda cifrado (AES-256-GCM). |
| Webhooks sin SSRF | Solo https y puerto 443, sin credenciales en la URL, sin nombres locales, y todas las IPs a las que resuelve deben ser públicas (v4 y v6). Se comprueba al crear y antes de cada entrega. No se siguen redirecciones. |
| Cuerpo acotado | 256 KB y solo application/json. |
| Cursor firmado | Un cursor manipulado se rechaza (400 invalid_cursor), no se interpreta. |
| Idempotencia | Idempotency-Key en las escrituras: misma clave + mismo cuerpo = misma respuesta; cuerpo distinto = 409. |
Qué se registra y qué no
Por cada petición queda: ruta (como patrón, sin ids), método, estado, latencia, código de error, si se limitó, un hash corto de la IP y el X-WAT-Request-Id. Se conserva 30 días. Nunca se registran cabeceras, cuerpos, parámetros ni la clave. Por cada entrega de webhook queda el estado HTTP, la duración, el error y un extracto de 300 caracteres de tu respuesta (sin saltos de línea).
Lo que te toca a ti
- Guarda la clave y el secreto del webhook en un gestor de secretos. No en el repositorio, no en el navegador, no en un log.
- Verifica la firma de cada webhook con comparación en tiempo constante y rechaza los que lleguen con más de 5 minutos de antigüedad. Cómo.
- Deduplica por
X-WAT-Event-Id. Un evento puede llegar más de una vez. - Trata el
request_idcomo parte de tu log. Sin él, soporte no puede encontrar tu petición. - Pide los scopes mínimos. Si tu integración no factura, no pidas
pricing:read. - Rota si dudas. Una rotación cuesta un despliegue; una filtración cuesta más.
Reportar una vulnerabilidad
Si encuentras un problema de seguridad en la API, escríbenos antes de publicarlo. El contacto está en la página Legal.