---
updatedAt: 2025-12-09T19:09:52.000Z
agentTools:
  projectIndex: https://docs.castle.io/llms.txt
---

# Upgrade Legacy Webhooks to new Webhooks

Seamlessly migrate to the latest Castle Webhooks by following this guide.

> 📘 Remember to re-evaluate how your current Webhooks are configured
>
> While this guide provides a one-to-one migration from Legacy Webhooks to the new Webhooks, we recommend re-evaluating how your Webhooks are configured. This is an opportunity to optimize your setup and ensure it aligns with your current workflow needs.

## Legacy Webhooks

Castle's Legacy Webhooks were configured via the [Castle Dashboard](https://dashboard.castle.io/settings/webhooks) based on two types of security events:

* `$review.opened`: Triggered when the event status is `$succeeded` and the Castle response policy action is `challenge`
* `$incident.confirmed`: Triggered when the event status is `$succeeded` and the Castle response policy action is `deny`.

## New Webhooks

The new Webhooks, as described in the [Webhooks documentation ](https://docs.castle.io/docs/webhooks), can be configured either at the policy level or the list level. The event types include:

* `$policy.matched`: Triggered when a specific policy is activated.
* `$list_item.created`, `$list_item.archived`, `$list_item.unarchived`: Triggered when list actions are performed.

## Migration Process

This guide shows how to create Webhooks under individual policies. Alternatively, you can create webhooks globally under [the Global Integrations Page](https://dashboard.castle.io/settings/integrations) or the **policies > integrations** page. You can read more about this in our [Webhook documentation](https://docs.castle.io/docs/webhooks).

### Migrating `challenge` webhooks

To migrate your legacy `$review.opened` Webhook:

* Go to the [policies page](https://dashboard.castle.io/policies).
* One by one, select policies which have a `Challenge` inline action and Event group set to an event with type `$succeeded` like `Login Succeeded` or `Registration Succeeded`.
* Click on **Add Webhook**.

![](https://files.readme.io/704bc02d6a64c30467a4d9e302fa637d30b405cee51c5950408e13ec75746bb5-image.png)

* Copy the **Endpoint URL** from the [Legacy Webhooks Page](https://dashboard.castle.io/settings/webhooks) where the "Events subscribed to" is `$review.opened`.

![](https://files.readme.io/01511303cc84b77b8d03ad8a51df82cefb2584a4de93b75b2bcfeead5a97a78c-image.png)

<br />

* Paste the URL into the new Webhook configuration.
* Click on **Save Changes**.

This new webhook will trigger whenever the associated policy is activated.

### Migrating `deny` webhooks

To migrate your legacy `$incident.confirmed` webhook:

* Go to the [policies page](https://dashboard.castle.io/policies).
* One by one, select policies which have a `Deny` inline action and Event group set to an event with type `$succeeded` like `Login Succeeded` or `Registration Succeeded`.
* Click on **Add Webhook**.

![](https://files.readme.io/175d540ec124e5cd753da12767530589d7ce6a7b4a80039210e62f90b8c48677-image.png)

<br />

* Copy the **Endpoint URL** from the [Legacy Webhooks Page](https://dashboard.castle.io/settings/webhooks) where the "Events subscribed to" is `$incident.confirmed`.

![](https://files.readme.io/33925480b03b031412025700438f7bffb88fdbca4faabea6e0510072368e96bf-image.png)

<br />

* Paste the URL into the new webhook configuration.
* Click on **Save Changes**.

This Webhook will now trigger whenever the associated policy is activated.

## Final Steps

> 📘 Review webhook data
>
> Review the new webhook data [here](https://docs.castle.io/docs/webhooks#policy-triggered).  Compare the data received from the new Webhooks with your legacy Webhook data, and update your code as needed.

> 🚧 Before deactivating your Legacy Webhooks
>
> Ensure your new Webhooks are functioning correctly. It's recommended to run both Legacy and New Webhooks for a week in parallel for testing.