Outbound webhooks Max
Send HTTPS POST requests to your own endpoints when cards change or comments are added. Webhooks are configured per board under board settings.
Overview
Each webhook has a URL, a list of subscribed events, and either a simple checkbox-driven JSON body or an advanced template you define. Deliveries appear in the board's recent delivery log; failed requests are not retried automatically.
Availability
Outbound webhooks are included on the Max plan only.
Simple vs advanced payload
Simple mode builds a standard envelope: version, event, occurred_at, and optional sections (board, list, card, labels, assignees, and so on) according to the toggles you enable.
Advanced mode lets you supply a JSON template. Tokens look like {card_title} and must sit where a JSON value is valid, for example "title": {card_title}, not inside a JSON string. Each token is replaced with the correct JSON (string, number, object, array, or null), then the result is parsed. Invalid JSON after substitution falls back to the simple envelope for that delivery (and a warning is logged).
In advanced mode, the same toggles as Simple still control which data is resolved: if you disable labels, {labels} will be an empty array.
Request format and signing
Every delivery is an HTTP POST with Content-Type: application/json and a JSON body (either the simple envelope or your advanced template result).
X-Saku-Eventholds the event name (e.g.card.created).X-Saku-Deliveryholds a unique id for that attempt.X-Saku-Signaturewhen a signing secret is set containssha256=<hex>, HMAC-SHA256 over the raw request body.
Template variables
Names are case-insensitive. Dots in a token are treated like underscores (e.g. {board.name} → board_name). Common aliases include {cardtitle} for {card_title}.
| Placeholder | Meaning |
|---|---|
| {version} | Payload schema version (currently 2) |
| {event} | Event id (e.g. card.created) |
| {occurred_at} | ISO-8601 timestamp when the webhook was sent |
| {board_id} | Board id |
| {board_name} | Board name |
| {list_id} | List id for the card |
| {list_name} | List name |
| {card_id} | Card id |
| {card_title} | Card title |
| {card_description} | Card description (string or null) |
| {card_priority} | Priority enum string |
| {card_due_date} | Due date ISO string or null |
| {card_archived} | Whether the card is archived |
| {card_position} | Numeric position in list |
| {card_list_id} | List id the card belongs to |
| {card_created_at} | ISO created timestamp |
| {card_updated_at} | ISO updated timestamp |
| {card_url} | Deep link to the card in Saku (null if no card) |
| {actor_id} | User id who triggered the action |
| {actor_name} | Display name or null |
| {changes} | Array of change objects (card.updated); empty if none |
| {labels} | Array of {id, name, colour} |
| {assignees} | Array of {user_id, name} |
| {custom_fields} | Array of {field_id, name, value} |
| {move} | Object {from: {id, name}, to: {id, name}} or null |
| {label} | Object {id, name, colour} for label events; null otherwise |
| {assignee} | Object {user_id, name} for assignee events; null otherwise |
| {comment} | Object {id, content, parent_comment_id, created_at} or null |
| {deleted_card} | Object {id, title, list_id, board_id} after delete; null otherwise |
| {test_message} | Only for webhook.test: human-readable test notice |
Nested objects from the simple envelope (e.g. {board}, {card}) are also available when those sections are included.
Examples
Minimal custom shape for a Slack-style incoming webhook or Zapier catch:
{
"source": "saku",
"event": {event},
"board": {board_name},
"card": {card_title},
"url": {card_url}
}Test deliveries (webhook.test) expose {test_message} and {message} with the same text as the default test body; other card fields are typically null or empty.
Delivery log
The webhook tab shows recent attempts with HTTP status, duration, and a short response preview. Use it after changing your endpoint or template, or after triggering events on the board.