Webhooks

This API allows you to create, access, and delete webhooks programmatically.

The webhooks API endpoint is available at:

v3/domains/<domain>/webhooks

Supported webhooks, and their documentation, are listed below:

Webhook Name Documentation
clicked Tracking Clicks
complained Tracking Spam Complaints
delivered Tracking Deliveries
opened Tracking Opens
permanent_fail Tracking Failures
temporary_fail Tracking Failures
unsubscribed Open and Click Bot Detection
GET /domains/<domain>/webhooks

Returns a list of webhooks set for the specified domain.

Parameter Description
domain Name of the domain
GET /domains/<domain>/webhooks/<webhookname>

Returns details about a the webhook specified in the URL.

Parameter Description
domain Name of the domain
id Name of the webhook. (See above for supported webhooks)
POST /domains/<domain>/webhooks

Creates a new webhook.

Note

When adding a Clicked or Opened webhook, ensure that you also have tracking enabled.

Parameter Description
domain Name of the domain
id Name of the webhook. (See above for supported webhooks)
url URL for the webhook event. May be repeated up to 3 times.
PUT /domains/<domain>/webhooks/<webhookname>

Updates an existing webhook.

Parameter Description
domain Name of the domain
webhookname Name of the webhook. (See above for supported webhooks)
url URL for the webhook event. May be repeated up to 3 times.
DELETE /domains/<domain>/webhooks/<webhookname>

Deletes an existing webhook.

Note

Mailgun imposes a rate limit for the Webhook API endpoint. Users may issue no more than 300 requests per minute, per account. See the resultant rate limit response below.

Parameter Description
domain Name of the domain
webhookname Name of the webhook. (See above for supported webhooks)

Examples

Return a list of webhooks set for the specified domain.

curl -s --user 'api:YOUR_API_KEY' -G \
    https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks
import com.mailgun.api.v3.MailgunWebhooksApi;
import com.mailgun.model.webhooks.WebhookListResult;;

// ...

public WebhookListResult getWebhooks() {
    MailgunWebhooksApi mailgunWebhooksApi = MailgunClient.config(API_KEY).createApi(MailgunWebhooksApi.class);

    return mailgunWebhooksApi.getAllWebhooks(YOUR_DOMAIN_NAME);
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = Mailgun::create('PRIVATE_API_KEY', 'https://API_HOSTNAME');
$domain   = 'YOUR_DOMAIN_NAME';

# Issue the call to the client.
$result = $mgClient->webhooks()->index($domain)
def get_bounces():
    return requests.get(
        "https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks",
        auth=("api", "YOUR_API_KEY"))
def get_webhooks
  RestClient.get "https://api:YOUR_API_KEY"\
                 "@api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks"
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class GetWebhooksChunk
{

    public static void Main (string[] args)
    {
        Console.WriteLine (GetWebhooks ().Content.ToString ());
    }

    public static IRestResponse GetWebhooks ()
    {
        RestClient client = new RestClient ();
        client.BaseUrl = new Uri ("https://api.mailgun.net/v3");
        client.Authenticator =
            new HttpBasicAuthenticator ("api",
                                        "YOUR_API_KEY");
        RestRequest request = new RestRequest ();
        request.AddParameter ("domain", "YOUR_DOMAIN_NAME", ParameterType.UrlSegment);
        request.Resource = "domains/{domain}/webhooks";
        return client.Execute (request);
    }

}
import (
    "context"
    "github.com/mailgun/mailgun-go/v3"
    "time"
)

func ListWebhooks(domain, apiKey string) (map[string]string, error) {
    mg := mailgun.NewMailgun(domain, apiKey)

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

    return mg.ListWebhooks(ctx)
}
const DOMAIN = 'YOUR_DOMAIN_NAME';

const formData = require('form-data');
const Mailgun = require('mailgun.js');

const mailgun = new Mailgun(formData);

const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
  try {
    const webhooks = await client.webhooks.list(DOMAIN);
    console.log('webhooks', webhooks);
  } catch (error) {
    console.error(error);
  }
})();

Sample response:

{
  "webhooks": {
    "opened": {
      "urls": [
                "https://your_domain.com/v1/opened",
                "https://your_domain.com/v2/opened"
              ]
    },
    "clicked": {
      "urls": [ "https://your_domain.com/v1/clicked" ]
    }
  }
}

