Events

Mailgun tracks every event that happens to your emails and makes this data available to you through the Events API. Mailgun retains this detailed data for two days for free accounts and 30 days for paid accounts. You can query the data and traverse through the result pages as explained below.

GET /<domain>/events

Note

The Events API replaces the deprecated Logs API endpoint. You should use the Events API moving forward.

A request should define a time range and can specify a set of filters to apply. In response, a page of events is returned along with URLs that can be used to retrieve the next and previous result pages. To traverse the entire range, you should keep requesting the next page URLs returned returned along with result pages until an empty result page is reached.

Both next and previous page URLs are always returned, even when retrieving one of them makes no sense. There are two such cases: previous page URL for the first result page, and next page URL for the last result page; requesting these URLs always returns an empty result page.

Time Range

The request time range should be given by a beginning timestamp and either an end timestamp or a search direction.

If the range end timestamp is provided then the relation between the beginning and the end timestamps determines the direction in which events are going to be traversed. E.g. if the end timestamp is less than the beginning timestamp, then result pages are returned from newer to older and events on the pages are sorted in the descending order of their timestamps.

If the end timestamp is not provided then depending on the range direction the result page traversal behaves differently:

  • If the range is descending then the end timestamp is determined by the user tariff plan retention period.
  • If the range is ascending the it is extended all the time as the time goes on. So after the most recent events have been retrieved and an empty result page has been reached, then requesting next page URL returned with the last page some time later will return events that occurred since then. And this can go on indefinitely.

Warning

Even though it seems that real-time event polling can be implemented by traversing next URLs of an ascending time range that has no explicit end timestamp, it is not that simple! Please refer to Event Polling for the proper way to do it.

If both the end range date and the direction of the search are specified then they should agree with each other, otherwise the request will return an error.

Event Polling

In our system events are generated by physical hosts and follow different routes to the event storage, therefore the order in which they appear in the storage and become retrievable via the events API does not correspond to the order in which they occur. A consequences of this is that page of most recent events returned by the events API may not contain all the events that occurred by that time. Some of them could still be on their way to the storage engine, and when they are eventually indexed it would appear as if they got inserted into an already retrieved page. This system behavior makes straight forward implementation of event polling miss some events.

To ensure that all your events are retrieved and accounted for please implement polling the following way:

  1. Make a request to the events API specifying an ascending time range that begins some time in the past (e.g. half an hour ago);
  2. Retrieve a result page;
  3. Check the timestamp of the last event on the result page. If it is older then some threshold age (e.g. half an hour) then go to step (4), otherwise proceed with step (6);
  4. The result page is trustworthy, use events from the page as you please;
  5. Make a request using the next page URL retrieved with the result page, proceed with step (2);
  6. Discard the result page for it is not trustworthy;
  7. Pause for some time (at least 15 seconds);
  8. Repeat the previous request, and proceed with step (2).

Query Options

URL parameters allow you to manipulate the results of your query:

Parameter Description
begin The beginning of the search time range. It can be specified as a string (see Date Format) or linux epoch seconds. Refer to Time Range for details.
end The end of the search time range. It can be specified as a string (see Date Format) or linux epoch seconds. Refer to Time Range for details.
ascending Defines the direction of the search time range if the range end time is not specified. Can be either yes or no. Refer to Time Range for details.
limit Number of entries to return. (300 max)
<field> <field> is the name of the Filter Field. The value of the parameter should be a valid Filter Expression. Several field filters can be specified in one request. If the same field is mentioned, more then once, then all its filter expressions are combined with AND operator.

Filter Field

Log records can be filtered by the following fields:

Fields Description
event An event type. For a complete list of all events written to the log see the Event Types table below.
list The email address of a mailing list the message was originally sent to.
attachment A name of an attached file.
from An email address mentioned in the from MIME header.
message-id A Mailgun message id returned by the messages API.
subject A subject line.
to An email address mentioned in the to MIME header.
size Message size. Mostly intended to be used with range filtering expressions (see below).
recipient An email address of a particular recipient. Even though a message may be addressed to several recipients, delivery is tracked on per recipient basis and every event pertains to only one recipient.
tags User defined tags.
severity Temporary or Permanent. Used to filter events based on severity, if exists. (Currently failed events only)

Filter Expression

Possible filtering expressions are listed below:

Expression Description
foo bar Matches field values that contain both term foo and term bar.
foo AND bar Same as above.
foo OR bar Matches field values that contain either term foo or term bar.
“foo bar” Matches field values that literally contain foo bar.
NOT foo Matches field values that do not contain term foo.
>10000 Matches values that greater then 10000. This filter can be applied to numeric fields only.
>10000 <20000 Matches values that are greater then 10000 and less then 20000. This filter can be applied to numeric fields only.

Note that more then one expression can be used as a filter value and parenthesis can be used to specify grouping. E.g.: (Hello AND NOT Rachel) OR (Farewell AND Monica).

Event Types

Mailgun tracks all of the events that occur throughout the system. Below are listed the events that you can retrieve using this API.

Event Type Description
accepted Mailgun accepted the request to send/forward the email and the message has been placed in queue.
rejected Mailgun rejected the request to send/forward the email.
delivered Mailgun sent the email and it was accepted by the recipient email server.
failed Mailgun could not deliver the email to the recipient email server.
opened The email recipient opened the email and enabled image viewing. Open tracking must be enabled in the Mailgun control panel, and the CNAME record must be pointing to mailgun.org.
clicked The email recipient clicked on a link in the email. Click tracking must be enabled in the Mailgun control panel, and the CNAME record must be pointing to mailgun.org.
unsubscribed The email recipient clicked on the unsubscribe link. Unsubscribe tracking must be enabled in the Mailgun control panel.
complained The email recipient clicked on the spam complaint button within their email client. Feedback loops enable the notification to be received by Mailgun.
stored Mailgun has stored an incoming message

Event Structure

Events are represented as loosely structured JSON documents. The exact event structure depends on the event type. But there are three fields that every event has. They are as follows:

Field Description
event The type of the event. Events of a particular type have an identical structure, though some fields may be optional. For the list of event types please refer to Event Types.
timestamp The time when the event was generated in the system provided as Unix epoch seconds.
id Event id. It is guaranteed to be unique within a day. It can be used to distinguish events that have already been retrieved when requests with overlapping time ranges are made.

Events can change their structure as new features are added to Mailgun, but we only add new fields and never modify or remove existing one.

Below you can find sample events of various types:

Accepted:

{
  "event": "accepted",
  "id": "ncV2XwymRUKbPek_MIM-Gw",
  "timestamp": 1377211256.096436,
  "tags": [],
  "envelope": {
    "sender": "sender@example.com"
  },
  "campaigns": [],
  "user-variables": {},
  "flags": {
    "is-authenticated": false,
    "is-test-mode": false
  },
  "routes": [
    {
      "priority": 1,
      "expression": "match_recipient(\".*@samples.mailgun.org\")",
      "description": "Sample route",
      "actions": [
        "stop()",
        "forward(\"http://host.com/messages\")"
      ]
    }
  ],
  "message": {
    "headers": {
      "to": "",
      "message-id": "77AF5C3CA1416D93FC47AF8AD42A60AD@example.com",
      "from": "John Doe <sender@example.com>",
      "subject": "Test Subject"
    },
    "attachments": [],
    "recipients": [
      "recipient@example.com"
    ],
    "size": 6021
  },
  "recipient": "recipient@example.com",
  "method": "smtp"
}

Delivered:

{
  "event": "delivered",
  "id": "W3X4JOhFT-OZidZGKKr9iA",
  "timestamp": 1377208314.173742,
  "tags": [],
  "envelope": {
    "transport": "smtp",
    "sender": "postmaster@samples.mailgun.org",
    "sending-ip": "184.173.153.199"
  },
  "delivery-status": {
    "message": "",
    "code": 0,
    "description": null
  },
  "campaigns": [],
  "user-variables": {},
  "flags": {
    "is-authenticated": true,
    "is-test-mode": false
  },
  "message": {
    "headers": {
      "to": "recipient@example.com",
      "message-id": "20130822215151.29325.59996@samples.mailgun.org",
      "from": "sender@example.com",
      "subject": "Sample Message"
    },
    "attachments": [],
    "recipients": [
      "recipient@example.com"
    ],
    "size": 31143
  },
  "recipient": "recipient@example.com",
}

