Webhooks

Webhooks allow you to subscribe to real-time notifications about various events that occur in MailerSend.

You can create a webhook directly from your MailerSend account and listen for events so your integration can automatically trigger reactions.

Webhooks overview

Setup

Currently, you can create a webhook using the API endpoints listed below or directly from your account. Read more about webhooksopen in new window.

Available events

These are all the events you can listen to and send a notification for.

EventDescription
activity.sentFired when your email is sent from our sending servers. We are now waiting for a response from the receiving servers.
activity.deliveredFired when your email is successfully delivered with no errors.
activity.soft_bouncedFired when your email is not delivered because it soft bounced.
activity.hard_bouncedFired when your email is not delivered.
activity.openedFired when the recipient receives your email and opens it.
activity.clickedFired when the recipient clicks a link in your email.
activity.unsubscribedFired when the recipient unsubscribes from your emails.
activity.spam_complaintFired when the recipient marks your emails as spam or junk.

Payload example

Our responses contain fat payloads, including the information about the event-related object, so there is no need to make an additional API request.

An example of activity.sent event:

{
  "type": "activity.sent",
  "domain_id": "yv69oxl5kl785kw2",
  "created_at": "2020-11-27T10:08:08.298647Z",
  "webhook_id": "2351ndgwr4zqx8ko",
  "url": "https://your-domain.com/webhook",
  "data": {
    "object": "activity",
    "id": "5fc0d006b42c3e16e1774882",
    "type": "sent",
    "created_at": "2020-11-27T10:08:06.258000Z",
    "email": {
      "object": "email",
      "id": "5fc0d003e7a5e7035446aa32",
      "created_at": "2020-11-27T10:08:03.923000Z",
      "from": "test@mailersend.com",
      "subject": "Test email",
      "status": "sent",
      "tags": null,
      "message": {
        "object": "message",
        "id": "5fc0d003f718c90162341852",
        "created_at": "2020-11-27T10:08:03.017000Z"
      },
      "recipient": {
        "object": "recipient",
        "id": "5f6887d6fd913a6523283fd2",
        "email": "test@mailersend.com",
        "created_at": "2020-09-21T11:00:38.184000Z"
      }
    },
    "template_id": "7nxe3yjmeq28vp0k",
    "morph": null
  }
}

Security

Webhook requests made by MailerSend include a Signature header. It contains a string generated by hashing the data sent to your webhook endpoint with an individual Signing Secret. A signing secret is a random string that is generated when you create a webhook.

Verifying a signature:

// $signature - a header sent by MailerSend, please refer to your framework
// or PHP manual on how to read the Signature header

// $requestContent - please refer to your framework or PHP manual on how to read the request content

$computedSignature = hash_hmac('sha256', $requestContent, $signingSecret);
return hash_equals($signature, $computedSignature);

Retrying failed webhooks

When your webhook receives a response other than a 2xx code from your endpoint URL, or if the endpoint doesn’t respond within 3 seconds, it will show up as a failed attempt in the log section of your webhook. If it receives a 2xx, then it will show as a success.

If a webhook call fails, MailerSend will retry the call a couple of times, waiting 10 seconds between the first and second attempt and 100 seconds between the second and the third attempt. This is to avoid hammering the application you want to send the information to.

Useful tools

Webhook.siteopen in new window or Pipedream.comopen in new window are useful tools for testing webhooks quickly, seeing how it works, and inspecting what's being sent—without any coding on your side.

FAQs

  • How do I track the Message I've sent via SMTP relay back to a webhook?

If the message was sent successfully, our SMTP relay will send you back a 250 Message queued as XXXXXX response. This can be parsed to an ID used in our Messages endpoints, and in webhooks that Message ID can be found at data.email.message.id.

If you want full interoperability, we encourage you to use our Email API for the best results.

Get a list of webhooks

If you want to retrieve information about webhooks, use this GET request:

GET https://api.mailersend.com/v1/webhooks

Request parameters

ParameterTypeRequiredLimitationsDetails
domain_idstringyes
use MailerSend\MailerSend;

$mailersend = new MailerSend(['api_key' => 'key']);

$mailersend->webhooks->get('domain_id');

More examplesopen in new window

