Tags

Mailgun lets you tag each outgoing message with a custom value and provides statistics on the tag level. To tag a message you need to provide one or more o:tag parameter in the API. Tags are created on the fly but they are subject to a limit.

The tags API endpoint is available at:

v3/<domain>/tags

Note

Unicode characters are not allowed in tags. Any unicode characters found in tags are stripped from the tag. If tag is entirely unicode characters, the tag is ignored.

GET /<domain>/tags

Returns a list of tags for a domain. Provides pagination urls if the result set is too long to be returned in a single response.

Parameter Description
domain Name of the domain
limit Number of entries to return. Default: 100.
GET /<domain>/tags/<tag>

Returns a given tag.

Parameter Description
domain Name of the domain
tag Name of the tag
PUT /<domain>/tags/<tag>

Updates a given tag with the information provided.

Parameter Description
domain Name of the domain
tag Name of the tag
description Optional description of a tag.
GET /<domain>/tags/<tag>/stats

Returns statistics for a given tag.

Parameter Description
event The type of the event. For a complete list of all events written to the log see the Event Types table below. (Required)
start The starting time. Should be in RFC 2822#page-14 or unix epoch format. Default: 7 days from the current time.
end The ending date. Should be in RFC 2822#page-14 or unix epoch time in seconds. Default: current time.
resolution Can be either hour, day or month. Default: day
duration Period of time with resolution encoded. See Duration for more info. If provided, overwrites the start date and resolution.
DELETE /<domain>/tags/<tag>

Deletes the tag. Note: The statistics for the tag are not destroyed.

Parameter Description
domain Name of the domain
GET /<domain>/tags/<tag>/stats/aggregates/countries

Returns a list of countries of origin for a given domain for different event types.

GET /<domain>/tags/<tag>/stats/aggregates/providers

Returns a list of email providers for a given domain for different event types.

GET /<domain>/tags/<tag>/stats/aggregates/devices

Returns a list of devices for a given domain that have triggered event types.

Duration

Duration is a string that represents a period of time with some resolution. It has a format [0-9]+[m,d,h] where

  • h - an hour
  • d - a day
  • m - a month

Examples:

  • 24h - a period of 24 hours (a day) with hourly resolution
  • 1d - a period of 1 day with daily resolution
  • 2m - a period of 2 months with monthly resolution

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.
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

Examples

Retrieve all tags for a domain:

curl -s --user 'api:YOUR_API_KEY' -G \
   https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/tags \
   -d limit=10
import com.mailgun.api.v3.MailgunTagsApi;
import com.mailgun.model.tags.TagsResult;

// ...

public TagsResult getTags() {
    MailgunTagsApi mailgunTagsApi = MailgunClient.config(API_KEY)
        .createApi(MailgunTagsApi.class);

    return mailgunTagsApi.getAllTags(YOUR_DOMAIN_NAME, 10);
}
# 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->tags()->index($domain);
def get_stats():
    return requests.get(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/tags",
        auth=("api", "YOUR_API_KEY"),
        params={"limit": 10})
def get_stats
  url_params = {}
  url_params[:limit] = 10
  query_string = url_params.collect {|k, v| "#{k.to_s}=#{CGI::escape(v.to_s)}"}.
    join("&")
  RestClient.get "https://api:YOUR_API_KEY"\
  "@api.mailgun.net/v3/YOUR_DOMAIN_NAME/tags?#{query_string}"
end
using System;
using System.IO;
using RestSharp;
using RestSharp.Authenticators;

public class GetTagsChunk
{

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

    public static IRestResponse GetTags ()
    {
        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}/tags";
        request.AddParameter ("limit", 10);
        return client.Execute (request);
    }

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

func ListTags(domain, apiKey string) ([]mailgun.Tag, error) {
    mg := mailgun.NewMailgun(domain, apiKey)
    it := mg.ListTags(nil)

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

    var page, result []mailgun.Tag
    for it.Next(ctx, &page) {
        result = append(result, page...)
    }

    if it.Err() != nil {
        return nil, it.Err()
    }
    return result, nil
}
const DOMAIN = 'YOUR_DOMAIN_NAME';

 import formData from 'form-data';
 import Mailgun from 'mailgun.js';

 const mailgun = new Mailgun(formData);

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

Sample response:

{
  "items": [
      {
        "tag": "red",
        "description": "red signup button",
      },
      {
        "tag": "green",
        "description": "green signup button",
      },
  ],
  "paging": {
    "next":
        "https://url_to_next_page",
    "previous":
        "https://url_to_previous_page",
    "first":
        "https://url_to_first_page",
    "last":
        "https://url_to_last_page"
  }
}

Delete tag:

curl -s --user 'api:YOUR_API_KEY' -X DELETE \
    https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/tags/newsletter
import com.mailgun.api.v3.MailgunTagsApi;
import com.mailgun.model.ResponseWithMessage;

// ...

public ResponseWithMessage deleteTag() {
    MailgunTagsApi mailgunTagsApi = MailgunClient.config(API_KEY)
        .createApi(MailgunTagsApi.class);

    return mailgunTagsApi.deleteTag(YOUR_DOMAIN_NAME, TAG_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';
$tag    = 'my_tag';

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

public class DeleteTagChunk
{

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

    public static IRestResponse DeleteTag ()
    {
        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}/tags/{tag}";
        request.AddUrlSegment ("tag", "newsletter");
        request.Method = Method.DELETE;
        return client.Execute (request);
    }

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

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

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

    return mg.DeleteTag(ctx, "newsletter")
}
const DOMAIN = 'YOUR_DOMAIN_NAME';

import formData from 'form-data';
import Mailgun from 'mailgun.js';

const mailgun = new Mailgun(formData);

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

Sample response:

{
  "message": "Tag deleted"
}

Retrieve all countries of origin for a domain with event types:

curl -v -s --user 'api:YOUR_API_KEY' \
https://api.mailgun.net/v3/<domain>/tags/<tag>/stats/aggregates/countries
const DOMAIN = 'YOUR_DOMAIN_NAME';

import formData from 'form-data';
import Mailgun from 'mailgun.js';

const mailgun = new Mailgun(formData);

const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
 (async () => {
    try {
      const countriesAggregation = await client.domains.domainTags.countries(
          DOMAIN,
          'YOUR_TAG_NAME'
      );
      console.log('countriesAggregation', countriesAggregation);
    } catch (error) {
      console.error(error);
    }
 })();

Sample response:

{
  "country": {
      "ad": {
          "clicked": 7,
          "complained": 4,
          "opened": 18,
          "unique_clicked": 0,
          "unique_opened": 2,
          "unsubscribed": 0
      },
      "ck": {
          "clicked": 13,
          "complained": 2,
          "opened": 1,
          "unique_clicked": 1,
          "unique_opened": 0,
          "unsubscribed": 2
      }
  },
  "tag": "exampletag"
}

Retrieve all providers of a domain with corresponding event types:

curl -v -s --user 'api:YOUR_API_KEY' \
https://api.mailgun.net/v3/<domain>/tags/<tag>/stats/aggregates/providers
const DOMAIN = 'YOUR_DOMAIN_NAME';

import formData from 'form-data';
import Mailgun from 'mailgun.js';

const mailgun = new Mailgun(formData);

const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
  try {
    const providersAggregation = await client.domains.domainTags.providers(
      DOMAIN,
      'YOUR_TAG_NAME'
    );
    console.log('providersAggregation', providersAggregation);
  } catch (error) {
    console.error(error);
  }
})();
{
  "provider": {
      "gmail.com": {
          "accepted": 23,
          "clicked": 15,
          "complained": 0,
          "delivered": 23,
          "opened": 19,
          "unique_clicked": 2,
          "unique_opened": 7,
          "unsubscribed": 1
      },
      "yahoo.com": {
          "accepted": 16,
          "clicked": 8,
          "complained": 2,
          "delivered": 8,
          "opened": 4,
          "unique_clicked": 0,
          "unique_opened": 0,
          "unsubscribed": 0
      }
  },
  "tag": "exampletag"
}

Retrieve all devices that have triggered an event type in a domain:

curl -v -s --user 'api:YOUR_API_KEY' \
https://api.mailgun.net/v3/<domain>/tags/<tag>/stats/aggregates/devices
const DOMAIN = 'YOUR_DOMAIN_NAME';

import formData from 'form-data';
import Mailgun from 'mailgun.js';

const mailgun = new Mailgun(formData);

const client = mailgun.client({ username: 'api', key: 'YOUR_API_KEY' || '' });
(async () => {
  try {
    const devicesAggregation = await client.domains.domainTags.devices(
      DOMAIN,
      'YOUR_TAG_NAME'
    );
    console.log('providersAggregation', devicesAggregation);
  } catch (error) {
    console.error(error);
  }
})();
{
  "device": {
      "desktop": {
          "clicked": 8,
          "complained": 1,
          "opened": 8,
          "unique_clicked": 0,
          "unique_opened": 0,
          "unsubscribed": 0
      },
      "mobile": {
          "clicked": 3,
          "complained": 1,
          "opened": 5,
          "unique_clicked": 0,
          "unique_opened": 0,
          "unsubscribed": 0
      }
  },
  "tag": "exampletag"
}