Failed:

{
  "event": "failed",
  "id": "pVqXGJWhTzysS9GpwF2hlQ",
  "timestamp": 1377198389.769129,
  "severity": "permanent",
  "tags": [],
  "envelope": {
    "transport": "smtp",
    "sender": "postmaster@samples.mailgun.org",
    "sending-ip": "184.173.153.199"
  },
  "delivery-status": {
    "message": "Relay Not Permitted",
    "code": 550,
    "description": null
  },
  "campaigns": [],
  "reason": "bounce",
  "user-variables": {},
  "flags": {
    "is-authenticated": true,
    "is-test-mode": false
  },
  "message": {
    "headers": {
      "to": "recipient@example.com",
      "message-id": "20130822185902.31528.73196@samples.mailgun.org",
      "from": "John Doe <sender@example.com>",
      "subject": "Test Subject"
    },
    "attachments": [],
    "recipients": [
      "recipient@example.com"
    ],
    "size": 557
  },
  "recipient": "recipient@example.com",
}

Opened:

{
  "event": "opened",
  "id": "-laxIqj9QWubsjY_3pTq_g",
  "timestamp": 1377047343.042277,
  "recipient": "recipient@example.com",
  "geolocation": {
    "country": "US",
    "region": "Texas",
    "city": "Austin"
  },
  "tags": [],
  "campaigns": [],
  "user-variables": {},
  "ip": "111.111.111.111",
  "client-info": {
    "client-type": "mobile browser",
    "client-os": "iOS",
    "device-type": "mobile",
    "client-name": "Mobile Safari",
    "user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B143"
  },
  "message": {
    "headers": {
      "message-id": "20130821005614.19826.35976@samples.mailgun.org"
    }
  },
}

Clicked:

{
  "event": "clicked",
  "id": "G5zMz2ysS6OxZ2C8xb2Tqg",
  "timestamp": 1377075564.094891,
  "recipient": "recipient@example.com",
  "geolocation": {
    "country": "US",
    "region": "TX",
    "city": "Austin"
  },
  "tags": [],
  "url": "http://google.com",
  "ip": "127.0.0.1",
  "campaigns": [],
  "user-variables": {},
  "client-info": {
    "client-type": "browser",
    "client-os": "Linux",
    "device-type": "desktop",
    "client-name": "Chromium",
    "user-agent": "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/28.0.1500.71 Chrome/28.0.1500.71 Safari/537.36"
  },
  "message": {
    "headers": {
      "message-id": "20130821085807.30688.67706@samples.mailgun.org"
    }
  },
}

Unsubscribed:

{
  "event": "unsubscribed",
  "id": "W3X4JOhFT-OZidZGKKr9iA",
  "timestamp": 1377213791.421473,
  "recipient": "recipient@example.com",
  "geolocation": {
    "country": "US",
    "region": "TX",
    "city": "San Antonio"
  },
  "campaigns": [],
  "tags": [],
  "user-variables": {},
  "ip": "50.51.14.451",
  "client-info": {
    "client-type": "browser",
    "client-os": "OS X",
    "device-type": "desktop",
    "client-name": "Chrome",
    "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
  },
  "message": {
    "headers": {
      "message-id": "20130822232216.13966.79700@samples.mailgun.org"
    }
  },
}

Complained:

{
  "event": "complained",
  "id": "ncV2XwymRUKbPek_MIM-Gw",
  "timestamp": 1377214260.049634,
  "recipient": "foo@example.com",
  "tags": [],
  "campaigns": [],
  "user-variables": {},
  "flags": {
    "is-test-mode": false
  },
  "message": {
    "headers": {
      "to": "foo@example.com",
      "message-id": "20130718032413.263EE2E0926@example.com",
      "from": "John Doe <sender@example.com>",
      "subject": "This is the subject."
    },
    "attachments": [],
    "size": 18937
  },
}

