Webhooks
Add a webhook URL to a run when your application prefers a callback over continuous polling. The stored run remains the source of truth; webhook delivery is best effort.
Request a webhook
Section titled “Request a webhook”const run = await magmell.runByName('reviewer', input, { webhookUrl: 'https://example.com/hooks/magmell',})The target must use HTTP or HTTPS and resolve only to publicly routable addresses. Redirects are not followed. Private, loopback, link-local, metadata, multicast, and other special-use targets are rejected.
Payload
Section titled “Payload”Magmell sends JSON after a run succeeds or fails:
{ "run_id": "8ebea6be-3b54-40ca-b8b5-5176264f2450", "deployment_id": "73aef731-3fd3-4fc1-a8cb-dadf00ddc1a0", "status": "succeeded", "result": { "summary": "..." }, "error": null, "finished_at": "2026-07-10T14:32:07.882Z"}The request includes:
Content-Type: application/jsonX-Siloga-Timestamp: 1783693927X-Siloga-Signature: sha256=<hex digest>Verify the signature
Section titled “Verify the signature”Compute HMAC-SHA256 over the timestamp, a period, and the exact raw request body:
import { createHmac, timingSafeEqual } from 'node:crypto'
function verify(body: Buffer, timestamp: string, received: string, secret: string) { const expected = 'sha256=' + createHmac('sha256', secret) .update(`${timestamp}.`) .update(body) .digest('hex')
const a = Buffer.from(expected) const b = Buffer.from(received) return a.length === b.length && timingSafeEqual(a, b)}Verify before parsing or acting on the body. Reject stale timestamps according to your application’s replay window.
Delivery behavior
Section titled “Delivery behavior”A 2xx response marks delivery successful. Network errors and other status codes are retried with
backoff, up to the environment’s configured attempt limit. The run records webhook status as
pending, delivered, or failed.
Make the receiver idempotent using run_id; retries can deliver the same completion more than once.