We're experiencing difficulty. Our engineers are on it. Please check status.mailgun.com for real-time updates.

Legacy Webhooks

Table Of Contents
Quick Overview
Is My Account Using Legacy Webhooks (API Version 2)?
Why Current Webhooks Are Better Than Legacy Webhooks
Mappings And The Nuances Between Legacy Webhooks & Current Webhooks
Migration From Legacy Webhooks (v2) To Current Webhooks (v3) Overview
Payloads Of The Legacy Webhooks
    Delivered Payload
    Dropped Messages Payload
    Hard Bounces Payload
    Clicks Payload
    Opens Payload
    Spam Complaints Payload
    Unsubscribes Payload
Redacted/Deprecated Documentation

Quick Overview

Below are various topics to help in transitioning from Legacy Webhooks to Current Webhooks.  Legacy webhooks have moved to read-only** as of April 18, 2023 and will be fully deprecated during October 2023.  

** "Read-only" means that currently existing Legacy Webhooks will continue to operate as expected; however, you no longer will be able to create new or edit existing Legacy Webhooks.

Is My Account Using Legacy Webhooks (API Version 2)?

  1. First, log in to the Mailgun Control Panel (if you have not already done so).
  2. Then, within the left-hand navigation pane, click the Sending option to expand its list of suboptions.
  3. Next, click the Webhooks suboption.
  4. Ensure that the domain for which you wish to configure the webhook is displayed within the Domain drop-down list towards the upper-right portion of the page. (Note: Check every US and EU domain on your account and perform step 5 below).
    Screen Shot 2022-09-11 at 6.58.43 PM.png
  5. Click the Legacy webhooks tab that will be towards the center of the page.
    1. If you have no Legacy Webhooks configured, the list will be empty and the page will look like the below:
      Screenshot 2023-03-28 at 12.15.11 PM.png
    2. If you have Legacy Webhooks configured, there will be a list of webhooks and the page will look like the below:
      Screenshot 2023-03-28 at 2.48.11 PM.png

Why Current Webhooks Are Better Than Legacy Webhooks

The main advantages of Current Webhooks over Legacy Webhooks are:

  • Current Webhooks return the same data structure as the Events API and transmits the data as application/json. Legacy webhooks transmit data in two different formats, neither of which match the format we use for Events. As such, Current Webhooks brings greater consistency and functionality to the service.
  • Additionally, unlike our Legacy Webhooks service, the Current Webhooks can be configured to POST to three endpoints (rather than only one). As such, should one endpoint ever fail, up to two more can still receive the POSTs.
  • Finally, Legacy Webhooks uses version 2 of the Webhooks API while Current Webhooks uses version 3 of the Webhooks API, which is the most current, fully-featured version of our Webhooks API.

Mappings And The Nuances Between Legacy Webhooks & Current Webhooks

Legacy Webhooks

Current Webhooks

(No equivalent webhook)

Accepted Messages

Delivered Messages

Delivered Messages

Dropped Messages

(Now included in the Permanent Failure webhook)

Hard Bounces

(Now included in the Permanent Failure webhook)

(No equivalent webhook)

Permanent Failure

(No equivalent webhook)

Temporary Failure

Clicks

Clicks

Opens

Opens

Spam Complaints

Spam Complaints

Unsubscribes

Unsubscribes 

 

As can be seen above, most Legacy Webhooks have intuitive mapping to the Current Webhooks; however, this is not so with various failed messages. Failed messages are quite nuanced in both cause and effect, and our prime, top-level delineation between failure types changed with the Current Webhooks.

