Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
7 changes: 7 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.32.2] - 2026-09-10

### Added

- `webhook::rotate_signing_secret`

## [0.32.1] - 2026-09-04

### Added
Expand Down Expand Up @@ -621,6 +627,7 @@ Disabled `reqwest`'s default features and enabled `rustls-tls`.

Initial release.

[0.32.2]: https://crates.io/crates/resend-rs/0.32.2
[0.32.1]: https://crates.io/crates/resend-rs/0.32.1
[0.32.0]: https://crates.io/crates/resend-rs/0.32.0
[0.31.1]: https://crates.io/crates/resend-rs/0.31.1
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.32.2"
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