sift_science/
webhooks.rs

1//! Receive notifications about events in Sift.
2//!
3//! When one of the events is triggered, Sift will send a JSON payload to the webhook's specified
4//! URL. Webhooks can be used to update your own support tool, data warehouses, and more.
5
6use crate::common::deserialize_ms;
7use crate::error::Error;
8use serde::{Deserialize, Serialize};
9use std::fmt;
10use std::time::SystemTime;
11
12/// The header sift science will attach to each webhook invocation.
13///
14/// This should be used to verify that the request originates from Sift's servers.
15pub const SIGNATURE_HEADER: &str = "X-Sift-Science-Signature";
16
17/// Options when creating a new [Webhook].
18///
19/// See <https://sift.com/developers/docs/curl/webhooks-api/create> for examples.
20#[derive(Debug, Serialize)]
21pub struct WebhookRequest {
22    /// The type of webhook payload
23    pub payload_type: PayloadType,
24
25    /// The webhook status.
26    pub status: Status,
27
28    /// The URL of the webhook endpoint.
29    ///
30    /// This must be HTTPS.
31    pub url: String,
32
33    /// The list of events to enable for this endpoint.
34    ///
35    /// These correspond to the Reserved Events in the [Events API].
36    ///
37    /// [Events API]: https://sift.com/developers/docs/curl/events-api/overview
38    pub enabled_events: Vec<EnabledEvent>,
39
40    /// A name you specify for this webhook.
41    pub name: Option<String>,
42
43    /// A description about what the webhook is used for.
44    pub description: Option<String>,
45}
46
47/// Webhook data
48///
49/// See <https://sift.com/developers/docs/curl/webhooks-api/create> for examples.
50#[derive(Debug, Deserialize, Serialize)]
51pub struct Webhook {
52    /// The id of the webhook.
53    pub id: u64,
54
55    /// The name of the webhook
56    #[serde(default)]
57    pub name: Option<String>,
58
59    /// The description of the webhook
60    #[serde(default)]
61    pub description: Option<String>,
62
63    /// The type of payload.
64    pub payload_type: PayloadType,
65
66    /// The webhook status.
67    pub status: Status,
68
69    /// The URL of the webhook endpoint.
70    ///
71    /// This must be HTTPS.
72    pub url: String,
73
74    /// The list of events to enable for this endpoint.
75    ///
76    /// These correspond to the Reserved Events in the [Events API].
77    ///
78    /// [Events API]: https://sift.com/developers/docs/curl/events-api/overview
79    pub enabled_events: Vec<EnabledEvent>,
80
81    /// The time at which the webhook was created
82    #[serde(skip_serializing, deserialize_with = "deserialize_ms")]
83    pub created: SystemTime,
84
85    /// The time at which the webhook was updated
86    #[serde(skip_serializing, deserialize_with = "deserialize_ms")]
87    pub last_updated: SystemTime,
88}
89
90/// The type of webhook payload.
91#[derive(Debug, Serialize, Deserialize)]
92pub enum PayloadType {
93    /// This payload type provides an order data response.
94    ///
95    /// See the [order object](https://sift.com/developers/docs/curl/orders-api/order).
96    #[serde(rename = "ORDER_V1_0")]
97    OrderV10,
98}
99
100/// The webhook status.
101#[derive(Debug, Serialize, Deserialize)]
102#[serde(rename_all = "UPPERCASE")]
103pub enum Status {
104    /// Indicates the webhook is in a draft state.
105    ///
106    /// No webhooks are sent.
107    Draft,
108
109    /// Indicates the webhook is active.
110    ///
111    /// The webhook is live.
112    Active,
113}
114
115/// The event to be included as enabled for a webhook.
116///
117/// These correspond to the Reserved Events in the [Events API].
118///
119/// [Events API]: https://sift.com/developers/docs/curl/events-api/overview
120#[derive(Debug, Serialize, Deserialize)]
121pub enum EnabledEvent {
122    /// Occurs whenever a [Event::CreateOrder] event is tracked.
123    ///
124    /// [Event::CreateOrder]: crate::events::Event::CreateOrder
125    #[serde(rename = "$create_order")]
126    CreateOrder,
127
128    /// Occurs whenever a [Event::UpdateOrder] event is tracked.
129    ///
130    /// [Event::UpdateOrder]: crate::events::Event::UpdateOrder
131    #[serde(rename = "$update_order")]
132    UpdateOrder,
133
134    /// Occurs whenever a [Event::OrderStatus] event is tracked.
135    ///
136    /// [Event::OrderStatus]: crate::events::Event::OrderStatus
137    #[serde(rename = "$order_status")]
138    OrderStatus,
139
140    /// Occurs whenever a [Event::Transaction] event is tracked.
141    ///
142    /// [Event::Transaction]: crate::events::Event::Transaction
143    #[serde(rename = "$transaction")]
144    Transaction,
145
146    /// Occurs whenever a [Event::Chargeback] event is tracked.
147    ///
148    /// [Event::Chargeback]: crate::events::Event::Chargeback
149    #[serde(rename = "$chargeback")]
150    Chargeback,
151}
152
153#[derive(Deserialize)]
154#[serde(untagged)]
155pub(crate) enum WebhooksResponse {
156    Error(Error),
157    Webhooks { data: Vec<Webhook> },
158}
159
160#[derive(Deserialize)]
161#[serde(untagged)]
162pub(crate) enum WebhookResponse {
163    Error(Error),
164    Webhook(Webhook),
165}
166
167/// Webhook API version
168#[derive(Copy, Clone, Debug)]
169pub enum ApiVersion {
170    /// Version 3
171    V3,
172}
173
174impl fmt::Display for ApiVersion {
175    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
176        match self {
177            ApiVersion::V3 => write!(f, "v3"),
178        }
179    }
180}