Team webhooks
Send events from your own systems to a team: a signed webhook URL per sender, how to sign a delivery, and what kanman does with it.
A team webhook lets another system tell kanman that something happened: a monitoring alert, a failed release, a form a customer filled in, a message from your own tooling. You give each sender its own URL and secret. kanman reads what arrives, decides what it means for the team and acts on it like on any other request: it may write a story, add to one that exists, ask someone, or let it go.
What a delivery says is never taken as an instruction. kanman treats it as information from outside the team.
To start work from a script instead, with a known title and description, use the story endpoints of the REST API.
Create a webhook
You need to be an owner or admin of the workspace.
- Open the team, then Team > API and webhooks (
/<workspace>/teams/<team>/team/api). - Click Add webhook, give it the name of the sender, for example “Grafana” or “Release pipeline”, and click Create.
- Copy the Webhook URL and the Signing secret. The secret is shown once. kanman stores it encrypted and never shows it again.
New secret replaces the secret: the old one stops working at once, the URL stays. Revoke turns the webhook off for good; its URL answers 410 from then on.
Members of the workspace see the webhooks and their recent deliveries, but cannot change them.
Sign a delivery
Send a POST to the webhook URL with these three headers:
| Header | Value |
|---|---|
X-Kanman-Timestamp |
The current time in Unix seconds. |
X-Kanman-Nonce |
A value you use once, 8 to 128 letters, digits, ., :, - or _, for example a UUID. |
X-Kanman-Signature |
sha256= followed by the hex HMAC-SHA256 of <timestamp>.<nonce>.<body>, keyed with the signing secret. |
The body can be any text up to 256 KB; JSON works best. kanman reads up to 8,000 characters of it.
SECRET="kmw_..." # the signing secret
URL="https://api.kanman.ai/functions/v1/team-webhook/..."
BODY='{"alert":"Checkout error rate above 5%","service":"checkout","since":"2026-10-19T09:12:00Z"}'
TS=$(date +%s)
NONCE=$(uuidgen)
SIG=$(printf '%s.%s.%s' "$TS" "$NONCE" "$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')
curl "$URL" \
--header "Content-Type: application/json" \
--header "X-Kanman-Timestamp: $TS" \
--header "X-Kanman-Nonce: $NONCE" \
--header "X-Kanman-Signature: sha256=$SIG" \
--data "$BODY"
Answers
| Status | outcome |
Meaning |
|---|---|---|
202 |
accepted |
kanman has the delivery and will look at it. |
400 |
invalid |
A header is missing or malformed. |
401 |
bad_signature |
The signature does not match the body, nonce and timestamp. |
401 |
stale |
The timestamp is more than five minutes away from kanman’s clock. |
409 |
replay |
This nonce was used already. Send a new nonce with every delivery. |
409 |
not_on_kanman |
kanman does not run this team yet. |
413 |
too_large |
The body is larger than 256 KB. |
429 |
rate_limited |
More than 30 deliveries in a minute. Wait for the seconds in Retry-After. |
404, 410 |
The URL is unknown, or the webhook was revoked. |
Every answer is JSON with the delivery’s id: { "delivery": "…", "outcome": "accepted" }. The webhook’s card in Team > API and webhooks lists its last five deliveries with their outcome.
Last updated: January 1, 0001
Open kanman