Stored:

{
   "event":"stored",
   "id": "czsjqFATSlC3QtAK-C80nw",
   "timestamp":1378335036.859382,
   "storage":{
      "url":"https://api.mailgun.net/v3/domains/ninomail.com/messages/WyI3MDhjODgwZTZlIiwgIjF6",
      "key":"WyI3MDhjODgwZTZlIiwgIjF6"
   },
   "campaigns":[],
   "user-variables":{},
   "flags":{
      "is-test-mode":false
   },
   "tags":[],
   "message":{
      "headers":{
         "to":"satshabad <satshabad@mailgun.com>",
         "message-id":"CAC8xyJxAO7Y0sr=3r-rJ4C6ULZs3cSVPPqYEXLHtarKOKaOCKw@mail.gmail.com",
         "from":"Someone <someone@example.com>",
         "subject":"Re: A TEST"
      },
      "attachments":[],
      "recipients":[
         "satshabad@mailgun.com"
      ],
      "size":2566
   },
}

Examples

Fetches the first page of log records that are older than Fri, 3 May 2013 09:00:00 -0000 and correspond to delivery to joe@example.com:

curl -s --user 'api:YOUR_API_KEY' -G \
      https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/events \
      --data-urlencode begin='Fri, 3 May 2013 09:00:00 -0000' \
      --data-urlencode ascending=yes \
      --data-urlencode limit=25 \
      --data-urlencode pretty=yes \
      --data-urlencode recipient=joe@example.com
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;

import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;

public class MGSample {

    // ...

    public static ClientResponse GetLogs() {

        Client client = ClientBuilder.newClient();
        client.register(HttpAuthenticationFeature.basic(
            "api",
            "YOUR_API_KEY"
        ));

        WebTarget mgRoot = client.target("https://api.mailgun.net/v3");

        return mgRoot
            .path("/{domain}/events")
            .resolveTemplate("domain", "YOUR_DOMAIN_NAME")
            .queryParam("begin", 50);
            .queryParam("ascending", "yes");
            .queryParam("limit", 1);
            .queryParam("pretty", "yes");
            .queryParam("recipient", "joe@example.com");
            .request()
            .buildGet()
            .invoke(ClientResponse.class);
    }
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = new Mailgun('YOUR_API_KEY');
$domain = 'YOUR_DOMAIN_NAME';
$queryString = array(
    'begin'        => 'Fri, 3 May 2013 09:00:00 -0000',
    'ascending'    => 'yes',
    'limit'        =>  25,
    'pretty'       => 'yes',
    'subject'      => 'test'
);

# Make the call to the client.
$result = $mgClient->get("$domain/events", $queryString);
def get_logs():
    return requests.get(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/events",
        auth=("api", "YOUR_API_KEY"),
        params={"begin"       : "Fri, 3 May 2013 09:00:00 -0000",
                "ascending"   : "yes",
                "limit"       :  25,
                "pretty"      : "yes",
                "recipient" : "joe@example.com"})
def get_logs
  RestClient.get "https://api:YOUR_API_KEY"\
  "@api.mailgun.net/v3/YOUR_DOMAIN_NAME/events",
   :params => {
    :'begin'       => 'Fri, 3 May 2013 09:00:00 -0000',
    :'ascending'   => 'yes',
    :'limit'       =>  25,
    :'pretty'      => 'yes',
    :'recipient' => 'joe@example.com'
   }
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class EventsDateTimeRecipientChunk
{

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

    public static IRestResponse EventsDateTimeRecipient ()
    {
        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 = "{domain}/events";
        request.AddParameter ("begin", "Fri, 3 May 2013 09:00:00 -0000");
        request.AddParameter ("ascending", "yes");
        request.AddParameter ("limit", 25);
        request.AddParameter ("pretty", "yes");
        request.AddParameter ("recipient", "joe@example.com");
        return client.Execute (request);
    }

}
func GetLog(domain, apiKey string) ([]mailgun.Event, error) {
  mg := mailgun.NewMailgun(domain, apiKey, "")
  ei := mg.NewEventIterator()
  err := ei.GetFirstPage(mailgun.GetEventsOptions{
    Begin:          time.Now().Add(-50 * Time.Minute),
    ForceAscending: true,
    Limit:          1,
    Filter:         map[string]string{
      "recipient": "joe@example.com",
    }
  })
  if err != nil {
    return nil, err
  }
  return ei.Events(), nil
}

Sample response:

{
  "items": [
    {
      "tags": [],
      "id": "czsjqFATSlC3QtAK-C80nw",
      "timestamp": 1376325780.160809,
      "envelope": {
        "sender": "me@samples.mailgun.org",
        "transport": ""
      },
      "event": "accepted",
      "campaigns": [],
      "user-variables": {},
      "flags": {
        "is-authenticated": true,
        "is-test-mode": false
      },
      "message": {
        "headers": {
          "to": "foo@example.com",
          "message-id": "20130812164300.28108.52546@samples.mailgun.org",
          "from": "Excited User <me@samples.mailgun.org>",
          "subject": "Hello"
        },
        "attachments": [],
        "recipients": [
          "foo@example.com",
          "baz@example.com",
          "bar@example.com"
        ],
        "size": 69
      },
      "recipient": "baz@example.com",
      "method": "http"
    }
  ],
  "paging": {
    "next":
        "https://api.mailgun.net/v3/samples.mailgun.org/events/W3siY...",
    "previous":
        "https://api.mailgun.net/v3/samples.mailgun.org/events/Lkawm..."
  }
}

Fetches the first page of log records that contain different types of failure, starting from the most recent:

curl -s --user 'api:YOUR_API_KEY' -G \
    https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/events \
    --data-urlencode event='rejected OR failed'
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;

import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;

public class MGSample {