Return a webhook for a specific event for the defined domain.

curl -s --user 'api:YOUR_API_KEY' -G \
    https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked
import com.mailgun.api.v3.MailgunWebhooksApi;
import com.mailgun.enums.WebhookName;
import com.mailgun.model.webhooks.WebhookDetailsResult;

// ...

public WebhookDetailsResult getWebhookEvent() {
    MailgunWebhooksApi mailgunWebhooksApi = MailgunClient.config(API_KEY).createApi(MailgunWebhooksApi.class);

    return mailgunWebhooksApi.getWebhookDetails(YOUR_DOMAIN_NAME, WebhookName.CLICKED);
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = Mailgun::create('PRIVATE_API_KEY', 'https://API_HOSTNAME');
$domain   = 'YOUR_DOMAIN_NAME';
$webhook  = 'delivered';

# Issue the call to the client.
$result = $mgClient->webhooks()->show($domain, $webhook)
def get_domain():
    return requests.get(
        "https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked",
        auth=("api", "YOUR_API_KEY"))
def get_domain
  RestClient.get("https://api:YOUR_API_KEY"\
                 "@api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked"\
                 {|response, request, result| response }
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class GetWebhookChunk
{

    public static void Main (string[] args)
    {
        Console.WriteLine (GetWebhook ().Content.ToString ());
    }

    public static IRestResponse GetWebhook ()
    {
        RestClient client = new RestClient ();
        client.BaseUrl = new Uri ("https://api.mailgun.net/v3");
        client.Authenticator =
            new HttpBasicAuthenticator ("api",
                                        "YOUR_API_KEY");
        RestRequest request = new RestRequest ();
        request.AddParameter ("domain", "YOUR_DOMAIN_NAME", ParameterType.UrlSegment);
        request.Resource = "/domains/{domain}/webhooks/clicked";
        return client.Execute (request);
    }

}
import (
    "context"
    "github.com/mailgun/mailgun-go/v3"
    "time"
)

func GetWebhook(domain, apiKey string) (string, error) {
    mg := mailgun.NewMailgun(domain, apiKey)

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

    return mg.GetWebhook(ctx, "clicked")
}
const DOMAIN = 'YOUR_DOMAIN_NAME';

const formData = require('form-data');
const Mailgun = require('mailgun.js');

const mailgun = new Mailgun(formData);

const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
  try {
    const webhooks = await client.webhooks.get(DOMAIN,'delivered');
    console.log('webhooks', webhooks);
  } catch (error) {
    console.error(error);
  }
})();

Sample response:

{
  "webhook": {
    "urls": [ "https://your_domain.com/v1/clicked" ]
  }
}

Create a new webhook.

curl -s --user 'api:YOUR_API_KEY' -X POST \
   https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks \
   -F id='clicked' \
   -F url='https://your_domain.com/v1/clicked' \
   -F url='https://your_domain.com/v2/clicked' \
   -F url='https://your_partner_domain.com/v1/clicked'
import com.mailgun.api.v3.MailgunWebhooksApi;
import com.mailgun.enums.WebhookName;
import com.mailgun.model.webhooks.WebhookRequest;
import com.mailgun.model.webhooks.WebhookResult;

import java.util.List;

// ...

public WebhookResult addWebhook() {
    MailgunWebhooksApi mailgunWebhooksApi = MailgunClient.config(API_KEY).createApi(MailgunWebhooksApi.class);

    WebhookRequest request = WebhookRequest.builder()
        .webhookName(WebhookName.CLICKED)
        .url("https://your_domain.com/v1/clicked")
        .urls(List.of("https://your_domain.com/v2/clicked", "https://your_partner_domain.com/v1/clicked"))
        .build();

    return mailgunWebhooksApi.createNewWebhook(YOUR_DOMAIN_NAME, request);
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = Mailgun::create('PRIVATE_API_KEY', 'https://API_HOSTNAME');
$domain   = 'YOUR_DOMAIN_NAME';
$webhook  = 'delivered';
$destination_url = 'https://my.webhook.url/delivered'

# Issue the call to the client.
$result = $mgClient->webhooks()->create($domain, $webhook, $destination_url);
def add_webhook():
    return requests.post(
        "https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks",
        auth=("api", "YOUR_API_KEY"),
        data={
          'id':'clicked',
          'url':[ 'https://your_domain.com/v1/clicked',
          'https://your_domain.com/v2/clicked',
          'https://your_partner_domain.com/v1/clicked'
          ]
        })
def add_webhook
  RestClient.post("https://api:YOUR_API_KEY"\
                  "@api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks",
                  :id => 'clicked',
                  :url => ['https://your_domain.com/v1/clicked',
                           'https://your_domain.com/v2/clicked',
                           'https://your_partner_domain.com/v1/clicked'])
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class AddWebhookChunk
{

    public static void Main (string[] args)
    {
        Console.WriteLine (AddWebhook ().Content.ToString ());
    }

    public static IRestResponse AddWebhook ()
    {
        RestClient client = new RestClient ();
        client.BaseUrl = new Uri ("https://api.mailgun.net/v3/");
        client.Authenticator =
            new HttpBasicAuthenticator ("api",
                                        "YOUR_API_KEY");
        RestRequest request = new RestRequest ();
        request.Resource = "domains/YOUR_DOMAIN_NAME/webhooks";
        request.AddParameter ("id", "clicked");
        request.AddParameter ("url", "https://your_domain.com/v1/clicked")
        request.AddParameter ("url", "https://your_domain.com/v2/clicked")
        request.AddParameter ("url", "https://your_partner_domain.com/v1/clicked")
        request.Method = Method.POST;
        return client.Execute (request);
    }

}
import (
    "context"
    "github.com/mailgun/mailgun-go/v3"
    "time"
)

func CreateWebhook(domain, apiKey string) error {
    mg := mailgun.NewMailgun(domain, apiKey)

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

    return mg.CreateWebhook(ctx, "clicked", []string{"https://your_domain.com/v1/clicked"})
}
const DOMAIN = 'YOUR_DOMAIN_NAME';

const formData = require('form-data');
const Mailgun = require('mailgun.js');

const mailgun = new Mailgun(formData);

const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
  try {
    // clicked or one of the Supported webhooks
    const createdWebhook = await client.webhooks.create(DOMAIN, 'clicked', 'https://your_domain.com/v1/clicked');
    console.log('createdWebhook', createdWebhook);
  } catch (error) {
      console.error(error);
  }
})();

Sample response:

{
  "message": "Webhook has been created",
  "webhook": {
    "urls": [
              "https://your_domain.com/v1/clicked",
              "https://your_domain.com/v2/clicked",
              "https://your_partner_domain.com/v1/clicked"
            ]
  }
}

Update an existing webhook.

curl -s --user 'api:YOUR_API_KEY' -X PUT \
    https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked \
    -F url='https://your_domain,com/v1/clicked'
import com.mailgun.api.v3.MailgunWebhooksApi;
import com.mailgun.enums.WebhookName;
import com.mailgun.model.webhooks.WebhookResult;
import com.mailgun.model.webhooks.WebhookUpdateRequest;

// ...

public WebhookResult updateWebhook() {
    MailgunWebhooksApi mailgunWebhooksApi = MailgunClient.config(API_KEY)
        .createApi(MailgunWebhooksApi.class);

    WebhookUpdateRequest request = WebhookUpdateRequest.builder()
        .url("https://your_domain.com/clicked")
        .build();

    return mailgunWebhooksApi.updateWebhook(YOUR_DOMAIN_NAME, WebhookName.CLICKED, request);
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = Mailgun::create('PRIVATE_API_KEY', 'https://API_HOSTNAME');
$domain   = 'YOUR_DOMAIN_NAME';
$webhook  = 'delivered';
$destination_url = 'https://my.webhook.url/delivered'

# Issue the call to the client.
$result = $mgClient->webhooks()->update($domain, $webhook, $destination_url);
def update_webhook():
    return requests.put(
        ("https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked"),
        auth=('api', 'YOUR_API_KEY'),
        data={'url': 'https://your_domain.com/clicked'})
def update_webhook
  RestClient.put("https://api:YOUR_API_KEY" \
                 "@api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked",
                 :url => 'https://your_domain.com/clicked')
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class UpdateWebhookChunk
{

    public static void Main (string[] args)
    {
        Console.WriteLine (UpdateWebhook ().Content.ToString ());
    }

    public static IRestResponse UpdateWebhook ()
    {
        RestClient client = new RestClient ();
        client.BaseUrl = new Uri ("https://api.mailgun.net/v3");
        client.Authenticator =
            new HttpBasicAuthenticator ("api",
                                        "YOUR_API_KEY");
        RestRequest request = new RestRequest ();
        request.Resource = "/domains/YOUR_DOMAIN_NAME/webhooks/clicked";
        request.AddParameter ("url", "https://your_domain.com/clicked");
        request.Method = Method.PUT;
        return client.Execute (request);
    }

}
import (
    "context"
    "github.com/mailgun/mailgun-go/v3"
    "time"
)

func UpdateWebhook(domain, apiKey string) error {
    mg := mailgun.NewMailgun(domain, apiKey)

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

    return mg.UpdateWebhook(ctx, "clicked", []string{"https://your_domain.com/clicked"})
}
const DOMAIN = 'YOUR_DOMAIN_NAME';

const formData = require('form-data');
const Mailgun = require('mailgun.js');

const mailgun = new Mailgun(formData);

const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
  try {
    const updatedWebhooks = await client.webhooks.update(DOMAIN, 'clicked', 'https://your_domain.com/v1/clicked');
    console.log('updatedWebhooks', updatedWebhooks);
  } catch (error) {
    console.error(error);
  }
})();

