Ir al contenido

Buenas prácticas

Una recepción de webhooks bien armada aguanta tres cosas que van a pasar: que la misma entrega llegue dos veces, que los eventos lleguen fuera de orden y que su servidor quede fuera de línea por un tiempo.

El intento tiene 15 segundos. Pasado eso, cuenta como falla y el evento vuelve después, aunque su sistema haya terminado el trabajo.

Entonces, en la recepción, haga solo lo mínimo:

  1. verifique la firma;
  2. guarde el evento (en una cola, en una tabla);
  3. responda 200.

El trabajo de verdad (actualizar el ERP, enviar un correo, llamar a otro sistema) corre después, fuera de la solicitud.

La misma entrega puede llegar más de una vez: su respuesta se perdió en la red, pasó de los 15 segundos, o alguien hizo el reenvío manual. En todos esos casos el webhook-id (y el id del cuerpo) es el mismo.

Guarde el webhook-id de cada evento que procesó y, antes de procesar, verifique si ya está ahí. Si está, responda 200 y no haga nada. Una restricción de unicidad en la base de datos resuelve esto sin carrera entre dos recepciones simultáneas.

Los eventos no llegan necesariamente en el orden en que ocurrieron. Una entrega que falló vuelve minutos u horas después, cuando otras del mismo registro ya llegaron; hasta 5 entregas del mismo endpoint pueden estar en curso al mismo tiempo; y dos eventos de la misma escritura no tienen orden entre sí.

Para decidir cuál información es la más nueva:

  • compare el timestamp del cuerpo, que es el horario en que ocurrió el evento (no el webhook-timestamp del encabezado, que es el horario del envío);
  • o compare el updated_at del objeto con lo que usted ya tiene guardado.

Si el evento que llegó es más viejo que lo que usted ya tiene, ignore sus datos. Un client.updated que llega después de un client.deleted del mismo cliente, por ejemplo, es de antes de la eliminación.

Cuando llegue object_truncated, busque el objeto

Sección titulada «Cuando llegue object_truncated, busque el objeto»

Con data.object_truncated: true, el objeto llegó solo con object e id: o porque pasaba de 256 KB, o porque la escritura vino de un camino que envía el evento resumido (WhatsApp, automatizaciones, Open Finance, rutinas automáticas). Busque el objeto por la API, con el GET del recurso. Llega como está ahora.

Buscar por la API también es lo correcto cuando el objeto es grande o cambia mucho: trate el evento como un aviso de “este registro cambió” y lea el estado actual.

Algunos cambios no generan evento (vea Lo que no genera evento), un endpoint desactivado no guarda lo que se perdió, y su servidor puede quedar fuera de línea más tiempo que los 3 días de reintentos. Para el dato que tiene que estar exacto:

  • ejecute cada tanto una sincronización con updated_after, que trae lo que cambió desde la última vez, en el orden en que cambió. Vea Paginación;
  • después de una caída de su lado, use GET /public/v1/events para ver lo que pasó en los últimos 30 días, y el reenvío manual para las entregas que fallaron.
  • Verifique la firma en cada entrega, y rechace una marca de tiempo con más de 5 minutos de diferencia.
  • Guarde el secreto como guarda una contraseña: fuera del código, fuera del repositorio, fuera de los logs.
  • No devuelva datos sensibles en el cuerpo de la respuesta: hasta 2 KB de él quedan en el registro de entregas, que el dueño y los administradores leen.
  • Rote el secreto cuando alguien que lo conocía se va, o cuando pasó por un lugar que usted no controla. Vea Rotar el secreto.