Current webhooks primarily delineate between two types of failure persistence: temporary (soft bounce) and permanent (hard bounce); note, a message “bounces” when rejected by a receiving SMTP server. We’ll need to dive deeper into the two failure types briefly before moving on to legacy webhooks:

  • Temporary failure webhooks fire for events such as a full mailbox; we try later on a few more times, but if delivery continues to be unsuccessful, we stop retrying. These failures do not add the email address to the “Bounces” table in the Suppressions tab of your Control Panel.

  • Permanent failure webhooks fire for events in which the recipient was not found, or was determined to not exist, within the recipient server’s environment. These failures - and thus the firing of the webhook - also occur due 1) soft bounced/temporarily failed emails exhausting all (re)delivery attempts, 2) ESP blocks due to poor sender domain or IP reputation, and 3) the email address is listed on one of Mailgun’s three Suppressions tables (Bounces, Complaints, and Unsubscribes) for your domain.

    • For permanent failures due to invalid recipients, we do not attempt any further deliveries after encountering the hard bounce. These failures do add the email address to the Bounces table in the Suppressions tab of your Control Panel.

    • For permanent failures due to all of the other reasons, we also do not attempt any further deliveries after encountering the hard bounce. However, these failures do not add the email address to the Bounces table in the Suppressions tab of your Control Panel.

    • If an email address is in the Bounces, Complaints, and/or Unsubscribes tables, Mailgun will not attempt delivery of future emails submitted to our system that contain said address.

    • Note: Bounces, Complaints, Unsubscribes, and Whitelists are available programmatically through the respective APIs.

Legacy Webhooks primarily delineate between permanent failure type: hard bounces (of a specific type only: messages sent to non-existent/invalid recipients) and dropped messages (all other types of hard bounces/permanent failures). Legacy Webhooks do not have soft bounce/temporary failure functionality.

  • Hard bounce webhooks fire for events in which the recipient was not found, or was determined to not exist, within the recipient server’s environment.

  • Dropped message webhooks fire for events such as 1) soft bounced/temporarily failed emails exhausting all (re)delivery attempts, 2) ESP blocks due to poor sender domain or IP reputation, and 3) the email address is listed on one of Mailgun’s three Suppressions tables (Bounces, Complaints, and Unsubscribes) for your domain.

    • For all messages that encounter such failures, all retrying is “dropped” immediately.

    • As such, the legacy dropped messages webhook is similiar to the current permanent failure webhook but differs in that hard bounces to non-existent/invalid recipients are not included in the legacy dropped messages webhook. Instead, hard bounces have their own webhook in the legacy environment.

Migration From Legacy Webhooks (v2) To Current Webhooks (v3) Overview

While our team cannot specify the exact and full extent of configuration or coding changes that a given application or use-case may require, we can provide a general overview of the key actions that will need to be taken to transition from the Legacy Webhooks to the Current Webhooks.

  1. Create new Current Webhooks that correspond/map to your existing Legacy Webhooks
    1. Refer to the "Mappings And The Nuances Between Legacy Webhooks & Current Webhooks" section, if needed, to ensure the Current Webhooks created are equivalent in functionality and business need to the Legacy Webhooks
  2. Test the Current Webhooks functionality in your Staging/Testing environment
    1. Steps 2-4 can be iterative and taken as a string of actions per webhook, if desired.
    2. Test so that you can see how the data arrives at your system and what it contains
    3. This information will help you in understanding what configuration or code changes your system may need to handle the new POST format (JSON) and the new data structure that mirrors the Events data structure
    4. Adjust any downstream processes and services within your system that rely on webhook data, if needed
  3. Replace the Legacy Webhooks with the Current Webhooks
    1. This is the time where you'll make the coding or configuration changes themselves based on the results of your testing above and your analysis of your system and the needed changes.
    2. To minimize risk, you could make and test the changes on a webhook by webhook basis. In this way, you can test once and ensure it's production-ready. If not, you can course-correct and use the lessons-learned for the remaining webhooks.
  4. Test the Current Webhooks functionality in your Production environment
    1. This may take the form of many of the actions in Step 2 above. Essentially, you want to insure that what works in your Testing environment works in your Production environment before you finally switch over to using Current Webhooks exclusively
  5. Delete the Legacy Webhooks from your Mailgun Control Panel
    1. Once you can confirm that you are receiving all the expected data, handling it correctly, and that all downstream processes and services in your system operate as expected, you can remove the Legacy Webhooks from your account
    2. Note: the deletion doesn't need to be immediate and you can give your system so time for further monitoring

Payloads Of The Legacy Webhooks