Sample response:

{
  "message": "Webhook has been updated",
  "webhook": {
    "urls": [ "https://your_domain.com/v1/clicked" ]
  }
}

Delete a webhook.

curl -s --user 'api:YOUR_API_KEY' -X DELETE \
    https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked
import com.mailgun.api.v3.MailgunWebhooksApi;
import com.mailgun.enums.WebhookName;
import com.mailgun.model.webhooks.WebhookResult;

// ...

public WebhookResult deleteWebhook() {
    MailgunWebhooksApi mailgunWebhooksApi = MailgunClient.config(API_KEY).createApi(MailgunWebhooksApi.class);

    return mailgunWebhooksApi.deleteWebhook(YOUR_DOMAIN_NAME, WebhookName.CLICKED);
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = Mailgun::create('PRIVATE_API_KEY', 'https://API_HOSTNAME');
$domain   = 'YOUR_DOMAIN_NAME';
$webhook  = 'delivered';

# Issue the call to the client.
$result = $mgClient->webhooks()->delete($domain, $webhook);
def delete_domain():
    return requests.delete(
        "https://api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked",
        auth=("api", "YOUR_API_KEY"))
def delete_domain
  RestClient.delete "https://api:YOUR_API_KEY"\
  "@api.mailgun.net/v3/domains/YOUR_DOMAIN_NAME/webhooks/clicked"
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class DeleteWebhookChunk
{

    public static void Main (string[] args)
    {
        Console.WriteLine (DeleteWebhook ().Content.ToString ());
    }

    public static IRestResponse DeleteWebhook ()
    {
        RestClient client = new RestClient ();
        client.BaseUrl = new Uri ("https://api.mailgun.net/v3");
        client.Authenticator =
            new HttpBasicAuthenticator ("api",
                                        "YOUR_API_KEY");
        RestRequest request = new RestRequest ();
        request.Resource = "/domains/{name}/webhooks/clicked";
        request.AddUrlSegment ("name", "YOUR_DOMAIN_NAME");
        request.Method = Method.DELETE;
        return client.Execute (request);
    }

}
import (
    "context"
    "github.com/mailgun/mailgun-go/v3"
    "time"
)

func DeleteWebhook(domain, apiKey string) error {
    mg := mailgun.NewMailgun(domain, apiKey)

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

    return mg.DeleteWebhook(ctx, "clicked")
}
const DOMAIN = 'YOUR_DOMAIN_NAME';

const formData = require('form-data');
const Mailgun = require('mailgun.js');

const mailgun = new Mailgun(formData);

const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
  try {
    const deletedWebhook = await client.webhooks.destroy(DOMAIN, 'clicked');
    console.log('deletedWebhook', deletedWebhook);
  } catch (error) {
    console.error(error);
  }
})();

Sample response:

{
  "message": "Webhook has been deleted",
  "webhook": {
    "urls": [
              "https://your_domain.com/v1/clicked",
              "https://your_domain.com/v2/clicked",
              "https://your_partner_domain.com/v1/clicked"
            ]
  }
}

Rate Limit Response:

{
        "retry-seconds": 60,
}