POST / email/send
Base URL: https://backend.easify.app/api/v3
This endpoint allows sending emails from Easify, supporting multiple recipients, CC, and BCC.
There is a rate limit of 15 requests per minute. If you exceed this limit, you will receive a 429 Too Many Requests status, along with a message indicating when you can try again.
Authentication
The Easify API token used for authentication is passed in the header as a Bearer token, which can be obtained from the easify app under Settings > API Settings.
Headers
Authorization string required Bearer << YOUR_EASIFY_API_TOKEN_HERE >>
Request Body
sender string |
Sender’s Email Address (can be obtained from the email-senders API response) |
Required |
receiver array |
Receiver (s) Email Address (A maximum of 50 emails are allowed in the array) |
Required |
cc array |
CC Email Address (s) (A maximum of 50 emails are allowed in the array) |
Optional |
bcc array |
BCC Email Address (s) (A maximum of 50 emails are allowed in the array) |
Optional |
subject string | subject for Email | Required |
message string | Email message body | Required without Attachment |
attachment string | file | Email Attachment | Required without Message |
additional_data json | Additional data to send with the email, which will be returned in the email status event webhook | Optional |
from_name string | The user can set the from_name for the email. By default, the selected sender's from_name will be used | Optional |
Sample Params and Success Response:
Request
{
"sender": "sender@easify.app",
"receiver": ["receiver1@easify.app", "receiver2@easify.app"],
"cc": ["cc@easify.app"],
"bcc": ["bcc@easify.app"],
"subject": "Subject",
"message": "Hai",
"from_name": "easify",
"additional_data": { "name" : "John", "id" : "232"}
}
Success Response:
{
"status": true,
"message": "Email processed successfully",
"data": {
"email_id": "674"
}
}
Api Response Status
Case | Status Code | Response |
---|---|---|
If the user does not provide a token in the header or provides an invalid token | 401 |
{
"status":false,
"message":"Unauthenticated",
"errors":[]
}
|
If the user's subscription has ended | 402 |
{
"status":false,"message":"You need to recharge your account to proceed","errors":[]
}
|
If user provided invalid sender email address | 400 |
{
"status": false,
"message": "Invalid Sender!",
"errors": []
}
|
If the user does not have enough credits to send the email | 400 |
{
"status": false,
"message": "Sorry, you do not have enough credits to send this email. Please recharge for more.",
"errors": []
}
|
If the user does not have an enterprise plan | 403 |
{
"status": false,
"message": "Access denied. Your current plan does not allow access to this feature. Please upgrade to the Enterprise plan.",
"errors": []
}
|
If the user passes an invalid datatype in the receiver instead of an array | 422 |
{
"message":"The receiver field must be an array.",
"errors":
{
"receiver":["The receiver field must be an array."
]
}
}
|
If the user passes an invalid datatype in the cc instead of an array | 422 |
{
"message":"The cc field must be an array.",
"errors":{
"cc":["The cc field must be an array."]
}
}
|
If the user passes an invalid datatype in the bcc instead of an array | 422 |
{
"message":"The bcc field must be an array.",
"errors":{
"bcc":["The bcc field must be an array."]
}
}
|
If the user passes duplicate email addresses | 422 |
{
"message":"Duplicate email addresses are not allowed across receiver, cc, and bcc.",
"errors":{
"receiver":["Duplicate email addresses are not allowed across receiver, cc, and bcc."]
}
}
|
If the user exceeds the allowed rate limit for requests | 429 |
{
"status":false,
"message":"Too many requests. Try again in 59 seconds",
"errors":[]
}
|
PHP-cURL
php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://backend.easify.app/api/v3/email/send',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array(
'sender' => 'sender@easify.app',
'receiver[]' => 'easify@easify.app',
'subject' => 'Subject Content',
'message' => 'Message',
'cc[]' => 'cc@easify.app',
'bcc[]' => 'bcc@easify.app'
),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer 1260|b9eb1d4f-8a6f-47eb-83fb-c155afc2****'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Email 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
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
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.
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);
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
}
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
}