Legacy Webhooks are transmitted as either multipart/form-data or application/x-www-form-urlencoded based on the event type and/or the data that the POST contains (i.e. attachments). This is different from our current version of webhooks which transmits all data in JSON.

Below is a breakdown of what events are associated with each data type for Legacy Webhooks:

application/x-www-form-urlencoded

  • Unsubscribes
  • Clicks
  • Opens
  • Delivered (without attachments) 

multipart/form-data

  • Complaints
  • Dropped
  • Hard Bounced
  • Delivered (with attachments)

Note: Our Events API documentation provides payload examples of the content for the current version of our webhooks (which mirror the data structures of the data found via the Events API/Logs).

Finally, to determine whether your existing endpoint can process the POSTs, you may also submit a test POST via the Webhooks page in the Control Panel to your endpoint (or you can use a temporary postbin for such tests as well).

Delivered Messages Payload

Parameter

Value

Message-Id

<20130503182626.18666.16540@testdocs.myexample.com>

domain

testdocs.myexample.com

event

delivered

message-headers

[
  [
    "Received",
    "by luna.mailgun.net with SMTP mgrt 8734663311733; Fri, 03 May 2013 18:26:27 +0000"
  ],
  [
    "Content-Type",
    [
      "multipart/alternative",
      {
        "boundary": "eb663d73ae0a4d6c9153cc0aec8b7520"
      }
    ]
  ],
  [
    "Mime-Version",
    "1.0"
  ],
  [
    "Subject",
    "Test deliver webhook"
  ],
  [
    "From",
    "Bob "
  ],
  [
    "To",
    "Alice "
  ],
  [
    "Message-Id",
    "<20130503182626.18666.16540@testdocs.myexample.com>"
  ],
  [
    "X-Mailgun-Variables",
    "{\"my-var-1\": \"Mailgun Variable #1\", \"my-var-2\": \"awesome\"}"
  ],
  [
    "Date",
    "Fri, 03 May 2013 18:26:27 +0000"
  ],
  [
    "Sender",
    "bob@testdocs.myexample.com"
  ]
]

my-var-1

Mailgun Variable #1

my-var-2

awesome

recipient

alice@example.com

signature

a33ce59411a04c8a82fb125a184367ccbc1b885c1b9296f8d70ef3ed9a73b3d5

timestamp

1677968955

token

6a7958862ce7014a14fba75a4e272e900dc3debaaecf838bef

 

Dropped Messages Payload

Parameter

Value

timestamp

1677970009

description

Not delivering to previously bounced address

domain

testdocs.myexample.com

message-headers

[
  [
    "Received",
    "by luna.mailgun.net with SMTP mgrt 8755546751405; Fri, 03 May 2013 19:26:59 +0000"
  ],
  [
    "Content-Type",
    [
      "multipart/alternative",
      {
        "boundary": "23041bcdfae54aafb801a8da0283af85"
      }
    ]
  ],
  [
    "Mime-Version",
    "1.0"
  ],
  [
    "Subject",
    "Test drop webhook"
  ],
  [
    "From",
    "Bob "
  ],
  [
    "To",
    "Alice "
  ],
  [
    "Message-Id",
    "<20130503192659.13651.20287@testdocs.myexample.com>"
  ],
  [
    "List-Unsubscribe",
    ""
  ],
  [
    "X-Mailgun-Sid",
    "WyIwNzI5MCIsICJpZG91YnR0aGlzb25lZXhpc3RzQGdtYWlsLmNvbSIsICI2Il0="
  ],
  [
    "X-Mailgun-Variables",
    "{\"my-var-1\": \"Mailgun Variable #1\", \"my-var-2\": \"awesome\"}"
  ],
  [
    "Date",
    "Fri, 03 May 2013 19:26:59 +0000"
  ],
  [
    "Sender",
    "bob@testdocs.myexample.com"
  ]
]

my-var-2

awesome

code

605

Message-Id

<20130503192659.13651.20287@testdocs.myexample.com>

event

dropped

attachment-count

1

signature