    // ...

    public static ClientResponse GetLogs() {

        Client client = ClientBuilder.newClient();
        client.register(HttpAuthenticationFeature.basic(
            "api",
            "YOUR_API_KEY"
        ));

        WebTarget mgRoot = client.target("https://api.mailgun.net/v3");

        return mgRoot
            .path("/{domain}/events")
            .resolveTemplate("domain", "YOUR_DOMAIN_NAME")
            .queryParam("event", "rejected OR failed");
            .request()
            .buildGet()
            .invoke(ClientResponse.class);
    }
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = new Mailgun('YOUR_API_KEY');
$domain = 'YOUR_DOMAIN_NAME';
$queryString = array('event' => 'rejected OR failed');

# Make the call to the client.
$result = $mgClient->get("$domain/events", $queryString);
def get_logs():
    return requests.get(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/events",
        auth=("api", "YOUR_API_KEY"),
        params={"event" : "rejected OR failed"})
def get_logs
  RestClient.get "https://api:YOUR_API_KEY"\
  "@api.mailgun.net/v3/YOUR_DOMAIN_NAME/events",
  :params => {
    :"event" => 'rejected OR failed'
  }
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class EventsFailureChunk
{

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

    public static IRestResponse EventsFailure ()
    {
        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 = "{domain}/events";
        request.AddParameter ("event", "rejected OR failed");
        return client.Execute (request);
    }

}
func GetLog2(domain, apiKey string) ([]mailgun.Event, error) {
  mg := mailgun.NewMailgun(domain, apiKey, "")
  ei := mg.NewEventIterator()
  err := ei.GetFirstPage(mailgun.GetEventsOptions{
    Filter:         map[string]string{
      "event": "rejected OR failed",
    }
  })
  if err != nil {
    return nil, err
  }
  return ei.Events(), nil
}
{
  "items": [
    {
      "severity": "temporary",
      "tags": [],
      "id": "czsjqFATSlC3QtAK-C80nw",
      "envelope": {
        "sender": "me@samples.mailgun.org",
        "transport": ""
      },
      "delivery-status": {
        "code": 498,
        "message": "No MX for [example.com]",
        "retry-seconds": 900,
        "description": "No MX for [example.com]"
      },
      "campaigns": [],
      "reason": "generic",
      "user-variables": {},
      "flags": {
        "is-authenticated": true,
        "is-test-mode": false
      },
      "timestamp": 1376435471.10744,
      "message": {
        "headers": {
          "to": "baz@example.com, bar@example.com",
          "message-id": "20130813230036.10303.40433@samples.mailgun.org",
          "from": "Excited User <me@samples.mailgun.org>",
          "subject": "Hello"
        },
        "attachments": [],
        "recipients": [
          "baz@example.com",
          "bar@example.com"
        ],
        "size": 370
      },
      "recipient": "bar@example.com",
      "event": "failed"
    }
  ],
  "paging": {
    "next":
        "https://api.mailgun.net/v3/samples.mailgun.org/events/W3siY...",
    "previous":
        "https://api.mailgun.net/v3/samples.mailgun.org/events/Lkawm..."
  }
}

Fetches the first page of log records written so far. Traversal is performed starting from the most recent records to the oldest:

curl -s --user 'api:YOUR_API_KEY' -G \
    https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/events
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;

import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;

public class MGSample {

