Skip to content

Instantly share code, notes, and snippets.



Last active Dec 29, 2015
What would you like to do? integration Client Integration Guide is a web service for managing web app generated emails. This guide describes the requirements for writing a Client Library in any language.

Please check to see if there is a client library for your language already.

This gist lives at

Style Guide

While this guide describes a style of writing a library in a certain way, this style may not be appropriate for any individual language. It's up to the author to decide if the style is appropriate for the language or if there is a more appropriate API style.


Delivery works by posting a JSON body to A json header must be supplied Content-Type: application/json.

The JSON can contain multiple recipients, each sending a unique template. See the json files in this gist for more examples.


An “domain key” is required to send emails on behalf of an “domain”. This must be provided as an authentication header Authorization: Bearer DOMAIN_KEY.

An invalid domain key will return a 401 response.


A global singleton with configuration available should be made available. The minimum values required are domain_key and delivery_host. Sane defaults should be provided. The default delivery_host is, and the domain_key should default to a configuration method that the language provides. For example, in Ruby, the convention is to make configuration variables available via the ENV variable, so it defaults to ENV['DOMAIN_KEY].

# Setting a new domain key value
Apostle.domain_key = "My domain key"

Note: The delivery_host will not be changed in almost all cases. This is provided so that clients can be tested against non production delivery endpoints for testing and QA.

Note: For testing configuration, please see the testing section (tl;dr add a deliver bool setting so that real delivery can be turned off in test suites).

The Mail Class

A mail class should be defined to represent an email to a single recipient. This mail object should be able to accept any data, however the minimum requirement is the template id and email address.

You should be able to add any value to the mail object and have it added to an object called data. The only attributes that are reserved and should be at the root level are email, from, headers, layout_id, name and reply_to. This maps to the json that gets sent to the delivery endpoint.

See all_attributes.json in this gist for an example.

To deliver a mail object, a method deliver should be defined. In languages where there is a convention for methods that are 'hard' rather than 'soft' (i.e. they raise exceptions rather than returning false on failure) then both methods should be defined. For example, the Ruby client has both deliver and deliver! methods.

The Queue Class

A queue class should be provided to send multiple mail objects. Note: the deliver method should define a queue with itself on it, and send via the queue's deliver method. This saves having to write delivery code in multiple places.

A queue should be able to be instantiated, have mail objects added to it, and then get those mail objects delivered as a single JSON object to

See multiple_recipients.json for a multiple recipients example.

A queue should validate only the minimum requirements for a mail object to be valid; the template_id and email address. If any email on the queue is invalid, the entire queue should not be sent.

The manner in which you access the validation errors will most likely depend on the language, and how that sort of information is usually passed. For example, in Ruby the information is provided via a #results method, whereas in PHP the information is provided by passing a reference object to the deliver method that gets populated.


=> false

=> {

=> #<Apostle::DeliveryError @message="No recipient provided">


echo $queue->deliver($failures);
// false

echo count($failures);
// 2

echo $failures[0]->deliveryError();
// "No email provided"

echo $failures[1]->deliveryError();
// "No template provided"

API Response

All responses are JSON encoded. If an incorrect request is made, an error message describing the issue will be supplied

    "status": "error",
    "message": "Json Invalid: EOF",
    "request_data": ""

Successful responses will respond with a success message

    "status": "queued"


Unit tests are required before a client library will be accepted into the official repository.

To avoid integrators accidentally sending live emails in their test suite, you should provide a deliver configuration flag. While defaulting to true, if set to false it should not attempt to post to the delivery endpoint, and should always return a true response.

Getting Help

Anyone integrating with should reach out to Mal Curtis,, for help – I'm always happy to contribute and answer questions where I can.

"": {
"template_id": "welcome",
"name": "Mal Curtis (optional)",
"from": "Optional from override",
"headers": { "Optional": "Headers Object" },
"layout_id": "Optional layout override slug",
"reply_to": "Optional reply to address",
"data": {
"Any": "Other data that the template might need",
"for_example": "Orders may have an array of items",
"items": [
{ "name": "Widget Wheel", "price": "$5", "quantity": 2 },
{ "name": "Widget Tyre", "price": "$4", "quantity": 2 },
{ "name": "Widget Seat", "price": "$25", "quantity": 1 },
"": {"template_id": "welcome", "name": "Mal Curtis"},
"": {"template_id": "another-template", "name": "Mal Curtis"}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment