Webhooks
Recibe en tu servidor los eventos de tu negocio, firmados, con reintentos y un registro para reconciliar.
Con los webhooks, Posdata le avisa a tu servidor cuando pasa algo en tu negocio (una venta completada, una factura emitida, un cierre de caja) en vez de que tú consultes la API a cada rato. Están incluidos en el plan Pro (con o sin facturación electrónica), igual que la API.
Crear un endpoint
Los endpoints se crean y administran solo en cuenta.posdata.so → Desarrolladores → Webhooks; no hay endpoints de la API para gestionarlos. Así, una API key filtrada nunca puede desviar tus eventos a otro servidor.
- Elige agregar endpoint, escribe la URL de tu servidor y marca los eventos que quieres recibir.
- Confirma con el código de 6 dígitos que llega al correo de la cuenta. La cuenta recibe además un correo de aviso de seguridad (también cuando se cambia la URL de un endpoint).
- Copia el secreto del endpoint (empieza por
whsec_). Solo se muestra una vez. Lo necesitas para verificar las firmas. - Usa Enviar evento de prueba para comprobar que tu servidor recibe y verifica bien.
Reglas de la URL:
- Solo
https://y el puerto 443 (el estándar). No se permiten otros puertos nihttp://. - Un nombre de dominio público (no una dirección IP, ni
localhost, ni dominios internos como.local). - Sin usuario ni contraseña en la URL y sin fragmento (
#…). - No se siguen redirecciones: una respuesta 3xx cuenta como entrega fallida.
Una cuenta puede tener hasta 5 endpoints. Desde cuenta también puedes pausarlos y reanudarlos, editarlos, eliminarlos y ver el historial de entregas de cada uno.
Tipos de evento
Cosas que conviene saber:
-
Una sola vez por objeto significa que, aunque una caja reintente subir la misma venta (lo hace si se le corta la conexión), el evento se registra una vez. Los
*.updatedsí pueden llegar varias veces para el mismo objeto, incluso sin cambios visibles: trátalos como «vuelve a leer este objeto». -
Los eventos de ventas, clientes, productos, movimientos, conteos y turnos que nacen en una caja se generan cuando esa caja sincroniza. Una caja sin internet produce sus eventos al reconectarse.
-
No hay un evento por cada cambio de stock, y los cambios de stock que Posdata aplica en la nube no emiten
product.updated. Para seguir el stock usainventory.movement.createdoGET /inventory/levels?updated_since=…(Cómo funciona el stock). -
invoice.issuedeinvoice.rejectedpueden tardar unos segundos más que el resto: el veredicto de la DIAN se revisa periódicamente. -
Una misma venta puede producir varios eventos (
sale.createdysale.completed, por ejemplo). El orden de entrega no está garantizado: usacreated_atdel evento y el estado del objeto, no el orden de llegada. -
Las eliminaciones y las categorías no producen eventos en esta versión.
Qué recibe tu servidor
Un POST con Content-Type: application/json y este cuerpo:
id: el id del evento. Es el mismo si el evento se reintenta: úsalo para no procesarlo dos veces.data.object: el objeto tal como lo devuelve la API (GET /sales/{id},GET /products/{id}…) en el momento del evento. En el ejemplo está recortado; los objetos completos están en la referencia.api_version: la versión del formato del evento. Hoy es2026-09-28.
Y estos headers:
Verifica la firma
Cualquiera que conozca tu URL puede enviarle peticiones. Verifica cada entrega antes de confiar en ella:
- Lee el header
Posdata-Signature. Tiene la format=1790608000,v1=de13e2…y, durante una rotación del secreto, dos valoresv1. - Descarta la entrega si
t(segundos Unix) está a más de 5 minutos de tu hora actual: eso impide que alguien reenvíe una entrega vieja que haya capturado. - Calcula
HMAC-SHA256con tu secreto (completo, incluido el prefijowhsec_) sobre el texto`${t}.${cuerpo}`, dondecuerposon los bytes exactos que recibiste, y pásalo a hexadecimal en minúsculas. - Acepta la entrega si cualquiera de los
v1coincide, comparando en tiempo constante.
La firma se calcula sobre los bytes exactos del cuerpo. Si tu framework ya convirtió el JSON en un objeto y
lo vuelves a serializar, los espacios o el orden pueden cambiar y la firma no coincidirá. Lee el cuerpo
sin procesar (express.raw, request.get_data(), php://input).
Uso con Express:
Con Flask, por ejemplo: verify_posdata_signature(request.headers.get("Posdata-Signature"), request.get_data(), secret).
Estos ejemplos se prueban automáticamente contra firmas generadas por el mismo código que usa Posdata para enviar los webhooks.
Responde rápido y procesa después
- Responde con un 2xx en menos de 10 segundos. Pasado ese tiempo, la entrega cuenta como fallida.
- Cualquier código que no sea 2xx (incluidos los 3xx) cuenta como fallo. Posdata no guarda el cuerpo de tu respuesta.
- Haz el trabajo pesado después de responder: guarda el evento en una cola o una tabla y procésalo aparte.
- Deduplica por
iddel evento. Un reintento, o un evento que también recuperaste conGET /events, llega con el mismoid.
Reintentos
Si una entrega falla, Posdata la reintenta con esta espera entre intentos:
Son 8 intentos en unas 28 horas. Si el octavo falla, esa entrega queda como fallida y no se reintenta
más; puedes recuperar el evento con GET /events.
Cada endpoint tiene su propio turno: uno que falla o responde lento no retrasa las entregas a tus otros endpoints.
Desactivación automática
Si un endpoint acumula 20 fallos seguidos durante más de 24 horas, Posdata lo desactiva, deja de
intentar sus entregas pendientes y envía un correo a la cuenta. Cuando arregles tu servidor, reactívalo
desde cuenta (puedes usar Enviar evento de prueba antes, también con el endpoint desactivado). Los
eventos de mientras estuvo desactivado no se reenvían solos: recupéralos con GET /events.
Si la cuenta deja de tener el plan Pro, las entregas pendientes se descartan sin reintentos, y los eventos que ocurran mientras no tenga Pro no se registran.
Reconcilia con GET /events
Todo evento (salvo webhook.test) queda en un registro que puedes consultar con la API durante 30 días,
aunque no tengas endpoints configurados (necesitas el permiso events:read):
Cada evento trae el mismo id, type, created_at y data.object que la entrega del webhook. Un buen
patrón: procesa los webhooks en tiempo real y, una vez al día, recorre GET /events del último día
procesando los id que no tengas.
Rotar el secreto
Desde cuenta, Rotar secreto (con el código por correo) genera un secreto nuevo que se muestra una sola
vez. Durante las 24 horas siguientes, cada entrega trae dos firmas v1: la del secreto nuevo primero
y la del anterior después. Como tu verificación acepta cualquiera de las dos, puedes desplegar el secreto
nuevo con calma. Pasadas las 24 horas, solo se firma con el nuevo.