# Configure Privacy Request Webhooks

## What is a Privacy Request webhook? [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#what-is-a-privacy-request-webhook/index.html)

A privacy request webhook is an HTTPS callback that you've defined on an [execution policy](/content/docs/privacy-requests/reference/request-policies/index.html) to trigger an external REST API endpoint either _before_ or _after_ a privacy request executes.

Webhooks can be `one_way`, where the API is pinged and the privacy request continues, or `two_way`, where Fides will wait for the webhook to respond before continuing.

A `two_way` webhook can return derived values which will be saved and used to locate other user information. For example, a webhook might take a known `email` to find a corresponding `phone_number`, i.e., a `derived_identity`.

Additionally, `two_way` webhooks can pause the request's execution by providing a `halt` flag in their response—allowing you to wait for other systems or complete other tasks before continuing.

Webhooks are also classified by their timing, both of which can be defined as `one_way` or `two_way`:

- `PolicyPreWebhooks`: Run before the privacy request
- `PolicyPostWebhooks`: Run after the privacy request

Both pre and post-execution webhooks run after the privacy requests have been approved. A [pre-approval webhook (opens in a new tab)](/content/docs/privacy-requests/pre-approval-webhooks/index.html) (`PreApprovalWebhook`) runs prior to approval, i.e., as soon as a privacy request is received.

### Why use privacy request webhooks? [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#why-use-privacy-request-webhooks/index.html)

Privacy request webhooks allow you to integrate external systems and custom logic into your privacy request workflow. Common use cases include:

- **Pre-execution webhooks**: Preparing systems before data access or erasure (e.g., waking up databases, validating prerequisites, deriving additional user identities from external systems)
- **Post-execution webhooks**: Triggering downstream processes after completion (e.g., notifying CRM systems, updating audit logs, sending confirmation emails through custom channels)
- **Derived identities**: Using `two_way` webhooks to enrich user identity data by querying external systems
- **Conditional processing**: Pausing execution with the `halt` flag to wait for manual approval or external system readiness

## Configuration [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#configuration/index.html)

The process below defines an example `https` [Connection](/content/docs/api-reference/manage/connection/index.html) with the details for an API endpoint, and then creates a `PolicyPreWebhook` or a `PolicyPostWebhook` for a specific execution policy using that Connection.

### Create an HTTPS Connection [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#create-an-https-connection/index.html)

The information that describes how to connect to your API endpoint is represented by a Connection.

PATCH /v1/connection

```
[
    {
      "name": "My Webhook Connection Configuration",
      "key": "test_webhook_connection_config",
      "connection_type": "https",
      "access": "read"
    }
]
```

#### Authorization [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#authorization/index.html)

Fides supports two different mechanisms for authorization of HTTPS connections: static connection secrets, or using an OAuth 2.0 client credentials flow. You can choose between the two, depending on your setup. Note that, with OAuth 2.0, currently only the client credentials grant type is supported for service-to-service communication.

##### Connection secrets [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#connection-secrets/index.html)

The credentials needed to access your API endpoint are defined by making a PUT to the Connection Secrets endpoint. These credentials are encrypted and securely stored in Fides.

PUT /v1/connection/test_webhook_connection_config/secret

```
{
    "url": "https://www.example.com",
    "authorization": "test_authorization"
}
```

Fides will use your `authorization` value to construct the `Authorization` header to call your API endpoint, for example, `Authorization: test_authorization`.

You can also prefix your auth value with `Basic`, `Bearer`, or another auth scheme.

The below secrets will result in Fides using an `Authorization: Bearer mysecrettoken` header:

PUT /v1/connection/test_webhook_connection_config/secret

```
{
    "url": "https://www.example.com",
    "authorization": "Bearer mysecrettoken"
}
```

##### OAuth 2.0 [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#oauth-20/index.html)

For those who use OAuth to perform authorization, Fides also supports using OAuth to handle service-to-service security. Instead of a single, trusted, secret that must be shared you can use OAuth's temporary tokens to grant Fides permission to access an upstream service on a case-by-case basis in a central location.

###### Adding [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#adding/index.html)

In order to do this, you have to have an existing HTTPS connection defined and then add the OAuth configuration to it. You can do this through the `oauth` resource of the connection configuration by making a `PUT` call and providing the grant type (currently the only supported type is `client_credentials`), URL of the token service, scope, client ID and client secret.

PUT /v1/connection/test_webhook_connection_config/oauth

```
{
    "grant_type": "client_credentials",
    "token_url": "https://oauth.example.com/token",
    "scope": "read write",
    "client_id": "fides_webhook",
    "client_secret": "topsecretsecret"
}
```

###### Removing [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#removing/index.html)

You can revoke the OAuth credentials by making a `DELETE` call to the connection configuration's `oauth` resource (such as `DELETE /v1/connection/test_webhook_connection_config/oauth`). This will cause subsequent webhook executions to have no authorization data unless you already have a `secrets` resource created.

###### Updating [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#updating/index.html)

You can update a part of the OAuth configuration by issuing a `PATCH` call using a partial JSON object with only the fields you want to update (for example, if you wanted to only update the client secret).

### Create pre-execution or post-execution webhooks [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#create-pre-execution-or-post-execution-webhooks/index.html)

After you've defined a new Connection, you can create a list of webhooks to run _before_ (`PolicyPreWebhooks`) or _after_ (`PolicyPostWebhooks`) a privacy request is executed.

You must provide the policy key of your DSR policy when applying a webhook to that policy. You can retrieve a list of DSR policies and their policy keys by making this request:

```
GET /v1/dsr/policy
```

Next, you can update a list of webhooks for a given policy. In this example, we'll create pre-execution webhooks by adding a list of `PolicyPreWebhooks`.

```
PUT /v1/policy/{policy_key}/webhook/post_execution
```

When defining webhooks, they should be included in the request body in the desired order that you'd like them to execute. Any webhooks on the execution policy _not_ included in the request will be removed from the policy.

PUT v1/policy/{policy_key}/webhook/pre_execution

```
[
    {
        "connection_config_key": "test_webhook_connection_config",
        "direction": "one_way",
        "key": "wake_up_snowflake_db",
        "name": "Wake up Snowflake DB Webhook"
    },
     {
        "connection_config_key": "test_webhook_connection_config",
        "direction": "two_way",
        "key": "prep_systems_webhook",
        "name": "Prep Systems Webhook"
    }
]
```

⚠️

This endpoint is a PUT - make sure to call GET v1/policy/{policy_key}/webhook/pre_execution and pass the entire body of that response with any desired updates, to avoid losing your configuration!

This request creates two webhooks that are run sequentially according to the `order` returned in the response body before a privacy request runs.

Similarly, to update your list of post-execution webhooks on a policy, use the following endpoint:

```
PUT /v1/policy/{policy_key}/webhook/post_execution
```

### Update a single webhook [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#update-a-single-webhook/index.html)

To update a single webhook, send a PATCH request to update selected attributes. **Updates to order can likewise update the order of related webhooks.**

The following example will update the `PolicyPreWebhook` with key `wake_up_snowflake_db` to be `two_way` instead of `one_way`, and will update its order from 0 to 1. Because we've defined two` PolicyPreWebhooks`, this causes the webhook at position 1 to move to position 0.

PATCH /v1/policy/{policy_key}/webhook/pre-execution/wake_up_snowflake_db

```
{
    "direction": "two_way",
    "order": 1
}
```

Because this PATCH request updated the order of other webhooks, a reordered summary is included under the `new_order` attribute:

Response

```
{
    "resource": {
        "direction": "two_way",
        "key": "wake_up_snowflake_db",
        "name": "Wake up Snowflake DB Webhook",
        "connection_config": "<TRUNCATED>",
        "order": 1
    },
    "new_order": [
        {
            "key": "prep_systems_webhook",
            "order": 0
        },
        {
            "key": "wake_up_snowflake_db",
            "order": 1
        }
    ]
}
```

Similarly, to update a post-execution webhook on an execution policy, use the following endpoint:

```
PATCH /v1/policy/{policy_key}/webhook/post_execution/{post_execution_key}
```

## Webhook request format [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#webhook-request-format/index.html)

Before and after running access or erasure requests, Fides will send requests to any configured webhooks in sequential order with the following request body:

POST {user-defined URL}