import 'dotenv/config';
import { MailerSend} from "mailersend";

const mailerSend = new MailerSend({
  apiKey: process.env.API_KEY,
});

mailerSend.email.webhook.list("domain_id")
  .then((response) => console.log(response.body))
  .catch((error) => console.log(error.body));

More examplesopen in new window

from mailersend import webhooks

api_key = "API key here"

mailer = webhooks.NewWebhook(api_key)

mailer.get_webhooks("domain-id")

More examplesopen in new window

package main

import (
	"context"
	"log"
	"time"
	
	"github.com/mailersend/mailersend-go"
)

var APIKey = "Api Key Here"

func main() {
	// Create an instance of the mailersend client
	ms := mailersend.NewMailersend(APIKey)

	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	domainID := "domain-id"
	
	options := &mailersend.ListWebhookOptions{
		DomainID: domainID,
		Limit:    25,
	}

	_, _, err := ms.Webhook.List(ctx, options)
	if err != nil {
		log.Fatal(err)
	}
}

More examplesopen in new window

import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.exceptions.MailerSendException;
import com.mailersend.sdk.webhooks.Webhook;
import com.mailersend.sdk.webhooks.WebhooksList;

public void GetWebhooks() {
    
    MailerSend ms = new MailerSend();
    ms.setToken("mailersend token");
    
    try {
        
        WebhooksList list = ms.webhooks().getWebhooks("domain id");
        
        for (Webhook webhook : list.webhooks) {
            
            System.out.println(webhook.name);
        }
        
    } catch (MailerSendException e) {
        
        e.printStackTrace();
    }
}

More examplesopen in new window

require "mailersend-ruby"

ms_webhooks = Mailersend::Webhooks.new
ms_webhooks.list(domain_id: "xxx2241ll")

More examplesopen in new window

Get a webhook

To retrieve information about a single webhook, use this GET request:

GET https://api.mailersend.com/v1/webhooks/{webhook_id}
use MailerSend\MailerSend;

$mailersend = new MailerSend(['api_key' => 'key']);

$mailersend->webhooks->find('webhook_id');

More examplesopen in new window

import 'dotenv/config';
import { MailerSend} from "mailersend";

const mailerSend = new MailerSend({
  apiKey: process.env.API_KEY,
});

mailerSend.email.webhook.single("webhook_id")
  .then((response) => console.log(response.body))
  .catch((error) => console.log(error.body));

More examplesopen in new window

from mailersend import webhooks

api_key = "API key here"

mailer = webhooks.NewWebhook(api_key)

mailer.get_webhook_by_id("webhook-id")

More examplesopen in new window

package main

import (
	"context"
	"log"
	"time"
	
	"github.com/mailersend/mailersend-go"
)

var APIKey = "Api Key Here"

func main() {
	// Create an instance of the mailersend client
	ms := mailersend.NewMailersend(APIKey)

	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()
	
	webhookID := "webhook-id"
	
	_, _, err := ms.Webhook.Get(ctx, webhookID)
	if err != nil {
		log.Fatal(err)
	}
}

More examplesopen in new window

import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.exceptions.MailerSendException;
import com.mailersend.sdk.webhooks.Webhook;

public void GetSingleWebhook() {
    
    MailerSend ms = new MailerSend();
    ms.setToken("mailersend token");
    
    try {
        
        Webhook webhook = ms.webhooks().getWebhook("webhook id");
        
        System.out.println(webhook.name);
        
    } catch (MailerSendException e) {
        
        e.printStackTrace();
    }
}

More examplesopen in new window

require "mailersend-ruby"

ms_webhooks = Mailersend::Webhooks.new
ms_webhooks.single(webhook_id: "zzz2241ll")

More examplesopen in new window

Create a webhook

Create a webhook using this POST request:

POST https://api.mailersend.com/v1/webhooks/

Request parameters

ParameterTypeRequiredLimitationsDetails
urlurlyesMax: 191
namestringyesMax: 191
eventsarrayyes
enabledbooleanoptional
domain_idstringyesExisting hashed domain ID.
use MailerSend\Helpers\Builder\WebhookParams;
use MailerSend\MailerSend;

$mailersend = new MailerSend(['api_key' => 'key']);

