> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getbluejay.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Send Bluejay results to your own tools.

Bluejay sends a signed `POST` request with a JSON body to your URL when it evaluates a conversation, ends a simulation, or fires an alert. The [Events Webhook reference](/api-reference/webhook/events-webhook.md) has the payload schemas.

## Create a webhook

To create a webhook, open **Settings → Webhooks** in the [workspace](/administration/workspaces.md) whose agents it should watch, and enter an HTTPS URL. A webhook fires only for agents in its own workspace. Copy the signing key to your receiver, which uses it to [verify the signature](#verify-the-signature) of each request.

To limit the webhook to some agents, select the agents or folders. A folder includes every agent in it. If you select no agents and no folders, the webhook fires for all agents in the workspace.

## Events

| UI label | `type` in the body | Fires when |
| - | - | - |
| Simulation evaluated | simulation\_result\_evaluated | A simulation result finishes evaluation. |
| Simulation ended | simulation\_ended | A simulated conversation ends, before evaluation. |
| Outbound simulation started | outbound\_simulation\_started | An outbound simulation run starts. |
| Observability log evaluated | observability\_call\_evaluated | A production conversation finishes evaluation. |
| Observability alert triggered | observability\_alert\_triggered | An observability [alert](/monitor/alerts.md) enters or leaves alarm. |
| Simulation alert triggered | simulation\_alert\_triggered | A simulation alert fires or recovers for a run. `subtype` is `triggered` or `recovered`. |

## Verify the signature

Each request has an `X-Bluejay-Signature` header. The value is the hex HMAC-SHA256 of the raw body, signed with your webhook's signing key.

1. Read the raw request body. Do not parse and serialize the JSON again, because the signature uses the exact bytes.
2. Compute `HMAC-SHA256(body, signing_key)` as a hex digest.
3. Compare it to `X-Bluejay-Signature` with a constant-time comparison.
4. If the values do not match, reject the request.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
import hmac, hashlib

def is_valid(body: bytes, signature: str, signing_key: str) -> bool:
    expected = hmac.new(signing_key.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
```

## Delivery

* Requests come from `api.getbluejay.ai`. If you use an allowlist, allow that host.
* Bluejay sends each event once and does not retry.

## Troubleshooting

If a webhook does not fire, do these checks:

1. Make sure the webhook is enabled.
2. Make sure the event is selected.
3. Make sure the agent is in the selected agents or folders.
4. Make sure the agent and the webhook are in the same workspace.
5. Check the tag. If a [`POST /v1/evaluate`](/api-reference/endpoint/evaluate) request sets `webhook_tag`, only webhooks with that tag fire. If it does not, webhooks that have a tag do not fire.
6. Make sure your URL is reachable from the internet.

## Related

* [Events Webhook reference](/api-reference/webhook/events-webhook.md)
* [Simulation Results](/test/simulations/create.md#read-the-results)
* [Alerts](/monitor/alerts.md)
* [Logs](/monitor/logs.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.