d8bca0f672e538c324140e96af240b475a546cc340ae4f8acc7304e4a06ea939

token

d96f0d79a46234c5cde1bb287efc2af8911d8463ff80fe1cdd

X-Mailgun-Sid

WyIwNzI5MCIsICJpZG91YnR0aGlzb25lZXhpc3RzQGdtYWlsLmNvbSIsICI2Il0=

my-var-1

Mailgun Variable #1

reason

hardfail

recipient

alice@example.com

attachment-1

{:filename=>"message.mime", :type=>"application/octet-stream", :name=>"attachment-1", :tempfile=>#<Tempfile:/tmp/RackMultipart20230304-2-1rz691f.mime>, :head=>"Content-Disposition: form-data; name=\"attachment-1\"; filename=\"message.mime\"\r\nContent-Type: application/octet-stream\r\n"}

 

Hard Bounces Payload

Parameter

Value

domain

testdocs.myexample.com

event

bounced

my-var-2

awesome

recipient

alice@example.com

signature

2e2e4e37cfef1926bf2711ba8b5d1cd6c7f5eba37b54b01e828c2d8acb034882

X-Mailgun-Sid

WyIwNzI5MCIsICJhbGljZUBleGFtcGxlLmNvbSIsICI2Il0=

token

3485536eb0a12575d72a259c00880baeca007948f178fa31f1

timestamp

1677967300

Message-Id

<20130503182626.18666.16540@testdocs.myexample.com>

error

5.1.1 The email account that you tried to reach does not exist. Please try 5.1.1 double-checking the recipient's email address for typos or 5.1.1 unnecessary spaces. Learn more at 5.1.1 http://support.example.com/mail/bin/answer.py

message-headers

[
  [
    "Received",
    "by luna.mailgun.net with SMTP mgrt 8734663311733; Fri, 03 May 2013 18:26:27 +0000"
  ],
  [
    "Content-Type",
    [
      "multipart/alternative",
      {
        "boundary": "eb663d73ae0a4d6c9153cc0aec8b7520"
      }
    ]
  ],
  [
    "Mime-Version",
    "1.0"
  ],
  [
    "Subject",
    "Test bounces webhook"
  ],
  [
    "From",
    "Bob "
  ],
  [
    "To",
    "Alice "
  ],
  [
    "Message-Id",
    "<20130503182626.18666.16540@testdocs.myexample.com>"
  ],
  [
    "List-Unsubscribe",
    ""
  ],
  [
    "X-Mailgun-Sid",
    "WyIwNzI5MCIsICJhbGljZUBleGFtcGxlLmNvbSIsICI2Il0="
  ],
  [
    "X-Mailgun-Variables",
    "{\"my-var-1\": \"Mailgun Variable #1\", \"my-var-2\": \"awesome\"}"
  ],
  [
    "Date",
    "Fri, 03 May 2013 18:26:27 +0000"
  ],
  [
    "Sender",
    "bob@testdocs.myexample.com"
  ]
]

code

550

attachment-count

1

my-var-1

Mailgun Variable #1

attachment-1

{:filename=>"message.mime", :type=>"application/octet-stream", :name=>"attachment-1", :tempfile=>#<Tempfile:/tmp/RackMultipart20230304-2-1rmaczq.mime>, :head=>"Content-Disposition: form-data; name=\"attachment-1\"; filename=\"message.mime\"\r\nContent-Type: application/octet-stream\r\n"}

 

Clicks Payload

Parameter

Value

signature

{
  "token": "1b4d2ef8bc44182bb9058a8f6a8fa75537c7c4c50df5d1b526",
  "timestamp": "1677980169",
  "signature": "dc4d717a5594e63ce5b18cb12eb7d2e41eea63cf65e78328608671abee889d1b"
}

event-data

{
  "id": "Ase7i2zsRYeDXztHGENqRA",
  "timestamp": 1521243339.873676,
  "log-level": "info",
  "event": "clicked",
  "message": {
    "headers": {
      "message-id": "20130503182626.18666.16540@testdocs.myexample.com"
    }
  },
  "recipient": "alice@example.com",
  "recipient-domain": "Example Domain ",
  "ip": "50.56.129.169",
  "geolocation": {
    "country": "US",
    "region": "CA",
    "city": "San Francisco"
  },
  "client-info": {
    "client-os": "Linux",
    "device-type": "desktop",
    "client-name": "Chrome",
    "client-type": "browser",
    "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31"
  },
  "campaigns": [

  ],
  "tags": [
    "my_tag_1",
    "my_tag_2"
  ],
  "user-variables": {
    "my_var_1": "Mailgun Variable #1",
    "my-var-2": "awesome"
  }
}

 

Opens Payload

Parameter

Value

signature

{
  "token": "75ff48baaa62ac1784b0109b8fe31840c74e2d77c5cf70642f",
  "timestamp": "1677970487",
  "signature": "459dc5c9c4f64cd72f889ff163225b6c45f644698bd95fb05f1dbf34f96291e8"
}

event-data

{
  "id": "Ase7i2zsRYeDXztHGENqRA",
  "timestamp": 1521243339.873676,
  "log-level": "info",
  "event": "opened",
  "message": {
    "headers": {
      "message-id": "20130503182626.18666.16540@testdocs.myexample.com"
    }
  },
  "recipient": "alice@example.com",
  "recipient-domain": "http://example.com ",
  "ip": "50.56.129.169",
  "geolocation": {
    "country": "US",
    "region": "CA",
    "city": "San Francisco"
  },
  "client-info": {
    "client-os": "Linux",
    "device-type": "desktop",
    "client-name": "Chrome",
    "client-type": "browser",
    "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31"
  },
  "campaigns": [

  ],
  "tags": [
    "my_tag_1",
    "my_tag_2"
  ],
  "user-variables": {
    "my_var_1": "Mailgun Variable #1",
    "my-var-2": "awesome"
  }
}

 

Spam Complaints Payload

Parameter

Value

signature

{
  "token": "ce12a1a95fdef5ea0393d005210e446dbbf1ee82f38e296d18",
  "timestamp": "1677980472",
  "signature": "7b3ecdcdf21199f7f84d455f0c9eaacd978b59d85307c5120ccfa4f023846ec8"
}

event-data

{
  "id": "-Agny091SquKnsrW2NEKUA",
  "timestamp": 1521233123.501324,
  "log-level": "warn",
  "event": "complained",
  "envelope": {
    "sending-ip": "173.193.210.33"
  },
  "flags": {
    "is-test-mode": false
  },
  "message": {
    "headers": {
      "to": "Alice ",
      "message-id": "20110215055645.25246.63817@testdocs.myexample.com",
      "from": "Bob ",
      "subject": "Test complained webhook"
    },
    "attachments": [

    ],
    "size": 111
  },
  "recipient": "alice@example.com",
  "campaigns": [

  ],
  "tags": [
    "my_tag_1",
    "my_tag_2"
  ],
  "user-variables": {
    "my_var_1": "Mailgun Variable #1",
    "my-var-2": "awesome"
  }
}

 

Unsubscribes Payload

Parameter

Value

city

San Francisco

client-name

Chrome

client-os

Linux

client-type

browser

country

US

device-type

desktop

domain

testdocs.myexample.com

event

unsubscribed

ip

50.56.129.169

my-var-1

Mailgun Variable #1

my-var-2

awesome

recipient

alice@example.com

region

CA

signature

daf18db283241dd63f82ff79605e96ce3a2c955f639dd232ea659399267be6fb

tags

*

timestamp

1677981180

token

fd096f96e1b4ab7c5aaceb2dfcf15cbcd91566494d663cf2e0

user-agent

Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.43 Safari/537.31

Redacted/Deprecated Documentation

A point in time where the legacy webhooks documentation was the one and only documentation is located in the following version of our Mailgun GitHub Documentation repo (also known as our Mailgun Technical Documentation):

Got Questions?

Mailgun by Sinch has answers! If you have any concerns or questions, please send us a Support ticket using the Support page within your Mailgun Control Panel.  Our Support Team will be happy to assist!