we post to your url
new card? status change? pro can now POST a signed json payload to your endpoint. hmac. retries. no slack-or-nothing.
slack is a chat. your product is a stack.
a new card used to die in a channel. a status change used to die in a channel. if you wanted it in linear, or a queue, or your own laravel app, you copy-pasted.
so i shipped a signed POST to your url.
what we send
pro. one url per project. you pick the events:
post.created— someone submitted a card (board, widget, mcp, same hook)post.status_changed— it moved.fromandtoare in the body
plus webhook.ping when you hit send test. ping is not a subscription. it just proves the wire.
the body looks like this:
{
"id": "delivery-uuid",
"event": "post.created",
"created_at": "2026-08-13T12:00:00+00:00",
"project": { "id": 1, "slug": "acme", "name": "acme" },
"data": {
"id": 42,
"title": "dark mode",
"status": "pending",
"url": "https://usehoot.app/projects/acme/board?post=42"
}
}
headers: X-Hoot-Event, X-Hoot-Delivery, X-Hoot-Signature. user-agent Hoot-Webhook/1.0.
queued. 3 tries. backoff 1s, 5s, 10s. we give your endpoint five seconds. then we stop.
how you know it's us
the secret starts with hoot_whsec_. we show it once. encrypted after that.
sign this string:
{unix timestamp}.{raw json body}
hmac-sha256. hex.
the header is:
X-Hoot-Signature: t=1710000000,v1=…
check it with hash_equals. reject a stale t. do not parse the json first — sign the raw body.
[$t, $v1] = /* parse t= and v1= */;
$expected = hash_hmac('sha256', $t.'.'.$raw, $secret);
hash_equals($v1, $expected);
that's the whole contract.
why not just slack
slack is fine. telegram is fine.
they are not your backend.
votes still measure demand. you still decide what ships. the webhook just means hoot can talk to the thing you already run, without us pretending a chat app is an api.
where it lives
project → notifications → outgoing webhook.
paste the url. pick the events. copy the secret. send a ping.
if you're on starter: that's a pro wall. upgrade, or stay on email.
if you're already on pro: turn it on. then go write the six lines above.
if you're not on hoot: usehoot.app
ask. ship. tell your backend. 🦉