Verify method 📢 Webhooks
Verifies the authenticity of incoming webhook requests by validating their signatures using the provided options.
All webhooks are signed by default. There are three HTTP headers to consider during the signature verification process:
Content-Digest: hash of the message bodySignature-Input: describes what parts of the message are signed, along with other data about the signing methodSignature: the cryptographic signature
Usage
import { Webhooks } from 'mailchannels-sdk'
const { data, error } = await Webhooks.verify({
payload: rawBody,
headers: {
'content-digest': req.headers['content-digest'],
'signature': req.headers['signature'],
'signature-input': req.headers['signature-input']
},
publicKey: 'MCowBQYD...'
})import { MailChannelsClient, Webhooks } from 'mailchannels-sdk'
const mailchannels = new MailChannelsClient('your-api-key')
const webhooks = new Webhooks(mailchannels)
const { data, error } = await webhooks.verify({
payload: rawBody,
headers: {
'content-digest': req.headers['content-digest'],
'signature': req.headers['signature'],
'signature-input': req.headers['signature-input']
},
publicKey: 'MCowBQYD...'
})import { MailChannels } from 'mailchannels-sdk'
const mailchannels = new MailChannels('your-api-key')
const { data, error } = await mailchannels.webhooks.verify({
payload: rawBody,
headers: {
'content-digest': req.headers['content-digest'],
'signature': req.headers['signature'],
'signature-input': req.headers['signature-input']
},
publicKey: 'MCowBQYD...'
})NOTE
The Webhooks class provides both a static and an instance verify method. The static method is useful for quickly verifying webhook requests without needing to create an instance of the MailChannels class using your API Key. However, you can also use the instance method if you prefer, as both will yield the same result.
Params
optionsWebhooksVerifyOptionsrequired: The options for verifying the webhook.payloadstringrequired: The raw body of the incoming webhook request as a string. This should be the exact payload received from the webhook, without any modifications or parsing, to ensure accurate signature verification.headersRecord<string, string>required: The headers of the incoming webhook request as a record of key-value pairs. These headers should includecontent-digest,signature, andsignature-inputrequired for validating the authenticity of the webhook request.publicKeystringoptional: The public key used to verify the webhook signature. If not provided, the SDK will attempt to retrieve the appropriate public key based on thekeyidspecified in thesignature-inputheader.NOTE
The key ID included in the
signature-inputheader of each incoming webhook is used to identify the key used to sign the request.TIP
The intended pattern is to fetch the public key once, cache it, and then reuse it for all subsequent requests. You'd only need to call the
getSigningKeymethod again if you see a key ID you haven't encountered before (e.g. if MailChannels rotate the key), which is a rare event.The public key can be provided in PEM format or as a raw base64 string. The SDK will handle both formats correctly.
cachebooleanoptional: Whether to cache signing keys fetched from the API by theirkeyId. Defaults totrue.
Response
dataWebhookEvent[] | nullnullableeventWebhookEventTypeguaranteed: The type of event that occurred.customerHandlestringguaranteed: The MailChannels account ID that generated the webhook. If the message was sent by a sub-account, this field contains the sub-account handle.timestampnumberguaranteed: The Unix timestamp (in seconds) when the event occurred; the timezone is always UTC.emailstringoptional: The sender's email address.smtpIdstringoptional: The Message-Id of the message that generated the event.requestIdstringoptional: A unique identifier generated to track the original HTTP request.campaignIdstringoptional: The campaign identifier for the message that generated the event.recipientsstring[]optional: The recipients of the message.userAgentstringoptional: The User-Agent header given when the recipient opened the message. This field is only present foropenandclickevents.ipstringoptional: The IP address of the host that made the HTTP request. This field is only present foropenandclickevents.urlstringoptional: The URL that was clicked by the recipient. This field is only present forclickevents.statusstringoptional: The SMTP status code that caused the bounce. This field is only present forhard-bounced,soft-bounced, anddroppedevents.reasonstringoptional: A human-readable explanation of why the message bounced or was dropped. This field is only present forhard-bounced,soft-bounced, anddroppedevents.
errorErrorResponse | nullnullable: Error information if the operation failed.messagestringguaranteed: A human-readable description of the error.statusCodenumber | nullnullable: The HTTP status code from the API, ornullif the error is not related to an HTTP request. This field is intended for diagnostic use only and should not be relied upon.typestringguaranteed: A string identifier for the type of error. This field is intended for diagnostic use only and should not be relied upon.
TIP
This method returns data as an array of events if the webhook request is authentic and valid. If the verification fails, data will be null, indicating the signature verification failed and the request may not be from MailChannels or could have been tampered with.
Type declarations
Signature
async function verify (options: WebhooksVerifyOptions): Promise<WebhooksVerifyResponse>Response type declarations
interface ErrorResponse {
message: string;
statusCode: number | null;
type: ErrorType;
}type DataResponse<T> = {
data: T;
error: null;
} | {
data: null;
error: ErrorResponse;
};Event type declarations
type WebhookEventType =
| "processed"
| "delivered"
| "open"
| "click"
| "hard-bounced"
| "soft-bounced"
| "dropped"
| "complained"
| "unsubscribed"
| "test";interface WebhookEventProcessed extends WebhookEventBase<"processed"> {}interface WebhookEventDelivered extends WebhookEventBase<"delivered"> {}interface WebhookEventOpen extends WebhookEventBase<"open">, WebhookEventWithTracking {}interface WebhookEventClick extends WebhookEventBase<"click">, WebhookEventWithTracking {
url?: string;
}interface WebhookEventHardBounced extends WebhookEventBase<"hard-bounced">, WebhookEventWithStatus {}interface WebhookEventSoftBounced extends WebhookEventBase<"soft-bounced">, WebhookEventWithStatus {}interface WebhookEventDropped extends WebhookEventBase<"dropped">, WebhookEventWithStatus {}interface WebhookEventComplained extends WebhookEventBase<"complained"> {}interface WebhookEventUnsubscribed extends WebhookEventBase<"unsubscribed"> {}interface WebhookEventTest extends Omit<WebhookEventBase<"test">, "recipients" | "campaignId"> {}type WebhookEvent =
| WebhookEventProcessed
| WebhookEventDelivered
| WebhookEventOpen
| WebhookEventClick
| WebhookEventHardBounced
| WebhookEventSoftBounced
| WebhookEventDropped
| WebhookEventComplained
| WebhookEventUnsubscribed
| WebhookEventTest;Verify type declarations
interface WebhooksVerifyOptions {
payload: string;
headers: Record<string, string> | {
"content-digest": string;
"signature": string;
"signature-input": string;
};
publicKey?: string;
cache?: boolean;
}type WebhooksVerifyResponse = DataResponse<WebhookEvent[]>;Source
Source • Playground • Docs • Tests