Skip to content

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.

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.

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/json
X-Siloga-Timestamp: 1783693927
X-Siloga-Signature: sha256=<hex digest>

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.

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.