What are Webhooks?
Webhooks allow you to receive real-time notifications when events occur in your Transmit account. Subscribe to specific event types and receive HTTP POST requests to your endpoint whenever those events happen.
Available Event Types
Email Events
Triggered when an email has been successfully submitted to the email provider for delivery. Example Payload: {
"id" : "evt_email123_sent" ,
"type" : "email.sent" ,
"created_at" : 1704894225000 ,
"data" : {
"email_id" : "email_abc123" ,
"from" : "[email protected] " ,
"to" : [ "[email protected] " ],
"subject" : "Welcome to Transmit" ,
"sent_at" : 1704894225000
}
}
Triggered when an email has been successfully delivered to the recipient’s mail server. Example Payload: {
"id" : "evt_email123_delivered" ,
"type" : "email.delivered" ,
"created_at" : 1704894230000 ,
"data" : {
"email_id" : "email_abc123" ,
"from" : "[email protected] " ,
"to" : [ "[email protected] " ],
"subject" : "Welcome to Transmit" ,
"delivered_at" : 1704894230000 ,
"provider" : "aws_ses" ,
"provider_message_id" : "0000014a-f4d4-4f4f-8f4f-4f4f4f4f4f4f"
}
}
Triggered when a recipient opens an email (tracking pixels enabled). Example Payload: {
"id" : "evt_email123_opened" ,
"type" : "email.opened" ,
"created_at" : 1704894245000 ,
"data" : {
"email_id" : "email_abc123" ,
"to" : "[email protected] " ,
"opened_at" : 1704894245000 ,
"user_agent" : "Mozilla/5.0..." ,
"ip_address" : "192.0.2.1"
}
}
Triggered when a recipient clicks a link in an email (link tracking enabled). Example Payload: {
"id" : "evt_email123_clicked" ,
"type" : "email.clicked" ,
"created_at" : 1704894250000 ,
"data" : {
"email_id" : "email_abc123" ,
"to" : "[email protected] " ,
"clicked_at" : 1704894250000 ,
"link" : "https://example.com/welcome" ,
"user_agent" : "Mozilla/5.0..." ,
"ip_address" : "192.0.2.1"
}
}
Triggered when an email bounces (hard or soft bounce). Example Payload: {
"id" : "evt_email123_bounced" ,
"type" : "email.bounced" ,
"created_at" : 1704894260000 ,
"data" : {
"email_id" : "email_abc123" ,
"to" : "[email protected] " ,
"bounced_at" : 1704894260000 ,
"bounce_type" : "hard" ,
"bounce_reason" : "mailbox_full" ,
"diagnostic_code" : "550 5.1.1 User unknown"
}
}
Triggered when a recipient marks an email as spam. Example Payload: {
"id" : "evt_email123_complained" ,
"type" : "email.complained" ,
"created_at" : 1704894270000 ,
"data" : {
"email_id" : "email_abc123" ,
"to" : "[email protected] " ,
"complained_at" : 1704894270000 ,
"feedback_type" : "abuse"
}
}
Domain Events
Triggered when a new domain is added to your account. Example Payload: {
"id" : "evt_domain123_added" ,
"type" : "domain.added" ,
"created_at" : 1704894280000 ,
"data" : {
"domain_id" : "domain_abc123" ,
"domain" : "example.com" ,
"apex_domain" : "example.com" ,
"nickname" : "Production Domain" ,
"status" : "pending"
}
}
Triggered when a domain has been successfully verified. Example Payload: {
"id" : "evt_domain123_verified" ,
"type" : "domain.verified" ,
"created_at" : 1704894290000 ,
"data" : {
"domain_id" : "domain_abc123" ,
"domain" : "example.com" ,
"verified_at" : 1704894290000
}
}
domain.failed_verification
Triggered when domain verification fails. Example Payload: {
"id" : "evt_domain123_failed" ,
"type" : "domain.failed_verification" ,
"created_at" : 1704894300000 ,
"data" : {
"domain_id" : "domain_abc123" ,
"domain" : "example.com" ,
"reason" : "DNS records not found"
}
}
Triggered when a domain is removed from your account. Example Payload: {
"id" : "evt_domain123_removed" ,
"type" : "domain.removed" ,
"created_at" : 1704894310000 ,
"data" : {
"domain_id" : "domain_abc123" ,
"domain" : "example.com"
}
}
Suppression Events
Triggered when an email or phone number is added to the suppression list. Example Payload: {
"id" : "evt_suppression123_added" ,
"type" : "suppression.added" ,
"created_at" : 1704894370000 ,
"data" : {
"identifier" : "[email protected] " ,
"identifier_type" : "email" ,
"suppression_type" : "hard_bounce" ,
"reason" : "mailbox_full"
}
}
Triggered when an email or phone number is removed from the suppression list. Example Payload: {
"id" : "evt_suppression123_removed" ,
"type" : "suppression.removed" ,
"created_at" : 1704894380000 ,
"data" : {
"identifier" : "[email protected] " ,
"identifier_type" : "email"
}
}
SMS Events (Coming Soon)
Setting Up Webhooks
Create an Endpoint
Create an HTTPS endpoint on your server to receive webhook events
Add Webhook in Dashboard
Go to Settings → Webhooks → Add Webhook
Enter URL and Select Events
Enter your endpoint URL and choose which events to receive
Test Your Webhook
Use the test button to send a sample payload
Webhook Payload
Example webhook payload:
{
"event" : "email.delivered" ,
"timestamp" : "2025-01-10T14:23:45Z" ,
"data" : {
"id" : "email_abc123" ,
"to" : "[email protected] " ,
"from" : "[email protected] " ,
"subject" : "Welcome!" ,
"status" : "delivered" ,
"deliveredAt" : "2025-01-10T14:23:45Z"
}
}
Handling Webhooks
import express from 'express' ;
import { Transmit } from 'transmitdev' ;
const app = express ();
app . use ( express . json ());
app . post ( '/webhooks/transmit' , async ( req , res ) => {
const { event , data } = req . body ;
switch ( event ) {
case 'email.delivered' :
console . log ( `Email ${ data . id } delivered to ${ data . to } ` );
break ;
case 'email.bounced' :
console . log ( `Email ${ data . id } bounced: ${ data . bounceReason } ` );
break ;
case 'email.opened' :
console . log ( `Email ${ data . id } opened by ${ data . to } ` );
break ;
}
res . status ( 200 ). send ( 'OK' );
});
app . listen ( 3000 );
Verifying Webhooks
Transmit signs all webhook requests. Verify the signature to ensure authenticity:
import crypto from 'crypto' ;
function verifyWebhookSignature ( payload , signature , secret ) {
const expectedSignature = crypto
. createHmac ( 'sha256' , secret )
. update ( JSON . stringify ( payload ))
. digest ( 'hex' );
return crypto . timingSafeEqual (
Buffer . from ( signature ),
Buffer . from ( expectedSignature )
);
}
app . post ( '/webhooks/transmit' , ( req , res ) => {
const signature = req . headers [ 'x-transmit-signature' ];
const secret = process . env . TRANSMIT_WEBHOOK_SECRET ;
if ( ! verifyWebhookSignature ( req . body , signature , secret )) {
return res . status ( 401 ). send ( 'Invalid signature' );
}
// Process webhook...
res . status ( 200 ). send ( 'OK' );
});
Retries
Transmit will retry failed webhooks:
Initial retry: after 1 minute
Second retry: after 5 minutes
Third retry: after 30 minutes
Final retry: after 2 hours
Your endpoint must return a 2xx status code within 30 seconds to be considered successful.
Best Practices
Return 200 Quickly Process webhooks asynchronously. Return 200 immediately, then process in background.
Verify Signatures Always verify webhook signatures to prevent spoofing
Handle Duplicates Webhooks may be delivered more than once. Use idempotency keys.
Log Everything Log all webhook events for debugging and auditing