$mailersend->webhooks->create(
    new WebhookParams('https://webhook_url', 'Webhook name', WebhookParams::ALL_ACTIVITIES, 'domain_id')
);

// Or a disabled webhook

$mailersend->webhooks->create(
    new WebhookParams('https://webhook_url', 'Webhook name', WebhookParams::ALL_ACTIVITIES, 'domain_id', false)
);

More examplesopen in new window

import 'dotenv/config';
import { EmailWebhook, EmailWebhookEventType, MailerSend } from "mailersend";

const mailerSend = new MailerSend({
  apiKey: process.env.API_KEY,
});

const emailWebhook = new EmailWebhook()
  .setName("Webhook Name")
  .setUrl("https://example.com")
  .setDomainId("domain_id")
  .setEnabled(true)
  .setEvents([EmailWebhookEventType.SENT, EmailWebhookEventType.OPENED]);

mailerSend.email.webhook.create(emailWebhook)
  .then((response) => console.log(response.body))
  .catch((error) => console.log(error.body));

More examplesopen in new window

from mailersend import webhooks

api_key = "API key here"

webhookEvents = ['activity.sent', 'activity.delivered']

webhook = webhooks.NewWebhook(api_key)
webhook.set_webhook_url("https://webhooks.mysite.com")
webhook.set_webhook_name("my first webhook")
webhook.set_webhook_events(webhookEvents)
webhook.set_webhook_domain("domain-id")

webhook.create_webhook()

More examplesopen in new window

package main

import (
	"context"
	"log"
	"time"
	
	"github.com/mailersend/mailersend-go"
)

var APIKey = "Api Key Here"

func main() {
	// Create an instance of the mailersend client
	ms := mailersend.NewMailersend(APIKey)

	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	domainID := "domain-id"
	events := []string{"activity.sent", "activity.opened"}

	createOptions := &mailersend.CreateWebhookOptions{
		Name:     "Webhook",
		DomainID: domainID,
		URL:      "https://test.com",
		Enabled:  mailersend.Bool(false),
		Events:   events,
	}
	
	_, _, err := ms.Webhook.Create(ctx, createOptions)
	if err != nil {
		log.Fatal(err)
	}
}

More examplesopen in new window

import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.exceptions.MailerSendException;
import com.mailersend.sdk.webhooks.Webhook;

public void CreateWebhook() {
    
    MailerSend ms = new MailerSend();
    ms.setToken("mailersend token");
    
    try {
        
        Webhook webhook = ms.webhooks().builder()
            .name("Webhook name")
            .url("Webhook url")
            .addEvent(WebhookEvents.ACTIVITY_OPENED)
            .addEvent(WebhookEvents.ACTIVITY_CLICKED)
            .createWebhook("domain id");
        
        System.out.println(webhook.name);
        
    } catch (MailerSendException e) {
        
        e.printStackTrace();
    }
}

More examplesopen in new window

require "mailersend-ruby"

ms_webhooks = Mailersend::Webhooks.new
ms_webhooks.create(domain_id: "xxx2241ll", url: "https://domain.com/hook", name: "Webhook", events: ["activity.sent", "activity.delivered"], enabled: true)

More examplesopen in new window

Update a webhook

Update a webhook using this PUT request:

PUT https://api.mailersend.com/v1/webhooks/{webhook_id}
ParameterTypeRequiredLimitationsDetails
urlurloptional
namestringoptionalMax: 191
eventsarrayoptional
enabledbooleanoptional
use MailerSend\MailerSend;
use MailerSend\Helpers\Builder\WebhookParams;

$mailersend = new MailerSend(['api_key' => 'key']);

$mailersend->webhooks->update('webhook_id', 'https://webhook_url', 'Webhook name', WebhookParams::ALL_ACTIVITIES);

// Enable webhook
$mailersend->webhooks->update('webhook_id', 'https://webhook_url', 'Webhook name', WebhookParams::ALL_ACTIVITIES, true);

// Disable webhook
$mailersend->webhooks->update('webhook_id', 'https://webhook_url', 'Webhook name', WebhookParams::ALL_ACTIVITIES, false);

More examplesopen in new window

