Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ and this project adheres to

<!--## Unreleased-->

## [0.33.0] - 2026-09-10
Comment thread
AntoniosBarotsis marked this conversation as resolved.
Resolved

### Added

- `webhook::rotate_signing_secret`

## [0.32.1] - 2026-09-04

### Added
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[package]
name = "resend-rs"
version = "0.32.1"
version = "0.33.0"
edition = "2024"

license = "MIT"
Expand Down
8 changes: 4 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,10 @@ pub mod types {
};
pub use super::webhooks::types::{
CreateWebhookOptions, CreateWebhookResponse, DeleteWebhookResponse,
ReplayWebhookEventResponse, UpdateWebhookOptions, UpdateWebhookResponse, Webhook,
WebhookEvent, WebhookEventAttempt, WebhookEventAttemptId, WebhookEventAttemptListResponse,
WebhookEventDetails, WebhookEventId, WebhookEventListResponse, WebhookEventStatus,
WebhookId, WebhookStatus,
ReplayWebhookEventResponse, RotateWebhookSigningSecretResponse, UpdateWebhookOptions,
UpdateWebhookResponse, Webhook, WebhookEvent, WebhookEventAttempt, WebhookEventAttemptId,
WebhookEventAttemptListResponse, WebhookEventDetails, WebhookEventId,
WebhookEventListResponse, WebhookEventStatus, WebhookId, WebhookStatus,
};
}

Expand Down
50 changes: 47 additions & 3 deletions src/webhooks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ use crate::{
list_opts::{AfterPagination, ListOptions, ListResponse},
types::{
CreateWebhookOptions, CreateWebhookResponse, DeleteWebhookResponse,
ReplayWebhookEventResponse, UpdateWebhookOptions, UpdateWebhookResponse, Webhook,
WebhookEventAttemptListResponse, WebhookEventDetails, WebhookEventListResponse,
ReplayWebhookEventResponse, RotateWebhookSigningSecretResponse, UpdateWebhookOptions,
UpdateWebhookResponse, Webhook, WebhookEventAttemptListResponse, WebhookEventDetails,
WebhookEventListResponse,
},
};

Expand Down Expand Up @@ -118,6 +119,24 @@ impl WebhookSvc {
Ok(content)
}

/// Rotate the signing secret of a webhook. The previous secret keeps working for 24 hours.
Comment thread
AntoniosBarotsis marked this conversation as resolved.
Resolved
///
/// <https://resend.com/docs/api-reference/webhooks/rotate-signing-secret>
#[maybe_async::maybe_async]
pub async fn rotate_signing_secret(
Comment thread
AntoniosBarotsis marked this conversation as resolved.
Resolved
&self,
webhook_id: &str,
) -> Result<RotateWebhookSigningSecretResponse> {
let path = format!("/webhooks/{webhook_id}/signing-secret/rotate");
let request = self.0.build(Method::POST, &path);
let response = self.0.send(request).await?;
let content = response
.json::<RotateWebhookSigningSecretResponse>()
.await?;

Ok(content)
}

/// Retrieve the delivery attempts for a webhook event.
///
/// <https://resend.com/docs/api-reference/webhooks/list-event-attempts>
Expand Down Expand Up @@ -253,6 +272,14 @@ pub mod types {
pub signing_secret: String,
}

#[must_use]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RotateWebhookSigningSecretResponse {
pub object: String,
pub id: WebhookId,
pub signing_secret: String,
}

#[must_use]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Webhook {
Expand Down Expand Up @@ -328,7 +355,8 @@ mod test {
list_opts::ListOptions,
types::{CreateWebhookOptions, CreateWebhookResponse},
types::{
Webhook, WebhookEventAttemptListResponse, WebhookEventDetails, WebhookEventListResponse,
RotateWebhookSigningSecretResponse, Webhook, WebhookEventAttemptListResponse,
WebhookEventDetails, WebhookEventListResponse,
},
};
#[cfg(not(feature = "blocking"))]
Expand Down Expand Up @@ -413,6 +441,22 @@ mod test {
assert!(res.is_ok());
}

#[test]
fn deserialize_rotate_signing_secret_response() -> serde_json::Result<()> {
let rotated = r#"{
"object": "webhook",
"id": "4dd369bc-aa82-4ff3-97de-514ae3000ee0",
"signing_secret": "whsec_yyyyyyyyyy"
}"#;

let rotated = serde_json::from_str::<RotateWebhookSigningSecretResponse>(rotated)?;

assert_eq!(rotated.id.as_ref(), "4dd369bc-aa82-4ff3-97de-514ae3000ee0");
assert_eq!(rotated.signing_secret, "whsec_yyyyyyyyyy");

Ok(())
}

#[test]
fn deserialize_webhook_event_responses() -> serde_json::Result<()> {
let events = r#"{
Expand Down