Skip to content
Last updated

PHP SDK

The official PHP wrapper for the Mailjet API is installed with Composer as mailjet/mailjet-apiv3-php and developed at mailjet/mailjet-apiv3-php.

Current release: 2.0.0

Compatibility

The library requires PHP 8.1 or higher.

Installation

composer require mailjet/mailjet-apiv3-php

The wrapper needs a PSR-18 HTTP client and PSR-17 factories. If your project does not already have one, Composer installs a compatible default (such as Guzzle) via php-http/discovery.

To pin a specific client, require it explicitly:

# Guzzle
composer require guzzlehttp/guzzle

# Symfony HttpClient
composer require symfony/http-client nyholm/psr7

Bring your own HTTP client

Since 2.0 the transport layer is fully delegated to the injected PSR-18 client, which is what makes timeouts, proxies and retries your own to configure:

use \Mailjet\Client;

// auto-discovery (default) — uses whatever PSR-18 client is installed
$mj = new Client($apikey, $apisecret);

// inject a specific HTTP client
$httpClient = new \GuzzleHttp\Client(['timeout' => 30, 'proxy' => 'tcp://localhost:8080']);
$mj = new Client($apikey, $apisecret, true, [], $httpClient);

// inject a Symfony HttpClient
$httpClient = new \Symfony\Component\HttpClient\Psr18Client();
$mj = new Client($apikey, $apisecret, true, [], $httpClient);

PSR-17 request and stream factories can be injected as the sixth and seventh constructor arguments.

Authentication

The Email API authenticates with your API key and secret:

export MJ_APIKEY_PUBLIC='your API key'
export MJ_APIKEY_PRIVATE='your API secret'
use \Mailjet\Resources;

$apikey = getenv('MJ_APIKEY_PUBLIC');
$apisecret = getenv('MJ_APIKEY_PRIVATE');

$mj = new \Mailjet\Client($apikey, $apisecret);

The SMS API authenticates with a bearer token instead — see SMS API.

Send your first email

<?php
require 'vendor/autoload.php';

use \Mailjet\Resources;

$mj = new \Mailjet\Client(
    getenv('MJ_APIKEY_PUBLIC'),
    getenv('MJ_APIKEY_PRIVATE'),
    true,
    ['version' => 'v3.1']
);

$body = [
    'Messages' => [
        [
            'From' => [
                'Email' => 'pilot@example.com',
                'Name' => 'Mailjet Pilot'
            ],
            'To' => [
                [
                    'Email' => 'passenger@example.com',
                    'Name' => 'Passenger 1'
                ]
            ],
            'Subject' => 'My first Mailjet Email!',
            'TextPart' => 'Greetings from Mailjet!',
            'HTMLPart' => '<h3>Dear passenger 1, welcome to Mailjet!</h3>'
        ]
    ]
];

$response = $mj->post(Resources::$Email, ['body' => $body]);

$response->success() && var_dump($response->getData());

Client and call configuration

The constructor signature is:

new \Mailjet\Client(
    $MJ_APIKEY_PUBLIC,
    $MJ_APIKEY_PRIVATE,
    $CALL,
    $OPTIONS,
    $HTTP_CLIENT,
    $REQUEST_FACTORY,
    $STREAM_FACTORY
);
ArgumentMeaning
$MJ_APIKEY_PUBLICpublic API key
$MJ_APIKEY_PRIVATEprivate API key
$CALLboolean; true performs the actual API call
$OPTIONSassociative array of connection options
$HTTP_CLIENToptional PSR-18 ClientInterface — auto-discovered if null
$REQUEST_FACTORYoptional PSR-17 RequestFactoryInterface
$STREAM_FACTORYoptional PSR-17 StreamFactoryInterface

API versioning

VersionScope
v3Email API
v3.1Send API v3.1 (latest send version)
v4SMS API, contact delete API

Most Email API endpoints sit under v3, which is the default. For anything else, set version:

$mj = new \Mailjet\Client(
    getenv('MJ_APIKEY_PUBLIC'),
    getenv('MJ_APIKEY_PRIVATE'),
    true,
    ['version' => 'v3.1']
);

Base URL

The default base domain is api.mailjet.com. Override it with url:

$mj = new \Mailjet\Client(
    getenv('MJ_APIKEY_PUBLIC'),
    getenv('MJ_APIKEY_PRIVATE'),
    true,
    ['url' => 'api.us.mailjet.com']
);

Accounts on Mailjet's US architecture must set api.us.mailjet.com.

Network connectivity

If you hit intermittent SSL_ERROR_SYSCALL errors, force IPv4 on your HTTP client:

$httpClient = new \GuzzleHttp\Client(['force_ip_resolve' => 'v4']);
$mj = new \Mailjet\Client(getenv('MJ_APIKEY_PUBLIC'), getenv('MJ_APIKEY_PRIVATE'), true, [], $httpClient);

Disable the API call

Useful in tests, to build a request without reaching Mailjet — set the third argument to false:

$mj = new \Mailjet\Client(getenv('MJ_APIKEY_PUBLIC'), getenv('MJ_APIKEY_PRIVATE'), false);

Request examples

All resources are constants on the Resources class, which maps PHP resource names to their API reference names. The full list is in /src/Mailjet/Resources.php.

$response = $mj->delete(Resources::$Template, ['id' => $id]);
$response = $mj->put(Resources::$ContactData, ['id' => $id, 'body' => $body]);
$response = $mj->post(Resources::$ContactManagecontactslists, ['id' => $id, 'body' => $body]);

POST — create an object

$params accepts body (the object to create) and id (when acting on an existing resource).

$body = [
    'Email' => 'passenger@example.com'
];

$response = $mj->post(Resources::$Contact, ['body' => $body]);
$response->success() && var_dump($response->getData());

