Introduction

This document describes the Apostle.io Domain API. This API provides an interface to interact with your domain data. For the Delivery API, please see our Client Integration Guide.

The Domain Data API is a REST API for users and applications to access data on Apostle.io. This document describes how to access the API, what requests and responses are expected, and what data is available.

All requests are accessed over HTTPS at https://api.apostle.io/v1. All clients are responsible for validating the API’s SSL certificate.

All requests are made via GET, POST, PATCH and DELETE HTTP verbs. Do not use PUT in place of PATCH as these requests will 404.

Request data may be supplied either encoded as JSON, or key value “query string”pairs.

Authentication

You can find your API key in your account details page. All requests to the Apostle.io API are made on behalf of a user.

Authentication is implemented using OAuth 2.0 Bearer Tokens in the Authorization HTTP header.

1
Authorization: Bearer YOUR_API_KEY_HERE

This is not a full implementation of OAuth 2.0. Only the name and format of the Authorization header is used. API clients must obtain this authentication token via a non-OAuth-2.0 method.

Attempting an API request without the required Authorization header will result in a 401 Unauthorized response.

Attempting an API request not permitted by the provided Authorization header will result in a 403 Forbidden response. This is not the case for data belonging to a domain other than the requesting domain, which will result in a 404 Not Found response.

Errors

Error responses are represented by a suitable HTTP code (e.g. 404 Not Found or 422 Unprocessable Entity) and a JSON response body containing a message attribute.

Some types of error will extend this response body with additional attributes.

Validation Errors

A validation error encountered while creating a resource is represented by a 422 Unprocessable Entity response.

For each validation error that occured, the errors array in the response JSON container a resource name, field name and array of error messages.

1
2
3
4
5
6
7
8
9
HTTP/1.1 422 Unprocessable Entity Content-Type: application/json; charset=utf-8 { "message":"Invalid request", "errors":{ "name":["can't be blank"], "slug":["can't be blank"] } }

Representations

Resources are represented as JSON; either a single object, or an array of objects. The representation of a resource may contain nested child and parent resources.

1
2
3
4
5
6
7
8
HTTP/1.1 200 OK [ { "id": "42fa7ff1-4e07-4a0e-9602-a0250ddbd35b", "template_id": "98517045-c5f5-4840-987d-cab4ab0e19e0", "sent_from": "mal@mal.co.nz" } ]

Domains

GET /domains

Returns a collection of domains available.

1
2
3
4
5
6
7
8
9
10
HTTP/1.1 200 OK [ { "id": "ecc938ab-0969-479c-b948-198a20185c59", "hostname": "test.com" }, { "id": "42fa7ff1-4e07-4a0e-9602-a0250ddbd35b", "hostname": "example.com" } ]

GET /domains/:domain_id

Returns a single domain and various associated entities.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
HTTP/1.1 200 OK { "id": "ecc938ab-0969-479c-b948-198a20185c59", "hostname": "test.com", "delivery_provider": "smtp", "delivery_user_name": "user", "delivery_host": "0.0.0.0:1025", "delivery_authentication_type": "plain", "access_token": "…", "test_access_token": "…", "organization_id": null, "user_id": "ae2a4aad-f32d-41fa-b0a8-a1a76589ece0", "delivery_history": { "See /statistics for history payload" }, "recent_receipts": [ "See /receipts for receipts payload" ], "templates": [ "See /templates for templates payload" ], "partials": [ "See /partials for partials payload" ], "layouts": [ "See /layouts for layouts payload" ], "invites": [], "users": [], "owner": { "id": "ae2a4aad-f32d-41fa-b0a8-a1a76589ece0", "name": "Mal Curtis", "email": "mal@mal.co.nz", "type": "user", "billable": false } }

Layouts

GET /layouts/:layout_id

Returns a Layout.

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK { "id": "b7229af5-cab4-4f03-a08d-b37f2be1ded2", "name": "Standard", "body_html": "…", "body_text": "…", "styles": "…", "slug": "standard" }

POST /layouts

Creates a new Layout. Returns a single layout representation.

(One body format required)

PATCH /layouts/:layout_id

Updates a Layout. Returns a single layout representation.

(One body format required)

DELETE /layouts/:layout_id

Deletes a Layout.

Partials

GET /partials/:partial_id

Returns a Partial.

1
2
3
4
5
6
7
8
HTTP/1.1 200 OK { "id": "f2d7022b-3804-4eaa-add7-67cf2a147ff7", "name": "Support Sign Off", "body_html": "…", "body_text": "…", "slug": "support-sign-off" }

POST /partials

Creates a new Partial. Returns a single partial representation.

(One body format required)

PATCH /partials/:partial_id

Updates an existing Partial. Returns a single partial representation.

(One body format required)

DELETE /partials/:partial_id

Deletes a Partial.

Receipts

GET /receipts?template_id&query&states&from&since&exclude

Requires domain_id parameter

Returns a collection of Receipts. Send a collection of states keys to limit receipts to those states.

Valid states are; sent, delivered, failed, opened, clicked, bounced, dropped and spammed.

The query param will do a full text filter on the name and email address fields of the receipt.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
HTTP/1.1 200 OK [ { "id": "5d1c88fa-b07c-4ea7-9c51-81e4756e698e", "sent_from": "mal@mal.co.nz", "sent_to": "Mal Curtis <mal+1@mal.co.nz>", "sent_subject": "test", "sent_body_html": "…", "sent_body_text": null, "sent_headers": null, "state": "clicked", "error_message": null, "created_at": "2014-03-13T04:20:58.163Z", "delivered_at": "2014-03-13T04:20:58.380Z", "email": "mal@mal.co.nz", "name": "Mal Curtis", "template_id": "98517045-c5f5-4840-987d-cab4ab0e19e0", "payload": "{…}" } ]
Pagination

Receipt resultsets are limited in size and as such you may require to page through results. If no paging parameters are passed, you will receive the latest results, in descending order.

The from parameter will return descending results that are older than, or equal to, the supplied date. The since parameter will return ascending results that are newer than, or equal to, the supplied date.

A Note on Dates

Including the date supplied for from and since queries may be counter intuitive. The reason for this is that the finest granularity recorded for receipts is one second, and many receipts may be created within the same second. Because of this, we include the results for the supplied date. This may result in duplicates across pages. You can choose to deal with these duplicates yourself, or supply a comma separate list of receipt ids as the exclude parameter.

For example, if you had receipts 1, 2, 3 and 4 that were all created at 2014-01-15 12:00:00, and receipts 1 and 2 came back as part of a result set, you would call the receipts api with a since or from param of 2014-01-15 12:00:00 and excludes of 1,2. The resultset returned would include only the ids 3 and 4.

Sample Data

POST /sample_data?template_id

Creates a Sample Datum payload for the given Template. Returns a single Sample Datum representation.

1
2
3
4
5
6
7
HTTP/1.1 201 Created { "id":"d5e9e609-cf6f-43d6-875d-c9a32928fc0d", "name":"Sample Order", "data":"{…}", "template_id":"50f33f78-5677-4fcc-b7e7-a597323b7416" }

PATCH /sample_data/:sample_datum_id

Updates a Sample Datum. Returns a single Sample Datum representation.

DELETE /sample_data/:sample_datum_id

Deletes a Sample Datum.

Statistics

GET /statistics?template_id&date_range_end&date_range

Requires domain_id parameter

Returns both total and daily representations of delivery statistics for the given period. Defaults to 2 weeks ending on the current day. If no counts are available for a day, the value is null.

Requests for all statistics are trimmed to the first day with values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
HTTP/1.1 200 OK { "domain_id": "17a7b4d5-bcf6-42ca-8443-5a6593311fc5", "totals": { "sent": 2564, "opened": 1234, "clicked": 50, "spammed": 2, "dropped": 0, "bounced": 2 }, "history": { "2014-03-14": null, "2014-03-15": { "sent": 2564, "opened": 1234, "clicked": 50, "spammed": 2, "dropped": 0, "bounced": 2 }, "2014-03-16": null }, "period_start": "2014-03-14", "period_end": "2014-03-16" }

Templates

GET /templates/:template_id

Returns all information about a Template, including revision history and AB test information.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
HTTP/1.1 200 OK { "id": "50f33f78-5677-4fcc-b7e7-a597323b7416", "name": "Order Details", "slug": "order-details", "delivery_statistics": { "sent": 55, "delivered": 55, "bounced": 0, "dropped": 0, "spammed": 0, "opened": 2, "unopened": 53, "clicked": 0 }, "ab_test_state": false, "domain_id": "17a7b4d5-bcf6-42ca-8443-5a6593311fc5", "revisions": [ { "id": "329db4fe-c5b7-4c1f-a0cc-c6577ab72352", "template_id": "50f33f78-5677-4fcc-b7e7-a597323b7416", "layout_id": "b7229af5-cab4-4f03-a08d-b37f2be1ded2", "body_html": "…", "body_text": "…", "change_message": null, "from": "Mal Curtis <mal@mal.co.nz>", "subject": "test4.com tax invoice", "created_at": "2014-02-17T20:47:27.124Z" } ], "sample_data": [ { "id": "d5e9e609-cf6f-43d6-875d-c9a32928fc0d", "name": "Sample Order", "data": "…", "template_id": "50f33f78-5677-4fcc-b7e7-a597323b7416" } ], "layouts": [ { "id": "b7229af5-cab4-4f03-a08d-b37f2be1ded2", "name": "Standard", "body_html": "…", "body_text": "…", "styles": "…", "settings": {}, "slug": "standard" } ], "layout": { "id": "b7229af5-cab4-4f03-a08d-b37f2be1ded2", "name": "Standard", "body_html": "…", "body_text": "…", "styles": "…", "settings": {}, "slug": "standard" }, "partials": [ { "id": "f2d7022b-3804-4eaa-add7-67cf2a147ff7", "name": "Support Sign Off", "body_html": "…", "body_text": "…", "slug": "support-sign-off" } ], "delivery_history": { "2014-03-02": {…}, }, "deliverable_revision": { "id": "c626dafb-dd8b-4474-9f27-37617e70385a", "template_id": "50f33f78-5677-4fcc-b7e7-a597323b7416", "parent_id": "427a3617-6636-4505-9a5c-add09c8c91ee", "user_id": "872bf60f-185b-4ade-ab6c-eda63451c401", "state": "active", "change_message": null, "from": "Mal Curtis <mal@mal.co.nz>", "subject": "test4.com tax invoice!", "body_html": "…", "body_text": "…", "created_at": "2014-03-02T22:55:48.937Z", "updated_at": "2014-03-12T04:06:36.127Z", "layout_id": "b7229af5-cab4-4f03-a08d-b37f2be1ded2" } }

POST /templates

Creates a new Template. Returns a Template representation as per GET /templates/:template_id.

At this point, only name and slug are set - you can only create template content by posting a new revision to the Template itself.

PATCH /templates/:template_id

Updates a Template. Returns a Template representation as per GET /templates/:template_id.

You cannot update a Template’s content via PATCH. You must POST a new revision to the template itself.

POST /templates/:template_id

Creates a new Revision for a Template. Returns a Template representation as per GET /templates/:template_id.

DELETE /templates/:template_id

Deletes a Template.