---
title: "How do I trigger and react to playbooks with webhooks?"
description: "TL;DR: A Webhook trigger gives a playbook a unique HTTP endpoint. External systems POST to that URL to start a run, and the request body is available to the playbook's steps as input. Use webhooks to start playbooks from services that emit outbound events, and use the runs stream to react when a run finishes."
canonical_url: "https://docs.ballet.dev/articles/how-do-i-trigger-and-react-to-playbooks-with-webhooks-DYv9XyeU51"
md_url: "https://docs.ballet.dev/articles/how-do-i-trigger-and-react-to-playbooks-with-webhooks-DYv9XyeU51.md"
---
# How do I trigger and react to playbooks with webhooks?

**TL;DR:** A Webhook trigger gives a playbook a unique HTTP endpoint. External systems POST to that URL to start a run, and the request body is available to the playbook's steps as input. Use webhooks to start playbooks from services that emit outbound events, and use the runs stream to react when a run finishes.

## Who this is for

Developers connecting Ballet to systems that emit outbound webhooks (helpdesks, CRMs, CI, payment processors).

## How do I trigger a playbook from an external event?

1. Open the playbook and add a **Webhook** trigger in the Trigger panel.
2. Copy the generated endpoint URL.
3. Register that URL as an outbound webhook in your external system.
4. When the system fires the event, it POSTs to the URL and starts a run; the payload is passed to the playbook as input.

```bash
curl https://app.ballet.dev/api/webhooks/<your-webhook-path> \
  -H "Content-Type: application/json" \
  -d '{ "ticketId": "123", "subject": "Refund request" }'
```

Configure the exact endpoint from the playbook's Trigger panel — it is unique per playbook.

## How is this different from the REST execute endpoint?

For your own backend or CI, prefer the authenticated [REST execute endpoint](/articles/how-do-i-run-a-playbook-over-the-rest-api-KQIz0apagm).

## How do I react when a run finishes?

Subscribe to `GET /api/playbooks/:id/runs/stream` and watch for the `run_stop` event, which carries `success` and `output`. This lets an external observer act on completion without being the caller that started the run. See [Stream run events](/articles/how-do-i-stream-playbook-run-events-SsXLWiWt9X).

## Tips

* Test with a manual trigger and a sample payload before enabling the live webhook.
* Validate and normalize the incoming payload in an early Code step — external systems vary.
* Keep secrets (for callbacks to the source system) in Secrets, not in the playbook body.

## Related articles

* [What triggers can start a playbook?](/articles/what-triggers-can-start-a-playbook-manual-schedule-webhook-P4mdwPZDGg)
* [Run playbooks over the REST API](/articles/how-do-i-run-a-playbook-over-the-rest-api-KQIz0apagm)
* [Stream run events](/articles/how-do-i-stream-playbook-run-events-SsXLWiWt9X)
* [Connecting to external systems](/articles/how-do-playbooks-connect-to-external-systems-Jije3yYddT)
