sailing Foudra MRP
Referencia chevron_rightwebhooks/index

Webhooks

Cuando pasa algo en Foudra, puede avisar a otro sistema enviándole un mensaje: el centro de control se entera de que ha terminado la revisión de un barco, una tienda se entera de que ha cambiado el stock. Solo administradores. Para preguntar cosas a Foudra, o para cambiarlas, usa la API; los webhooks sirven para recibir avisos.

Crear uno

Campo Significado
Name (nombre) Qué hay al otro lado
URL Adónde enviar. Tiene que ser https y accesible desde internet. Una dirección dentro de una red privada se rechaza, salvo que quien gestione Foudra haya permitido ese host
Events (eventos) Qué eventos enviar

El signing secret (secreto de firma) se muestra una sola vez, en la página siguiente. Cópialo en ese momento: el receptor lo necesita para comprobar que un mensaje viene de Foudra.

Send test (enviar prueba) envía un evento ping. Switch off (desactivar) deja de enviar; los eventos que ocurren mientras un webhook está desactivado no se guardan para él. Remove (eliminar) lo borra y conserva su historial de entregas.

Eventos

Evento Cuándo data
work_order.completed Se ha hecho toda la cantidad de una orden de fabricación work_order (id, number, external_ref, quantity, quantity_done, due_at, notes) y part (id, part_number, name, is_stocked)
stock.changed Cualquier movimiento de stock. Un traslado son dos movement (id, type, quantity_delta, reference_type, reference_id, occurred_at), part, location, on_hand_here, on_hand_total
ping Send test {"hello": "world"}

El external_ref de una orden de fabricación es lo que permite al otro sistema saber de qué iba el trabajo. Crea una revisión con la referencia "Hull 207" y el evento de finalización lo dirá.

Qué se envía

Un POST con un cuerpo JSON:

{
  "id": 412,
  "type": "work_order.completed",
  "occurred_at": "2026-10-01T14:11:18Z",
  "text": "WO-00031 completed: 1 × Class 1 service (Hull 207).",
  "data": { "work_order": { "number": "WO-00031", "external_ref": "Hull 207" }, "part": { } }
}

text es una frase para una persona. Las cantidades son cadenas, como en la API.

Cabecera Significado
X-Foudra-Event El tipo de evento
X-Foudra-Event-Id El id del evento, el mismo que id en el cuerpo
X-Foudra-Delivery El id de esta entrega
X-Foudra-Signature t=<unix time>,v1=<signature>

Qué debe hacer el receptor

import hmac, hashlib, time

def verify(secret: str, header: str, body: bytes) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    signed = parts["t"].encode() + b"." + body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"]) and abs(time.time() - int(parts["t"])) < 300

Cuando falla

Una entrega fallida se reintenta al cabo de 1 minuto, luego de 5, 15, una hora, 3, 6 y 12 horas, y se abandona tras el octavo intento, aproximadamente un día después. Recent deliveries (entregas recientes) muestra cada una, cuántos intentos lleva y la última respuesta; Send now (enviar ahora) vuelve a intentar una en el acto.

Tras ocho fallos seguidos sin ningún éxito entre medias, el webhook se desactiva y aparece una tarea en el panel explicando el motivo. Arregla el receptor, vuelve a activar el webhook y usa Send now en todo lo que se haya abandonado.

Los eventos se envían más o menos en el orden en que ocurren, pero uno reintentado puede llegar después de otro posterior. Usa occurred_at si el orden importa.