Trigger from a webhook
A webhook starts a run when another system sends a signed HTTP call. Create one with hook:create, and get a callback when runs end with notify:set.
1 · Create the webhook
hook:create needs the deployment id and the task to run, and its reply shows the secret once, so store it now.
$ ignitify hook:create dep_Hn4TqXw8Zc2P --task-name image-resize⚠️ The `secret` below is shown ONCE and cannot be read back — `hook:list` never returns it. Store it now; if it is lost, delete the hook and create a new one.A webhook body over 10 KiB is refused with 413 before the signature is checked.✓ Webhook Createdresource_id hok_Wd3Lm8Qz5RtYhook_id 4f1c9a7e2b6d03581a9c7e4d2f60b8315ce79a04d1b2863furl https://api.ignitify.dev/hooks/trigger/4f1c9a7e2b6d03581a9c7e4d2f60b8315ce79a04d1b2863fsecret (shown ONCE) 9d3f6a1c8e5b2074a6c91f3e8d0b5a72c4e61f98b3d7a05e2c4f1a86d09b37e
2 · Sign the body and send it
The signature is the HMAC-SHA256 of the exact body, in hex, with the secret as the key.
SECRET=9d3f6a1c8e5b2074a6c91f3e8d0b5a72c4e61f98b3d7a05e2c4f1a86d09b37e
HOOK_URL=https://api.ignitify.dev/hooks/trigger/4f1c9a7e2b6d03581a9c7e4d2f60b8315ce79a04d1b2863f
BODY='{"name":"world"}'
SIG=$(printf %s "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.* //')
# x-ignitify-delivery is optional: a repeated id returns the same run.
curl -X POST "$HOOK_URL" \
-H "content-type: application/json" \
-H "x-ignitify-signature: sha256=$SIG" \
-H "x-ignitify-delivery: order-1042" \
-d "$BODY"3 · Read the answer
A good request answers 202 and starts a run whose payload is the body text.
202 {"run_id":"019fdec4-2b71-7d90-a3c5-1e8f4b6a9d02","resource_id":"run_Qm3TbX8kLw2Z","status":"PENDING"}
401 {"error":"invalid signature"}
404 {"error":"unknown hook"}
413 {"error":"payload too large"}
429 {"error":"rate limited"}4 · List and delete webhooks
hook:list shows the webhooks of a deployment, and hook:delete removes one by its own hok_ id.
$ ignitify hook:list dep_Hn4TqXw8Zc2Pid 019f3c30-6e12-7b44-8a07-9c15d3e2f8a6resource_id hok_Wd3Lm8Qz5RtYhook_id 4f1c9a7e2b6d03581a9c7e4d2f60b8315ce79a04d1b2863ftask_name image-resizecreated_at 2026-10-14T09:40:00.000Z
5 · Get a callback when a run ends
notify:set takes an HTTPS URL and a signing secret of at least 32 characters, read from stdin. The URL is your own endpoint, and the server must be able to find its host name.
$ printf %s "$NOTIFY_SECRET" | ignitify notify:set dep_Hn4TqXw8Zc2P --url https://your-domain.example/ignitify --secret-stdinNotify URL for dep_Hn4TqXw8Zc2P set to https://your-domain.example/ignitify
6 · Check the callback signature
The callback is a POST with the same x-ignitify-signature header, so check it the same way.
import { createHmac, timingSafeEqual } from "node:crypto";
// Body: {"run_id":"run_Qm3TbX8kLw2Z","status":"COMPLETED","deployment_id":"…","tenant_id":"…"}
export function isFromIgnitify(rawBody: string, header: string, secret: string): boolean {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
const got = header.replace(/^sha256=/, "");
return got.length === expected.length && timingSafeEqual(Buffer.from(got), Buffer.from(expected));
}