# Webhooks

> Get a signed event from Willo when content publishes or your site goes live, and start an Agent Program from a webhook call.

Last updated: November 10, 2026

Source: https://www.willo.ai/docs/ai-agents/webhooks

Webhooks run in both directions. Willo tells your own systems when something happens on the business, and your systems start an Agent Program by calling its webhook URL. Both directions use the same `X-Willo-Signature` scheme, so one verifier serves both.

## Receive events from Willo

An owner or admin registers an endpoint under **Settings → AI Agents → Webhooks**: an `https` URL and the events it should get. Webhooks come with Builder and up.

| Event | Sent when |
| --- | --- |
| `content.published` | A content item is published, by anyone, or its scheduled time comes. |
| `content.unpublished` | A published item goes back to a draft. |
| `content.deleted` | A published item is deleted, taking it off the site. Deleting a draft sends nothing. |
| `site.deployed` | A new version of the site goes live. |

From then on each event is sent with no approval step: registering the endpoint is the decision. Use it to rebuild another site, refresh a search index, start your own agent, or post to a team channel through Zapier, Make or your own code.

### The signing secret

Willo shows the endpoint's signing secret (`willo_whs_…`) once, when you register it. Every request carries an `X-Willo-Signature` header made with it. Check that header against the raw body before you trust a request: the [reference](https://www.willo.ai/docs/reference/outbound-webhooks#signature) has Node and Python examples. **Rotate secret** issues a new one and the old one stops signing at once, including for events still waiting.

### What a request carries

A JSON body with the event's id, name and time, the business, who caused it (`actor`), and `data` for the event: for content, the item's id, collection, slug, title, status, public URL and publish time. Payloads never include an item's body or field values, so a leaked endpoint URL reveals that something changed, not what it says. For the text, call `willo_content`, or fetch the post's [JSON copy](https://www.willo.ai/docs/site/your-site#use-your-posts-elsewhere) (`/blog/<slug>.json` for a blog post) after the `site.deployed` event that follows the publish: the copy changes when the site rebuilds.

Every field, header, retry and limit is on [Outbound webhook format](https://www.willo.ai/docs/reference/outbound-webhooks).

### Failures and retries

Answer with any `2xx` within the timeout. Anything else, including a redirect, is a failed try, and Willo retries on a backoff schedule; after the last try the delivery is marked failed. Deliveries can arrive out of order, and a retry repeats the same `X-Willo-Delivery` id, so ignore an id you have already handled.

An endpoint that keeps failing for days is disabled, and the business's owners and admins get a notification and an email. Fix the receiver, click **Send test event**, then **Resume**.

### On the card

Each endpoint shows its status, its events and its newest deliveries, with the try number, the receiver's HTTP status and the error. Owners and admins can send a test event, pause and resume it, change its events, rotate the secret and remove it. While an endpoint is paused nothing is queued for it. Editors see each endpoint's host, not its full URL, because a receiver URL often contains a credential.

A connected AI agent reads the same list with the `willo_webhooks` tool, so it can debug its own receiver: a delivery id there is the `X-Willo-Delivery` header the receiver got.

## Events while you are drafting

When the business is drafting its site, a publish lands on the draft, and visitors see it only when the draft is published. The `content.published` event is sent at the moment of the publish, with `data.visibility` set to `awaiting_site_publish`. When the draft goes live, `site.deployed` is sent; there is no second `content.published`. An event with `visibility: live` means visitors can see the change now. See [Who publishes content](https://www.willo.ai/docs/content/who-publishes#events-for-your-own-systems).

## Start a program from a webhook

An Agent Program with a webhook trigger has its own URL, and each POST to it starts one run. Zapier, Make, n8n, a form tool or your own code can call it. Setup, signing and responses are on [Webhook triggers](https://www.willo.ai/docs/agent-programs/webhook-triggers).

## Run a program when a post publishes

Register a program's own trigger URL as an endpoint, and each `content.published` event starts a run. The steps are on [Webhook triggers](https://www.willo.ai/docs/agent-programs/webhook-triggers#run-when-a-post-publishes).

Related: [Outbound webhook format](https://www.willo.ai/docs/reference/outbound-webhooks), [Webhook triggers](https://www.willo.ai/docs/agent-programs/webhook-triggers), [Edit CMS content and publish](https://www.willo.ai/docs/ai-agents/edit-cms-content-and-publish).

## Questions

### Does an event include the post's text?

No. Events carry ids, the title, the slug, the status and the public URL. Fetch the item when you need its body, with the willo_content tool straight away, or from the page or the post's JSON copy (/blog/<slug>.json) once the site.deployed event that follows says the new version is live.

### Why did my endpoint stop getting events?

Someone paused it, Willo disabled it after its tries kept failing for days, or the business's plan dropped below the one webhooks come with. Settings → AI Agents → Webhooks shows which. For a disabled endpoint, fix the receiver, click Send test event, then Resume.

### Can my AI agent register a webhook?

No. An owner or admin registers endpoints on the dashboard. A connected agent can list them and their deliveries with willo_webhooks.
