Skip to main content
Work has two kinds of webhook. A webhook subscription sends a board’s events out to a URL you own. An inbound webhook lets another tool start an automation. Both use the same signature, so one verifier works for both. Both are set up through the API or by an Agent over MCP. There is no screen for them yet.

Send board events out

A subscription belongs to one board. You need Manage on the board to create, change or delete one. A board can have up to 10. Create one with POST /v1/boards/{boardId}/webhooks:
An empty eventTypes list means every event. The response shows the signing secret once. Store it then: it is never shown again.

Events

The URL must answer a challenge

Before it stores a subscription, Work sends one signed request to the URL with the body {"type": "webhook.challenge", "challenge": "<value>"}. Your endpoint must answer 2xx with the same value, as JSON {"challenge": "<value>"} or as the bare text. If it does not, the subscription is not created, and the board’s data is never sent to that URL. The URL must be https and point to a public host. Addresses on private networks are refused, both when you create the subscription and on every delivery.

What a delivery looks like

Each event is sent as a POST with a JSON body and these headers: To check a delivery, compute the HMAC with your secret over {x-bot-timestamp}.{raw body}, compare it to the signature in constant time, and reject a timestamp more than 5 minutes old. A subscription gets exactly one delivery per event. Delivery is at least once: if Work crashes after your endpoint answered but before it recorded the answer, it sends again. Use x-worksong-delivery to ignore a repeat.

Retries and the delivery log

A 2xx answer ends the delivery. A 408, 425, 429, a 5xx or a network error is retried, after 10 seconds, 1 minute, 5 minutes, 30 minutes, 2 hours, 6 hours and 12 hours, 8 attempts in all. Any other 4xx is not retried. A delivery that runs out of attempts is marked failed. GET /v1/webhooks/{id}/deliveries lists recent deliveries with their status, attempts and last HTTP status. Large events are cut to 200 KB and flagged truncated.

Manage a subscription

The URL cannot be edited. A new URL needs a new subscription, because the challenge verified the old one.

Start an automation from outside

Give an automation the Inbound webhook trigger. Then PUT /v1/automations/{id}/webhook returns its URL and a signing secret, once. Calling it again rotates the secret, and the old one stops working at once. DELETE removes the webhook, and its URL answers 404. Send a signed POST with a JSON object to the URL (/v1/hooks/{tenantId}/{automationId}), using the same x-bot-timestamp and x-bot-signature headers as above. The call needs no login. The object is flattened to dotted keys: {"customer": {"name": "Dana"}} becomes customer.name. The automation’s actions can then copy these keys into columns, for example with a CreateItem action. A body can have up to 200 fields. A repeated request with the same signature is accepted but runs the automation only once. Source: worksong-ai/worksong:services/work/src/Boardy.Api/WebhooksApi.cs@f8b76d6, worksong-ai/worksong:services/work/src/Boardy.Edge/Domain/WebhookSubscription.cs@f8b76d6, worksong-ai/worksong:services/work/src/Boardy.Workers/WebhookDeliverer.cs@f8b76d6. Docs version: Worksong 2.0 with Work 1.2.