import 'dotenv/config';
import { EmailWebhook, EmailWebhookEventType, MailerSend } from "mailersend";

const mailerSend = new MailerSend({
  apiKey: process.env.API_KEY,
});

const emailWebhook = new EmailWebhook()
  .setName("Webhook Name 2")
  .setEnabled(false)
  .setEvents([EmailWebhookEventType.SENT, EmailWebhookEventType.OPENED]);

mailerSend.email.webhook.update("webhook_id", emailWebhook)
  .then((response) => console.log(response.body))
  .catch((error) => console.log(error.body));

More examplesopen in new window

from mailersend import webhooks

api_key = "API key here"

webhook = webhooks.NewWebhook(api_key)

webhook.update_webhook("webhook-id", "name", "a new webhook name")

More examplesopen in new window

package main

import (
	"context"
	"log"
	"time"
	
	"github.com/mailersend/mailersend-go"
)

var APIKey = "Api Key Here"

func main() {
	// Create an instance of the mailersend client
	ms := mailersend.NewMailersend(APIKey)

	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	webhookID := "webhook-id"
	events := []string{"activity.clicked"}

	updateOptions := &mailersend.UpdateWebhookOptions{
		WebhookID: webhookID,
		Enabled:   mailersend.Bool(true),
		Events:    events,
	}
	
	_, _, err := ms.Webhook.Update(ctx, updateOptions)
	if err != nil {
		log.Fatal(err)
	}
}

More examplesopen in new window

import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.exceptions.MailerSendException;
import com.mailersend.sdk.webhooks.Webhook;

public void UpdateWebhook() {
    
    MailerSend ms = new MailerSend();
    ms.setToken("mailersend token");
    
    try {
        
        Webhook webhook = ms.webhooks()
                .builder()
                .name("Updated webhook name")
                .updateWebhook("webhook id");
                    
        System.out.println(webhook.name);
        
    } catch (MailerSendException e) {
        
        e.printStackTrace();
    }
}

More examplesopen in new window

require "mailersend-ruby"

ms_webhooks = Mailersend::Webhooks.new
ms_webhooks.update(webhook_id: "zzz2241ll", enabled: false)

More examplesopen in new window

Delete a webhook

Delete a webhook using this DELETE request:

DELETE https://api.mailersend.com/v1/webhooks/{webhook_id}
use MailerSend\MailerSend;

$mailersend = new MailerSend(['api_key' => 'key']);

$mailersend->webhooks->delete('webhook_id');

More examplesopen in new window

import 'dotenv/config';
import { MailerSend} from "mailersend";

const mailerSend = new MailerSend({
  apiKey: process.env.API_KEY,
});

mailerSend.email.webhook.delete("webhook_id")
  .then((response) => console.log(response.body))
  .catch((error) => console.log(error.body));

More examplesopen in new window

from mailersend import webhooks

api_key = "API key here"

webhook = webhooks.NewWebhook(api_key)

webhook.delete_webhook("webhook-id")

More examplesopen in new window

package main

import (
	"context"
	"log"
	"time"
	
	"github.com/mailersend/mailersend-go"
)

var APIKey = "Api Key Here"

func main() {
	// Create an instance of the mailersend client
	ms := mailersend.NewMailersend(APIKey)

	ctx := context.Background()
	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
	defer cancel()

	webhookID := "webhook-id"
	
	_, err := ms.Webhook.Delete(ctx, webhookID)
	if err != nil {
		log.Fatal(err)
	}
}

More examplesopen in new window

import com.mailersend.sdk.MailerSend;
import com.mailersend.sdk.MailerSendResponse;
import com.mailersend.sdk.exceptions.MailerSendException;

public void DeleteWebhook() {
    
    MailerSend ms = new MailerSend();
    ms.setToken("mailersend token");
    
    try {
        
        MailerSendResponse response = ms.webhooks().deleteWebhook("webhook id");
            
        System.out.println(response.responseStatusCode);
        
    } catch (MailerSendException e) {
        
        e.printStackTrace();
    }
}

More examplesopen in new window

require "mailersend-ruby"

ms_webhooks = Mailersend::Webhooks.new
ms_webhooks.delete(webhook_id: "zzz2241ll")

More examplesopen in new window

Last Updated: