---
title: "Managing Webhooks via API"
slug: managing-webhooks-via-api
description: "Create, retrieve, list, and delete webhooks programmatically."
created_at: "2025-10-31"
updated_at: "2025-10-31"
image: https://cdn.resend.com/posts/managing-webhooks-via-api.jpg
humans: ["lucas-costa", "bu-kinoshita"]
---

You can now use the Resend API to manage webhooks.

This allows you to manage your webhooks, which will be triggered when certain events happen, like when an email bounces or a contact unsubscribes. There are currently [15 different events](https://resend.com/docs/dashboard/webhooks/event-types) that your webhooks can listen to.

The Webhooks API includes five new endpoints:
* [Create Webhook](https://resend.com/docs/api-reference/webhooks/create-webhook)
* [Retrieve Webhook](https://resend.com/docs/api-reference/webhooks/get-webhook)
* [Update Webhook](https://resend.com/docs/api-reference/webhooks/update-webhook)
* [Delete Webhook](https://resend.com/docs/api-reference/webhooks/delete-webhook)
* [List Webhooks](https://resend.com/docs/api-reference/webhooks/list-webhooks)

## How to use it

The best way to use these new endpoints is with our SDKs.

Here's an example of how you can create new webhooks:

<CodeTabs codeHeight={250}>

```nodejs
import { Resend } from 'resend';

const resend = new Resend('re_xxxxxxxxx');

const { data, error } = await resend.webhooks.create({
  endpoint: 'https://example.com/handler',
  events: ['email.sent'],
});
```

```php
$resend = Resend::client('re_xxxxxxxxx');

$resend->webhooks->create([
  'endpoint' => 'https://example.com/handler',
  'events' => ['email.sent'],
]);
```

```python
import resend

resend.api_key = 're_xxxxxxxxx'

params: resend.Webhooks.CreateParams = {
    "endpoint": "https://example.com/handler",
    "events": ["email.sent"],
}

webhook = resend.Webhooks.create(params=params)
```

```ruby
require 'resend'

Resend.api_key = 're_xxxxxxxxx'

params = {
  endpoint: 'https://example.com/handler',
  events: ['email.sent']
}

webhook = Resend::Webhooks.create(params)
```

```go
import "github.com/resend/resend-go/v2"

client := resend.NewClient("re_xxxxxxxxx")

params := &resend.CreateWebhookRequest{
  Endpoint: "https://example.com/handler",
  Events:   []string{"email.sent"},
}

webhook, err := client.Webhooks.Create(params)
```

```rust
use resend_rs::{
  events::EmailEventType::{EmailSent},
  types::CreateWebhookOptions,
  Resend, Result,
};

#[tokio::main]
async fn main() -> Result<()> {
  let resend = Resend::new("re_xxxxxxxxx");

  let events = [EmailSent];
  let opts = CreateWebhookOptions::new("https://example.com/handler", events);
  let _webhook = resend.webhooks.create(opts).await?;

  Ok(())
}
```

```java
import com.resend.*;
import static com.resend.services.webhooks.model.WebhookEvent.*;

public class Main {
    public static void main(String[] args) {
        Resend resend = new Resend("re_xxxxxxxxx");

        CreateWebhookOptions options = CreateWebhookOptions.builder()
              .endpoint("https://example.com/handler")
              .events(EMAIL_SENT)
              .build();

        CreateWebhookResponseSuccess response = resend.webhooks().create(options);
    }
}
```

```dotnet
using Resend;

IResend resend = ResendClient.Create("re_xxxxxxxxx"); // You can alsouse Dependency Injection

var data = new WebhookData()
{
  EndpointUrl = "https://example.com/handler",
  Events = [WebhookEventType.EmailSent],
  Status = WebhookStatus.Disabled,
};

var resp = await resend.WebhookCreateAsync(data);
Console.WriteLine("Webhook Id={0}", resp.Content.Id);
Console.WriteLine("Signing secret={0}", resp.Content.SigningSecret);
```

```curl
curl -X POST 'https://api.resend.com/webhooks' \
     -H 'Authorization: Bearer re_xxxxxxxxx' \
     -H 'Content-Type: application/json' \
     -d '{
  "endpoint": "https://example.com/handler",
  "events": ["email.sent"]
}'
```

</CodeTabs>

Once you perform a request, the API will return a standard response containing the object type, entity ID, and a signing secret that you can use to verify requests.

```json
{
  "object": "webhook",
  "id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
  "signing_secret": "whsec_xxxxxxxxxx"
}
```

## Verify webhook requests

In addition to the five new endpoints, we're also introducing an SDK helper to help [verify webhook requests](https://resend.com/docs/dashboard/webhooks/verify-webhooks-requests).

You can now use the new `verify` method as seen in the Next.js example below.

<Callout type="insight">
  You can get the Resend webhook secret from the webhook details page, accessible from the [Webhooks dashboard](https://resend.com/webhooks). It's also included in the response body of calls to create or list webhooks.
</Callout>

```nodejs
export async function POST(req: NextRequest) {
  try {
    const payload = await req.text();

    // Throws an error if the webhook is invalid
    // Otherwise, returns the parsed payload object
    const result = resend.webhooks.verify({
      payload,
      headers: {
        id: req.headers['svix-id'],
        timestamp: req.headers['svix-timestamp'],
        signature: req.headers['svix-signature'],
      },
      webhookSecret: 'whsec_xxxxxxxxxx',
    });

    // Handle the result after validating it
  } catch {
    return new NextResponse('Invalid webhook', { status: 400 });
  }
}
```

<Callout type="insight">
  Make sure that you're using the raw request body when verifying webhooks.
  The cryptographic signature is sensitive to even the slightest change.
  Some frameworks parse the request as JSON and then stringify it,
  and this will also break the signature verification.
</Callout>

Learn more about [verifying webhook requests](https://resend.com/docs/dashboard/webhooks/verify-webhooks-requests#verify-webhooks-requests).

## Get started

Visit the [documentation](https://resend.com/docs/api-reference/webhooks/create-webhook) to learn more about managing webhooks via the API.