```
{
  "privacy_request_id": "pri_029832ba-3b84-40f7-8946-82aec6f95448",
  "timestamp": "2025-10-01T21:31:14.931Z", // the time of the request (in case of a delay, or to detect out of order requests)
  "direction": "one_way | two_way",
  "callback_type": "pre | post", // a pre or post-execution webhook
  "identity": {
    "email": "customer-1@example.com",
    "phone_number": "+15555555555"
  },
  "privacy_request": {
    // the complete privacy request object is available here
    "id": "pri_029832ba-3b84-40f7-8946-82aec6f95448",
    "external_id": "privacy_request_123",
    "status":  "in_processing", // Will vary based on the actual status
    "requested_at": "2024-08-01T14:38:32.499588",
    "started_processing_at":"2024-08-01T14:45:23.832828",
    "finished_processing_at": null,
    "reviewed_at": null,
    "reviewed_by": "reviewer id",
    "finalized_at": null,
    "finalized_by": null,
    "submitted_by": "submitter id",
    "custom_privacy_request_fields_approved_by": "entity approving custom fields",
    "custom_privacy_request_fields_approved_at": "2024-08-01T14:45:23.832828",
    "identity_verified_at": "2024-08-01T14:45:23.832828",
    "client_id": "client identifier",
    "origin": "http-origin",
    "policy_id": "example-policy-id",
    "policy": {
        "id": "example-policy-id",
        "name": "Deletion of data",
        "key": "delete-data",
        "drp_action": "deletion",
        "execution_timeframe": 42,
        "client_id": "example-client-id",
        "rules": [
            {
                "id": "rule-1",
                "name": "The golden rule",
                "key": "rule-key",
                "action_type": "erasure",
                "masking_strategy": {
                  "strategy": "nullify",
                  "configuration": {}
                },
                "storage_destination_id": "storage-resource-00"
            }
        ],
    },
    "property_id": "example_property_id",
    "cancel_reason": null,
    "canceled_at": null,
    "consent_preferences": [
    // list of consent preferences
    ],
    "source": "Privacy Center",
    "paused_at": null,
    "due_date": "2025-10-01T21:31:14.931Z",
    "days_left": 0,
    "custom_fields": [
    // a list of custom fields
    ],
    "location": "US"
  }
}
```

The `identity` attributes should exist in Fides before the webhook was created. In this example, the `email` field represents the user's email that was used to issue the privacy request. Other known identities for that user will also be embedded in the request (e.g., `phone_number`).

## Webhook response format [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#webhook-response-format/index.html)

Your webhook should respond immediately. If more processing time is needed, either make sure it is configured as a `one-way` webhook, or reply with `halt=True` if you want to pause execution and wait to finish processing.

**Note that only pre-execution webhooks can pause execution.**

Responses are not expected from `one-way` webhooks, but `two-way` webhooks should respond with the following:

```
{
  "derived_identity": {
    "email": "customer-1@gmail.com", // updated email address
    "phone_number": "+15555555555", // phone number returned in E.164 format
    "custom_identity": { // custom values (i.e. not email or phone number)
        "label": "Custom Identity Label",
        "value": "custom_value"
    }
  },
  "halt": "true | false" // set to true to pause execution; false to proceed
}
```

The example provides a `derived_identity` of derived identities, i.e., identities that are derived from the original identifier used for the privacy request. Values returned in the `derived_identity` will replace currently known identities — in this case, email and phone number — when fulfilling the privacy request. The `derived_identity` field is optional.

A `two-way` webhook will also respond with `reply-to` headers, allowing you to pause the request's execution while any additional processing takes place:

```
  reply-to: /privacy-request/{privacy_request_id}/resume
  reply-to-token: <jwe_token>
```

## Resuming request execution [Permalink for this section](/content/docs/privacy-requests/guides/webhooks#resuming-request-execution/index.html)

Once a paused webhook finishes processing, send a request to the `reply-to` URL appended to your Fides domain (e.g. `<your-fides-instance-domain>/privacy-request/{privacy_request_id}/resume`) , along with the `reply-to-token` as the `Bearer` token in the `Authorization` header.

POST /v1/privacy_request/{privacy-request-id}/resume

```
{
  "derived_identity": {
    "email": "customer-1@gmail.com",
    "phone_number": "+15555555555",
    "custom_identity": { // custom values (i.e. not email or phone number)
        "label": "Custom Identity Label",
        "value": "custom_value"
    }
  }
}
```

If there are no derived identities, send an empty `{}` request body.

The `reply-to-token` is a JWE containing the current webhook ID, scopes to access the callback endpoint, and the datetime the token is issued. The token is valid for the duration defined in your [`privacy_request_delay_timeout`](/content/docs/platform/configuration/configuration#execution/index.html).

When a request expires, it will be given an `error` status and require resubmission.
