Skip to content

Email Events (Resend)

Synapse receives webhook events from Resend for email delivery tracking. These events update email log records, create contact activity timeline entries, and power your analytics dashboard.


Webhook Endpoint

POST https://synapse-api.pyrx.tech/v1/webhooks/resend

This endpoint is configured automatically when you set up Resend integration in your workspace settings.

Note

You do not need to configure this webhook yourself. Synapse manages the Resend webhook subscription. This documentation is for understanding how email tracking works.


Supported Events

Resend EventSynapse Event NameDescriptionAction
email.sentemail_sentEmail accepted by Resend for deliveryLogged only (already marked as sent during send)
email.deliveredemail_deliveredEmail accepted by recipient's mail serveremail_logs.status set to delivered, delivered_at set
email.delivery_delayedemail_delivery_delayedTemporary delivery delay (soft bounce, server busy)Delay reason logged; status unchanged (Resend retries automatically)
email.openedemail_openedRecipient opened the email (pixel tracking)email_logs.first_opened_at set on first open
email.clickedemail_clickedRecipient clicked a link in the emailemail_logs.first_clicked_at set on first click
email.bouncedemail_bouncedEmail permanently rejected (hard bounce)email_logs.status set to bounced, contact auto-unsubscribed
email.complainedemail_spam_reportedRecipient marked the email as spamemail_logs.status set to complained, contact auto-unsubscribed
email.failedemail_failedSend failure on Resend's sideemail_logs.status set to failed, error message captured
email.suppressedemail_suppressedEmail blocked by Resend suppression listemail_logs.status set to suppressed, reason captured

Webhook Payload

Resend sends individual event objects (not batches). Each event has this structure:

json
{
"type": "email.delivered",
"created_at": "2026-04-01T10:30:00.000Z",
"data": {
"email_id": "re_abc123def456",
"from": "[email protected]",
"to": ["[email protected]"],
"subject": "Your claim has been submitted",
"headers": [
{"name": "X-Email-Log-Id", "value": "8f14e45f-ceea-467f-a83c-01a01ba3c5db"}
]
}
}

Synapse matches events to email log records using the X-Email-Log-Id custom header, which is injected into every outgoing email. If the header is missing, Synapse falls back to matching by data.email_id against the provider_message_id field.


Signature Verification

Resend uses Svix for webhook signing. Verification uses three headers:

HeaderDescription
svix-idUnique message identifier
svix-timestampTimestamp used in signature generation
svix-signatureHMAC signature of the payload

See Signature Verification for implementation details and code examples.


Event Processing

Delivered

When an email is delivered, Synapse updates the log record:

email_logs.status = 'delivered'
email_logs.delivered_at = event.created_at

Opened

First-open tracking (subsequent opens are counted but do not update the timestamp):

email_logs.first_opened_at = event.created_at (only if NULL)
email_logs.status = 'opened'
Warning

Open tracking relies on a 1x1 pixel image. Email clients that block images (Apple Mail Privacy, Outlook) may not register opens. Open rates should be treated as a lower-bound estimate.

Clicked

First-click tracking:

email_logs.first_clicked_at = event.created_at (only if NULL)
email_logs.status = 'clicked'

Bounced (Hard Bounce)

Hard bounces indicate a permanent delivery failure:

email_logs.status = 'bounced'
email_logs.bounced_at = event.created_at
email_logs.error_message = data.bounce.message
contact.subscription_status = 'unsubscribed' (automatic)
Warning

Contacts that bounce are automatically unsubscribed to protect your sender reputation. Do not re-subscribe contacts who have bounced -- verify the email address first.

Complained (Spam Report)

When a recipient marks your email as spam:

email_logs.status = 'complained'
email_logs.error_message = 'Spam complaint'
contact.subscription_status = 'unsubscribed' (automatic)

Contacts who file spam complaints are automatically unsubscribed and will not receive any further emails. This is enforced at the delivery pipeline level.

Delivery Delayed

Resend fires this event when delivery is temporarily delayed (soft bounce, recipient server busy). Synapse logs the delay reason but does not change the email status -- Resend retries delivery automatically.

email_logs.error_message = 'Delivery delayed: <reason>'
email_logs.status = (unchanged -- remains 'sent' or 'queued')

Failed

A send failure on Resend's side (infrastructure error, rejected by Resend):

email_logs.status = 'failed'
email_logs.error_message = data.error.message

Suppressed (Provider)

The email was blocked because the recipient is on Resend's suppression list (previous hard bounce or spam complaint on Resend's side):

email_logs.status = 'suppressed'
email_logs.error_message = data.suppression.message
Note

Provider-level suppression (from Resend's suppression list) is different from NLT suppression (from the required modifier). Both result in a suppressed status, but the error message indicates the cause.


Activity Timeline

For each recognized event, Synapse creates an Event record on the contact's activity timeline. Timeline events include:

  • email_log_id -- the internal email log record
  • email_subject -- the rendered email subject
  • to -- the recipient address
  • email_provider -- always "resend" for Resend events
  • resend_email_id -- the Resend email ID (when available)
  • url -- the clicked link URL (for click events)

Viewing Email Events

Dashboard

Navigate to Email Logs in the Synapse dashboard to see per-email delivery status, open/click tracking, and bounce details.

API

Use the Email Logs API to query email logs programmatically:

bash
curl "https://synapse-api.pyrx.tech/v1/email-logs?status=bounced&date_from=2026-04-01" \
-H "Authorization: Bearer <jwt>"

Contact Status Lifecycle

subscribed ──(hard bounce)──> unsubscribed
subscribed ──(spam report)──> unsubscribed
subscribed ──(user opt-out)──> unsubscribed
StatusCan Receive EmailTriggered By
subscribedYesDefault state, manual re-subscribe
unsubscribedNoHard bounce, spam complaint, user opt-out