    // ...

    public static ClientResponse GetLogs() {

        Client client = ClientBuilder.newClient();
        client.register(HttpAuthenticationFeature.basic(
            "api",
            "YOUR_API_KEY"
        ));

        WebTarget mgRoot = client.target("https://api.mailgun.net/v2");

        return mgRoot
            .path("/{domain}/events")
            .resolveTemplate("domain", "YOUR_DOMAIN_NAME")
            .request()
            .buildGet()
            .invoke(ClientResponse.class);
    }
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = new Mailgun('YOUR_API_KEY');
$domain = 'YOUR_DOMAIN_NAME';

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

public class EventsTraversalChunk
{

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

    public static IRestResponse EventsTraversal ()
    {
        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 = "{domain}/events";
        return client.Execute (request);
    }

}
// coming soon

Fetches the next page of log records, assuming that the URL was returned by the previous request:

curl -s --user 'api:YOUR_API_KEY' -G \
    https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/events/W3siYSI6IGZhbHNlLC
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;

import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;

import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;

public class MGSample {

    // ...

    public static ClientResponse GetLogs() {

        Client client = ClientBuilder.newClient();
        client.register(HttpAuthenticationFeature.basic(
            "api",
            "YOUR_API_KEY"
        ));

        WebTarget mgRoot = client.target("https://api.mailgun.net/v2");

        return mgRoot
            .path("/{domain}/events/{page_id}")
            .resolveTemplate("domain", "YOUR_DOMAIN_NAME")
            .resolveTemplate("page_id", "W3siYSI6IGZhbHNlLC")
            .request()
            .buildGet()
            .invoke(ClientResponse.class);
    }
}
# Include the Autoloader (see "Libraries" for install instructions)
require 'vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = new Mailgun('YOUR_API_KEY');
$domain = 'YOUR_DOMAIN_NAME';
$nextPage = 'W3siYSI6IGZhbHNlLC';

# Make the call to the client.
$result = $mgClient->get("$domain/events/$nextPage");
def get_logs():
    return requests.get(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/events/W3siYSI6IGZhbHNlLC",
        auth=("api", "YOUR_API_KEY"))
def get_logs
  RestClient.get "https://api:YOUR_API_KEY"\
  "@api.mailgun.net/v3/YOUR_DOMAIN_NAME/events/W3siYSI6IGZhbHNlLC"}
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class EventsPaginationChunk
{

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

    public static IRestResponse EventsPagination ()
    {
        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 = "{domain}/events/W3siYSI6IGZhbHNlLC";
        return client.Execute (request);
    }

}
func GetLog2(domain, apiKey string) ([]mailgun.Event, error) {
  mg := mailgun.NewMailgun(domain, apiKey, "")
  ei := mg.NewEventIterator()
  err := ei.GetFirstPage(mailgun.GetEventsOptions{
    Filter:         map[string]string{
      "event": "rejected OR failed",
    }
  })
  if err != nil {
    return nil, err
  }
  // ...
  err = ei.GetNext()
  if err != nil {
    return nil, err
  }
  events := ei.Events()
  if len(events) == 0 {
    return nil, fmt.Errorf("No more events")
  }
  return events, nil
}