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.

  1. Open the team, then Team > API and webhooks (/<workspace>/teams/<team>/team/api).
  2. Click Add webhook, give it the name of the sender, for example “Grafana” or “Release pipeline”, and click Create.
  3. 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