Handling Webhook Events
Relevant source files
The following files were used as context for generating this wiki page:
- src/Resend.Webhooks/IWebhookHandler.cs
- src/Resend.Webhooks/EmailEventData.cs
- src/Resend.Webhooks/WebhookEvent.cs
- src/Resend.Webhooks/WebhookValidator.cs
- src/Resend.Webhooks/WebhookSink.cs
- src/Resend.Webhooks/Json/WebhookEventConverter.cs
- src/Resend/ResendClient.Webhooks.cs
- tools/Resend.ApiServer/Program.cs
- src/Resend/WebhookEventType.cs
Handling Webhook Events allows your application to receive and process real-time notifications from Resend regarding email delivery, contact updates, and domain status. The system provides a structured pipeline to validate incoming HTTP requests, deserialize JSON payloads into strongly-typed objects, and execute custom logic through handlers.
The architecture centers on the WebhookSink, which coordinates validation via WebhookValidator and execution via an implementation of IWebhookHandler. This ensures that only authentic requests from Resend are processed, protecting your endpoint from unauthorized access.
Sources: src/Resend.Webhooks/README.md, src/Resend.Webhooks/WebhookSink.cs:12-25
Webhook Architecture and Data Flow
The webhook system follows a linear execution path from the HTTP request to the final handler logic. The WebhookSink acts as the entry point for the middleware or controller.
Processing Pipeline
- Validation: The
WebhookValidatorextracts Svix headers (svix-id,svix-timestamp,svix-signature) and verifies the payload against the configured signing secret. - Context Creation: A
WebhookContextis generated, containing the validation result, the raw payload, and the deserializedWebhookEvent. - Dispatch: Based on the
IsValidproperty of the context, the sink calls eitherHandleValidorHandleInvalidon the registeredIWebhookHandler.
The following diagram illustrates the flow of a webhook request through the system:
Request Validation
Security is enforced using Svix-compatible signatures. The WebhookValidator requires three specific headers to authenticate the request.
| Header | Description |
|---|---|
svix-id | Unique identifier for the webhook message. |
svix-timestamp | Unix timestamp of when the message was sent. |
svix-signature | HMAC signature used to verify authenticity. |
If any of these headers are missing or if the signature does not match the computed hash using the RESEND_WEBHOOK_SECRET, the validation fails.
Sources: src/Resend.Webhooks/WebhookValidator.cs:64-100, tools/Resend.ApiServer/Program.cs:20-23
Webhook Event Data Models
Incoming payloads are deserialized into a WebhookEvent object. This object contains metadata and a polymorphic Data property that changes based on the EventType.
Event Structure
A WebhookEvent consists of:
EventType: AWebhookEventTypeenum value (e.g.,EmailSent,ContactCreated).MomentCreated: The timestamp when the event occurred.Data: The specific payload data, which can be cast using theDataAs<T>()helper method.
Sources: src/Resend.Webhooks/WebhookEvent.cs:9-35, src/Resend.Webhooks/Json/WebhookEventConverter.cs:30-70
Supported Event Categories
The system categorizes events to simplify data casting.
| Category | Associated Data Type | Examples |
|---|---|---|
EmailEventData | email.sent, email.delivered, email.bounced | |
| Contact | ContactEventData | contact.created, contact.deleted |
| Domain | DomainEventData | domain.created, domain.verified |
| Suppression | SuppressionEventData | suppression.added, suppression.removed |
| Inbox | InboxEventData | inbox.created, inbox.updated |
Sources: src/Resend/WebhookEventType.cs:12-210, src/Resend.Webhooks/Json/WebhookEventConverter.cs:85-160
Implementation Guide
To handle webhooks, you must implement the IWebhookHandler interface and register it during application startup.
Custom Handler Implementation
Your handler defines the logic for successful and failed validations.
public class MyWebhookHandler : IWebhookHandler
{
public async Task<IResult> HandleValid(WebhookContext context)
{
var emailData = context.Event.DataAs<EmailEventData>();
// Process valid email event
return Results.Ok();
}
public async Task<IResult> HandleInvalid(WebhookContext context)
{
// Log unauthorized attempt
return Results.BadRequest();
}
}
Sources: src/Resend.Webhooks/IWebhookHandler.cs:8-23, tools/Resend.ApiServer/WebhookHandlers/Handler1.cs:20-50
Dependency Injection and Routing
In Program.cs, use the provided extension methods to configure the webhook services and map the endpoint.
- Call
AddResendWebhooksto register validation services and the signing secret. - Register your handler in the DI container.
- Use
MapResendWebhook<T>to link a URL path to your handler.
builder.Services.AddResendWebhooks(c =>
{
c.Secret = "whsec_your_secret";
});
builder.Services.AddScoped<MyWebhookHandler>();
var app = builder.Build();
app.UseRouting();
app.MapResendWebhook<MyWebhookHandler>("/webhooks/resend");
Sources: tools/Resend.ApiServer/Program.cs:18-40
Management API
The ResendClient provides methods to programmatically manage webhook registrations and inspect delivery logs.
WebhookCreateAsync: Registers a new endpoint URL and the events it should receive.WebhookListAsync: Retrieves a paginated list of all configured webhooks.WebhookEventListAsync: Lists the history of events sent to a specific webhook.WebhookEventReplayAsync: Requests Resend to redeliver a specific event.
Sources: src/Resend/ResendClient.Webhooks.cs:10-100
Summary
The webhook system in resend-dotnet provides a secure, type-safe framework for reacting to Resend platform events. By utilizing the WebhookValidator and implementing IWebhookHandler, developers ensure their applications process authentic data with minimal boilerplate. The combination of structured data models and a robust processing pipeline facilitates reliable integration with Resend's real-time notification services.