Email v3 Webhooks

Email Status Event Webhook Configuration

This section explains how users can configure webhooks in the application and verify signatures using the provided signature verification secret for enhanced security.

Adding a Webhook URL

Users can specify a webhook URL in the application where events will be sent. The webhook URL should be a publicly accessible endpoint capable of handling HTTP POST requests.

Steps to Add a Webhook:
  • Go to Settings -> API Settings -> Email -> Status Update. Easify Email Webhook Settings
Webhook Event Structure:

When an event is triggered, the application will send a POST request to the configured webhook URL with the following headers and body:

Headers
  • X-Easify-Signature: A Base64-encoded signature of the payload, generated using the verification secret.
  • X-Easify-Timestamp: The UNIX timestamp of the request.
Payload

The POST body contains the event data. Example:

[
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "processed",
    "category": ["cat facts"],
    "sg_event_id": "4mA9l_cHKMlUEEkEuZc3****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "deferred",
    "category": ["cat facts"],
    "sg_event_id": "eKRNAYmTi2jlSdymGKZs****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****",
    "response": "400 try again later",
    "attempt": "5"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "delivered",
    "category": ["cat facts"],
    "sg_event_id": "GuGhSahRjAq7Ci2m_FF****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****",
    "response": "250 OK"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "open",
    "category": ["cat facts"],
    "sg_event_id": "ABygEH8H1JfhmJQnDEtz****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****",
    "useragent": "Mozilla/4.0 (compatible; MSIE 6.1; Windows XP; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "ip": "255.255.255.***"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "click",
    "category": ["cat facts"],
    "sg_event_id": "RlVuHd4e6J1KX1c3UXtu****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****",
    "useragent": "Mozilla/4.0 (compatible; MSIE 6.1; Windows XP; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "ip": "255.255.255.***",
    "url": "http://www.sendgrid.com/"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "bounce",
    "category": ["cat facts"],
    "sg_event_id": "SMrxoGPPPugXFS_tLM0b****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****",
    "reason": "500 unknown recipient",
    "status": "5.0.*"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "dropped",
    "category": ["cat facts"],
    "sg_event_id": "00udEyCl5KqOB8aviHUI****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****",
    "reason": "Bounced Address",
    "status": "5.0.*"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "spamreport",
    "category": ["cat facts"],
    "sg_event_id": "cxwA33aN6INAhHxR4eEl****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "unsubscribe",
    "category": ["cat facts"],
    "sg_event_id": "6KQ3MWWC3jY5Fm9PgYxE****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****"
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "group_unsubscribe",
    "category": ["cat facts"],
    "sg_event_id": "E9VM-8dxczn2XE1nstn4****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****",
    "useragent": "Mozilla/4.0 (compatible; MSIE 6.1; Windows XP; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "ip": "255.255.255.***",
    "url": "http://www.sendgrid.com/",
    "asm_group_id": 1*
  },
  {
    "additional_data" : "{'name':'John','id':'232'}",
    "email": "example@test.com",
    "email_id": "675",
    "timestamp": 1734081***,
    "smtp-id": "<14c5d75ce93.dfd.64b469@ismtpd-***>",
    "event": "group_resubscribe",
    "category": ["cat facts"],
    "sg_event_id": "Q3zFzf5hk2ec_Ck5330R****",
    "sg_message_id": "14c5d75ce93.dfd.64b469.filter0001.16648.5515E0B8****",
    "useragent": "Mozilla/4.0 (compatible; MSIE 6.1; Windows XP; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
    "ip": "255.255.255.***",
    "url": "http://www.sendgrid.com/",
    "asm_group_id": 1*
  }
]

* You can use the status in the response by checking both the email and email_id values

Steps for Validating the Signature

  1. Extract Header and Payload Information

X-Easify-Timestamp from the request headers.

X-Easify-Signature from the request headers.

Raw JSON payload from the request body.

  1. Recreate the Signature

To validate the signature, recreate it using the following process:

Use the raw JSON payload as the input:

$payloadString = json_encode($payload);

Generate an HMAC signature using the shared webhook_secret:

$computedSignature = hash_hmac('sha256', $payloadString,  $webhook_secret);

Encode the generated signature in Base64

$computedSignatureBase64 = base64_encode($computedSignature);
  1. Compare the Signatures

Compare the computed signature with the one received in the X-Easify-Signature header:

if (hash_equals($computedSignatureBase64, $receivedSignature)) {

// Signature is valid

} else {

// Signature is invalid

}
  1. Validate the Timestamp

To prevent replay attacks, ensure that the timestamp in X-Easify-Timestamp is within an acceptable range (e.g., ±5 minutes):

$currentTime = time();

if (abs($currentTime - $receivedTimestamp) > 300) {

// 5 minutes

// Reject the request as expired

}

pixel for linkedin