POST — endpoints with an action

$body = [
    'ContactsLists' => [
        [
            'ListID' => $listID1,
            'Action' => 'addnoforce'
        ],
        [
            'ListID' => $listID2,
            'Action' => 'addforce'
        ]
    ]
];

$response = $mj->post(Resources::$ContactManagecontactslists, ['id' => $id, 'body' => $body]);

GET — all objects

$params accepts id (a single object) and filters (query parameters).

$response = $mj->get(Resources::$Contact);
$response->success() && var_dump($response->getData());

GET — with filters

$filters = [
    'IsExcludedFromCampaigns' => 'false'
];

$response = $mj->get(Resources::$Contact, ['filters' => $filters]);

GET — with paging and sorting

$filters = [
    'Limit' => 40,   // default 10, maximum 1000
    'Offset' => 20,
    'Sort' => 'ArrivedAt DESC',
    'Contact' => $contact->ID,
    'showSubject' => true
];

$response = $mj->get(Resources::$Message, ['filters' => $filters]);

GET — a single object

$response = $mj->get(Resources::$Contact, ['id' => $id]);

PUT — update an object

A PUT in the Mailjet API behaves like a PATCH: only the properties you send are updated, everything else is left untouched, and non-mandatory properties can be omitted.

$body = [
    'first_name' => 'John',
    'last_name' => 'Smith'
];

$response = $mj->put(Resources::$ContactData, ['id' => $id, 'body' => $body]);

DELETE — remove an object

A successful DELETE returns 204 No Content with no response body.

$response = $mj->delete(Resources::$Template, ['id' => $id]);

Contact deletion (GDPR) uses the v4 endpoint:

$mj = new \Mailjet\Client(
    getenv('MJ_APIKEY_PUBLIC'),
    getenv('MJ_APIKEY_PRIVATE'),
    true,
    ['version' => 'v4']
);

$response = $mj->delete(Resources::$Contacts, ['ID' => $contactID]);

Response object

get, post, put and delete return a Response object:

MethodReturns
success()whether the call succeeded
getStatus()HTTP status code (200, 400, …)
getData()the Data property of the JSON payload as a PHP associative array, or the full payload if there is none
getCount()number of objects returned
getReasonPhrase()HTTP reason phrase ("OK", "Bad Request", …)

SMS API

SMS endpoints authenticate with a bearer token generated in the SMS section of your account. Pass the token as the first argument and NULL as the second:

$mj = new \Mailjet\Client(
    getenv('MJ_APITOKEN'),
    NULL,
    true,
    ['url' => 'api.mailjet.com', 'version' => 'v4', 'call' => false]
);

$body = [
    'Text' => 'Have a nice SMS flight with Mailjet!',
    'To' => '+33600000000',
    'From' => 'MJPilot',
];

$response = $mj->post(Resources::$SmsSend, ['body' => $body]);
$response->success() && var_dump($response->getData());

Further examples

Emoji in a subject line

Use the string utility to get the UTF notation the API expects:

use \Mailjet\Resources;

$subject = \Mailjet\Utility\StringUtility::utfStringNotation('This is a subject with emoji 🤑');

$body = [
    'Locale' => 'en_US',
    'Sender' => 'sender@example.com',
    'SenderEmail' => 'sender@example.com',
    'Subject' => $subject,
    'TemplateID' => 12345,
    'ContactsListID' => 12345,
    'Title' => 'Emoji Test ' . time(),
];

$response = $mj->post(Resources::$Campaigndraft, ['body' => $body]);

Retrieve campaigns with filters

Without query parameters, only campaigns sent since 00:00 UTC today are returned — set period to widen the window:

$filters = [
    'period' => 'Year',
];

$response = $mj->get(Resources::$Campaign, ['filters' => $filters]);

Retrieve ESP statistics

$filters = [
    'CampaignID' => 123456,
];

$response = $mj->get(Resources::$Useragentstatistics, ['filters' => $filters]);

Campaign overview

$response = $mj->get(Resources::$Campaignoverview);

Data transfer objects

DTOs give you typed objects instead of raw arrays:

use Mailjet\Model\MailjetCampaignDataDTO;
use \Mailjet\Resources;

$filters = [
    'period' => 'Month',
    'Limit' => 10,
];

$response = $mj->get(
    Resources::$Campaigndraft + ['model' => MailjetCampaignDataDTO::class],
    ['filters' => $filters]
);

foreach ($response->getData() as $campaign) {
    /** @var MailjetCampaignDataDTO $campaign */
    print_r($campaign);
}

Create a template via the API

Creating a template takes two calls: one for the metadata, one for the content. The content endpoint does not accept MJML — send HTML and text parts.

$body = [
    'Author' => 'John Doe',
    'Copyright' => 'Mailjet',
    'Description' => 'Used to send out promo codes.',
    'EditMode' => 2,
    'IsStarred' => false,
    'IsTextPartGenerationEnabled' => true,
    'Locale' => 'en_US',
    'Name' => 'promo-codes',
    'OwnerType' => 'user',
    'Purposes' => ['marketing'],
];

$response = $mj->post(Resources::$Template, ['body' => $body]);
$id = $response->getData()[0]['ID'];

if ($id) {
    $content = [
        'Headers' => '',
        'Html-part' => '<h3>Dear passenger, welcome to Mailjet!</h3>',
        'MJMLContent' => '',
        'Text-part' => 'Dear passenger, welcome to Mailjet!'
    ];

    $mj->post(Resources::$TemplateDetailcontent, ['id' => $id, 'body' => $content]);
}

Contribute

The wrapper is open source. Fork the repository, branch, implement your fix or feature, document it, and open a pull request at mailjet/mailjet-apiv3-php. Documentation improvements belong in the API documentation repo.