Docs / Reference
Webhooks
Have Sokie POST to your own systems when a deploy goes live or fails, a server takes its first call, or usage passes your alert.
A webhook tells your own systems when something happens to your servers: a deploy goes live or fails, a server takes its first call, usage passes your alert. Sokie sends a signed POST to an https address of yours each time, and tries again if it's down.
Add one
In Settings, under Workspace, open Webhooks and choose Add a webhook. Give the endpoint's https address and pick its events. Sokie shows the webhook's signing secret once, as whsec_…: save it with the endpoint's other secrets, since it's how the endpoint knows a delivery came from Sokie. Send a test sends a ping to check the endpoint before a real event does.
A workspace can have 5 webhooks. Their addresses must be https, and never one inside a network: Sokie checks what the name resolves to when you add it and before each delivery, and doesn't follow redirects.
Events
deploy.live: a production deploy went live.datahasserveranddeploy(id,number,tools,source).deploy.failed: a production deploy failed or timed out.deployalso haserror, with acodeand amessage.server.first_call: a server took its first tool call from a client other than Sokie's own.datahasserver,at,clientandtool.usage.alert: the month's tool calls passed the alert threshold set on Billing.datahasmonthandtoolCalls, the threshold that was passed.usage.stopped: tool calls stopped for the month, at the plan's limit or your cap. Samedata.upstream.sign_in_broken: a server's shared sign-in to its API was refused, and someone needs to sign in again.datahasserver.ping: the test Send a test sends.
Pull request previews don't send deploy events; their pull request already shows how they went.
What a delivery looks like
The body is JSON:
{
"id": "k57a3m9c2x8w1q0e5r4t6y7u8i9o0p1a",
"type": "deploy.failed",
"createdAt": "2026-10-22T09:14:03.120Z",
"workspaceId": "j97b2n8d3y7v2p1f6s5u7z8w9j0k1l2m",
"data": {
"server": {
"id": "js7by1shfy4gy7ne49sqcx4he98gk6gh",
"name": "Tasks",
"slug": "patient-tiger-637",
"url": "https://patient-tiger-637.sokie.cloud/mcp"
},
"deploy": {
"id": "kd7c4p1v9b2n8m3x6z5a4s3d2f1g0h9j",
"number": 12,
"error": { "code": "MISSING_SECRETS", "message": "The server uses TASKS_TOKEN, which isn't set." },
"source": "git"
}
}
}With it come these headers:
x-sokie-event: the event, as intype.x-sokie-delivery: the delivery's id, the same on every retry of it, so your endpoint can ignore one it has already handled.x-sokie-signature:t=<seconds>,v1=<hex>, described next.
Check the signature
v1 is an HMAC-SHA256, in hex, of the timestamp, a dot and the body exactly as it arrived, keyed with the webhook's secret. Compute it yourself, compare in constant time, and refuse a timestamp more than five minutes old, so a captured delivery can't be replayed later. In Node or Bun:
import { createHmac, timingSafeEqual } from "node:crypto";
export function fromSokie(body: string, header: string, secret: string): boolean {
const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
const timestamp = Number(parts.t);
if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
const expected = createHmac("sha256", secret).update(`${timestamp}.${body}`).digest("hex");
const given = Buffer.from(parts.v1 ?? "", "hex");
return given.length === 32 && timingSafeEqual(given, Buffer.from(expected, "hex"));
}Read the body as text before parsing it: parsing and printing JSON again can change its bytes, and then the signature won't match.
Answers and retries
Answer with any 2xx within 10 seconds, and do the work afterwards. A timeout, a failure to connect, a 5xx, a 408 or a 429 is tried again a minute, 5 minutes and 30 minutes later; any other answer fails the delivery for good. Each webhook's row in Settings shows how its latest delivery went, and Recent deliveries lists the last week's, with the status your endpoint answered. Sokie never keeps what your endpoint answered beyond its status.
Removing a webhook stops its deliveries, including ones waiting for a retry.