Skip to content

Instant API

TIP

Access to our APIs is evaluated on a case-by-case basis. To find out if your use case is one that we support feel free to get in touch with the details of your project. partners@litmus.com

Why the Instant API?

The Instant API is ideal for integration within email editing tools that have an iterative workflow which can be enhanced with real, rather than approximated, previews.

Our Instant API is the easiest and fastest way to get super speedy email client screenshots into your service. In fact, it's what Litmus uses to power its email client previews within Builder. If you haven't checked that out already, we'd recommend giving it a try to see the API in action.

The Instant API in action in Litmus Builder

In our editor, a user makes a change to their email and saves. The screenshots on the right automatically refresh within seconds.

How does it work?

When a user makes a change to their email, or tests it for the first time, you create a new Instant test by creating a POST request with details of the email. There's no need to send an email to us, simply POST the HTML and other details, along with a list of the email clients you'd like us to screenshot. We'll return a unique email id (email_guid) to you.

And that's it!

To show the screenshots to the user, all you need to do is set the src attribute of an img:

html
<img alt="Outlook 2003"
     src="https://instant-api.litmus.com/v1/emails/{email_guid}/previews/OL2003/full"/>

Litmus will handle the rest. For more granular control, you can specify fallback images to show in case there was a problem or timeout, or request the image server-side. We've covered all those specifics and more below, but even with the simplest implementation, we're sure you'll be thrilled with the ease of integration and the reliable performance.

How fast is fast?

Pretty damn fast. Where previews have traditionally taken many minutes to complete, Litmus' previews return within seconds without any accuracy cost---it's still real screenshots of real email clients. In the table below, we've included a sample of average completion times seen when using the Instant API. In all cases, you should expect previews to return in around 10 seconds or less.

Typically, creating an Instant Preview test will take 600ms to generate an email_guid. If your images are larger or take longer to download, you may see this step take a little longer.

Email clientAverage speed via the Instant API
Outlooks3s - 7s
iPhones & iPads7s
Android & Gmail apps7s - 10s
Gmail & Google apps5s - 8s
Yahoo, AOL, & Outlook.com5s - 11s
Apple Mails5s
Lotus Notes6s

Overview

Previews can be obtained in only two steps:

  1. POST an email
    Describe its content and attributes in JSON. In response, the API will provide you with an email_guid.

  2. GET each preview required
    Specify the email_guid and the desired client.

The GET request does not require authentication, so it can be used directly as the source for an image within an end user's browser.

Requiring that the email source is POSTed via HTTP, rather than waiting on email delivery, is one of the methods used to obtain the fast responses.

To capture the most reflective previews, please ensure that the email source provided has been through any transformation that would be applied by the Email Service Provider before being sent on to the mail transfer agent.

Base URI

The base URI of the API is https://instant-api.litmus.com/v1.

SSL/TLS

All API endpoints are only available via HTTPS.

Content types

By default all data is sent and received as application/json, exceptions to this are marked in the documentation.

CORS, JSONP

Neither CORS nor JSONP are currently supported. If you have a use case that would benefit from either, please let us know.

Authentication

The Instant API support authentication with either:

  • HTTP Basic Authentication - use an API key to make calls on behalf of your own account; or:
  • OAuth Bearer tokens - act on behalf of Litmus users with usage against their account

HTTP Basic Authentication

For each Instant API application, you'll be issued an API key. The API key should be provided in the Auth Basic username field. The password field can be left blank.

For the cURL examples shown below, either export your key to the API_KEY environment variable, e.g.

sh
$ export API_KEY="XeyNuXp_NdVtTREH1iaJ78vjFqlBGQfaJOur"

or replace $API_KEY in each example with your key directly. Note that the trailing colon will hint cURL to send the required empty password, rather than prompting you for it, e.g.

sh
curl -X "POST" "https://instant-api.litmus.com/v1/emails"\
  -H "Content-Type: application/json"\
  -u "$API_KEY:"\
  -d "{\"plain_text\":\"Hello World\"}" -v

OAuth Bearer Tokens

OAuth is useful when you wish to access the API on behalf of Litmus users, typically when you want to bring Litmus features to your own web application, but leverage the Litmus subscriptions that your users may already have.

Obtaining tokens requires implementing the OAuth2 flow within your application which involves sending each end user to litmus.com to authorize you to act on their behalf after which they're returned. See our guide on implementing the OAuth2 flow for detailed integration details.

To authorize an API request with a Bearer token, provide an HTTP Authorization header of Bearer $TOKEN (replacing $TOKEN appropriately), e.g.

sh
$ curl -X "POST" "https://instant-api.litmus.com/v1/emails"\
       -H "Content-Type: application/json"\
       -H "Authorization: Bearer a66841f0a212c0afb6344c6377df4dde0389922511540d9e3c1d11e2ab811a2e"\
       -d "{\"plain_text\":\"Hello World\"}" -v

> POST /v1/emails HTTP/1.1
> Host: instant-api.litmus.com
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Type: application/json
> Authorization: Bearer a66841f0a212c0afb6344c6377df4dde0389922511540d9e3c1d11e2ab811a2e
> Content-Length: 28
>

< HTTP/1.1 200 OK
< Server: nginx
< Date: Tue, 21 Jun 2016 20:10:06 GMT
< Content-Type: application/json;charset=utf-8
< Content-Length: 58
< Connection: keep-alive
< Strict-Transport-Security: max-age=3600; includeSubdomains; preload
< X-Frame-Options: DENY
< X-Content-Type-Options: nosniff
<

{
  "email_guid": "113bdfdf-6d54-4cbe-8d38-dd66157e1751"
}

Lifetimes

Emails

Uploaded emails are available to request new captures against for up to 48 hours. After this time, attempting to capture a new preview may yield a 404 Not Found when using the corresponding email_guid.

If access to unrequested previews is likely outside the 48 hour window, you can:

  • Pre-request previews if you know expected capture configurations; or:
  • Repost the email and obtain a fresh email_guid then capture a new preview using this

Previews

The image data following a successful capture will be available for 180 days. However, the storage location during this time may change. Once time has passed since a capture, a request to either the Instant API previews endpoint or a litmuscdn URL returned by the API will handle these changes in location gracefully—they will return a 404 Not Found when a capture is no longer available. Later requests to other locations, like the result of the redirection when the initial capture was made, may result in failure when a capture is still available.

If access to previews is likely outside the 180 day window, you can:

  • Download the previews when first captured and host them elsewhere

Example

To make our example less verbose, first download an example HTML email encoded in to the html_text property of a JSON object:

sh
$ wget https://docs.litmus.com/html-test-email.json

Next describe an email, providing your application's API key. This step is intended to be conducted server to server. Do not share the API key with your end users.

sh
$ curl -X "POST" "https://instant-api.litmus.com/v1/emails"\
       -H "Content-Type: application/json"\
       -u "$API_KEY:"\
       -d @html-test-email.json -v
> POST /v1/emails HTTP/1.1
> Authorization: Basic XXXXXXXXXXXXXXXXXXXXXX
> User-Agent: curl/7.37.1
> Host: instant-api.litmus.com
> Accept: */*
> Content-Type: application/json
> Content-Length: 59740
> Expect: 100-continue
>
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Server: nginx
< Date: Fri, 12 Jun 2015 16:58:38 GMT
< Content-Type: application/json
< Content-Length: 58
< Connection: keep-alive
< Strict-Transport-Security: max-age=3600;
<
{
  "email_guid": "87bf47f2-600e-40eb-8ccb-c9649f17644d"
}

Then simply construct a GET request for each capture you require, using the email_guid you just received and a code for the client you want (OL2015 in this example):

sh
$ curl -X "GET" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2015/full" -v
> GET /v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2015/full HTTP/1.1
> User-Agent: curl/7.37.1
> Host: instant-api.litmus.com
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx
< Date: Fri, 12 Jun 2015 17:37:40 GMT
< Content-Type: application/json
< Content-Length: 0
< Connection: keep-alive
< Location: https://ol2015.capture.litmuscdn.com/87bf47f2-600e-40eb-8ccb-c9649f17644d/results/ol2015-vertical-allowed.png
< Strict-Transport-Security: max-age=3600;
<

Behind the scenes a lot of work is going on between the GET being received and the response being provided—the capture of the preview is only initiated once the first request for it is received. While capture is occurring the HTTP connection remains open, once complete the response is sent and then the connection closed. Typically this will take around 6 seconds.

The GET URL can be embedded directly in an HTML image tag:

html
<html>
<body>
  <img src="https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2015/full">
</body>

Create an email

POST https://instant-api.litmus.com/v1/emails

This method expects to receive a JSON object describing an email's content and metadata and, in exchange, returns an email_guid required to capture previews of it.

We intend these objects to be treated as lightweight. Once uploaded, emails can't be modified. Obtain a new email_guid each time changes need to be reflected.

The uploaded email has a limited lifespan. As a result, a new email_guid should be obtained before requesting new previews if more than a day has passed since the last upload.

At least one of html_textplain_textraw_source must be provided.

Body parametersDescription
html_textstring

Quotes within the HTML must be escaped appropriately
plain_textstring
subjectstring
from_addressstring
from_display_namestring
raw_sourcestring

This field provides an alternative approach to defining the email and so is only valid in the absence of all the fields above
end_user_idstring

A unique identifier for your end users. When provided, we use this to partition your usage data. See Identifying End Users
configurationsarray of objects

An array of capture capture configurations as JSON objects. This allows pre-requesting previews that should be captured as soon as possible. This can be a useful performance optimisation. See the dedicated pre-request method for further detail on format
Errors
400 Bad Request
401 Unauthorized
JSON response body attributesDescription
email_guidA unique identifier for the uploaded email required to requests captures
end_user_idoptional

Confirmation if an end_user_id was provided in the request
configurationsoptional

Confirmation if configurations was provided in the request

Examples

sh
curl -X "POST" "https://instant-api.litmus.com/v1/emails"\
  -H "Content-Type: application/json"\
  -u "$API_KEY:"\
  -d "{\"plain_text\":\"Hello World\"}" -v
sh
$ curl -X "POST" "https://instant-api.litmus.com/v1/emails" \
       -H "Content-Type: application/json" \
       -H "Authorization: Bearer $TOKEN"\
       -d "{\"plain_text\":\"Hello World\"}" -v
ruby
Litmus::Instant.api_key = ENV["API_KEY"]
Litmus::Instant.create_email(plain_text: "Hello World")
# => {"email_guid"=>"ce6ba90f-cf28-4772-ab09-30a1d48a5e12"}
ruby
api_client = Litmus::Instant::Client.new(oauth_token: user_oauth_token)
api_client.create_email(plain_text: "Hello World")
# => {"email_guid"=>"ce6ba90f-cf28-4772-ab09-30a1d48a5e12"}

Result Format

200 OK

json
{
  "email_guid": "ce6ba90f-cf28-4772-ab09-30a1d48a5e12"
}

List supported email clients

GET https://instant-api.litmus.com/v1/clients

Returns a JSON array of email client names.

Examples

sh
curl -X "GET" "https://instant-api.litmus.com/v1/clients"
ruby
Litmus::Instant.clients
# => ["ANDROID4",
#     "ANDROIDGMAILAPP",
#     "AOLONLINE",
#     "APPMAIL8",
#     ...clipped...

Result Format

200 OK

json
[
  "OL2000",
  "OL2002",
  "OL2003",
  "OL2007",
  "OL2010",

  ...clipped...

  "NOTES9",
  "OFFICE365",
  "FFOFFICE365",
  "CHROMEOFFICE365",
  "ANDROIDGMAILAPP"
]

List supported email client configurations

GET https://instant-api.litmus.com/v1/clients/configurations

Returns a JSON hash detailing available options for each client.

Examples

sh
curl -X "GET" "https://instant-api.litmus.com/v1/clients/configurations"
ruby
> Litmus::Instant.client_configurations
# => {"OL2000"=>{"orientation_options"=>["vertical"], "images_options"=>["allowed"]},
#     "OL2002"=>{"orientation_options"=>["vertical"], "images_options"=>["allowed"]},
#     "OL2003"=>{"orientation_options"=>["vertical"], "images_options"=>["allowed", "blocked"]},
#     ... clipped ...

Result Format

200 OK

json
{
    "OL2000": {
        "orientation_options": [
            "vertical"
        ],
        "images_options": [
            "allowed"
        ],
        "name": "Outlook 2000",
        "group": "Desktop",
        "platform": "Windows 7",
        "status": "normal"
    },
    "OL2002": {
        "orientation_options": [
            "vertical"
        ],
        "images_options": [
            "allowed"
        ],
        "name": "Outlook 2002",
        "group": "Desktop",
        "platform": "Windows 7",
        "status": "normal"
    },
    "OL2003": {
        "orientation_options": [
            "vertical"
        ],
        "images_options": [
            "allowed",
            "blocked"
        ],
        "name": "Outlook 2003",
        "group": "Desktop",
        "platform": "Windows 7",
        "status": "normal"
    }

  ... clipped ...

}

Request a preview

GET https://instant-api.litmus.com/v1/emails/:email_guid/previews/:client

This triggers the capture of a preview. Once the capture is complete, the content of the JSON response body will contain URLs for each of the image sizes available. A second request will be needed to obtain actual image data.

WARNING

This method typically blocks for about 6 seconds when a new preview must be captured.

The URLs returned will be on subdomains of litmuscdn.com e.g. https://ol2015.capture.litmuscdn.com/87bf47f2-600e-40eb-8ccb-c9649f17644d/results/ol2015-vertical-allowed.png. GET requests to these URLs will return redirects to the current location of the image asset.

Subsequent requests for a capture that's previously been made will result in a redirect to the cached result of the previous capture. To trigger a new capture a new email_guid must be obtained. Only the initial capture is a billable event, not GETs of the cached preview.

Path parametersDescription
email_guidREQUIRED

string

Provided on email creation
clientREQUIRED

string

An identifier present in available clients
Query parametersDescription
imagesDefault allowed

string

One of allowedblocked. Refer to configurations to determine what's valid for for each client
orientationDefault vertical

string

One of vertical, horizontal. Refer to configurations to determine what's valid for for each client

Different configurations of the same client are considered as separate captures and billed as such. For instance the following would be considered three separate captures:

sh
$ curl -X "GET" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/IPAD?images=allowed&orientation=vertical"
$ curl -X "GET" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/IPAD?images=blocked&orientation=vertical"
$ curl -X "GET" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/IPAD?images=blocked&orientation=horizontal"
Errors
400 Bad Request
404 Not Found - when the email_guid is not found. This can occur when email assets or stored captures have expired having exceeded their lifetime
500 Internal Server Error - in particular when email clients fail unexpectedly
503 Service Unavailable
504 Timeout - this can occur when an email client takes too long to respond

Examples

sh
curl -X "GET" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2019" -v
ruby
Litmus::Instant.get_preview("7179b074-2b1e-455e-bf48-8068eb42d7ca", "OL2010", images: "blocked")
# => {"full_url"=>"https://ol2010.capture.litmuscdn.com/7179b074-2b1e-455e-bf48-8068eb42d7ca/results/ol2010-vertical-blocked-1366.png",
# "thumb_url"=>"https://ol2010.capture.litmuscdn.com/7179b074-2b1e-455e-bf48-8068eb42d7ca/results/ol2010-vertical-blocked-1366-thumb.png",
# "thumb450_url"=>"https://ol2010.capture.litmuscdn.com/7179b074-2b1e-455e-bf48-068eb42d7ca/results/ol2010-vertical-blocked-1366-thumb450.png"}

Result Format

200 OK

json
{
  "full_url": "https://OL2019.capture.litmuscdn.com/87bf47f2-600e-40eb-8ccb-c9649f17644d/results/ol2019-vertical-allowed-1366.png",
  "thumb_url": "https://OL2019.capture.litmuscdn.com/87bf47f2-600e-40eb-8ccb-c9649f17644d/results/ol2019-vertical-allowed-1366-thumb.png",
  "thumb450_url": "https://OL2019.capture.litmuscdn.com/87bf47f2-600e-40eb-8ccb-c9649f17644d/results/ol2019-vertical-allowed-1366-thumb450.png"
}

Directly request a preview image

GET https://instant-api.litmus.com/v1/emails/:email_guid/previews/:client/:capture_size

This method returns a redirect to the preview image or an (optional) redirect to a fallback image. In all other respects it behaves identically to requesting a preview above.

This makes requesting and displaying a capture in your user interface as simple as including any other remote image. For example, for a web application, you would place the constructed URL in the src attribute of an <img> tag (see example).

It can also be used as a convenience when downloading captures by simply configuring your HTTP client to follow redirects, cutting out the need to parse JSON and make a second request.

WARNING

This method typically blocks for about 6 seconds when a new preview must be captured.

Path parametersDescription
email_guidREQUIRED

string

Provided on email creation
clientREQUIRED

string

An identifier present in available clients
capture_sizeREQUIRED

string

One of full, thumb450, thumb
Query parametersDescription
imagesDefault allowed

string

One of allowedblocked. Refer to configurations to determine what's valid for for each client
orientationDefault vertical

string

One of vertical, horizontal. Refer to configurations to determine what's valid for for each client
fallbackDefault true

boolean

When fallback is enabled capture errors result in a redirect to a fallback image rather than in a failed response. An error is indicated by the presence of the custom header X-Litmus-Error. Errors relating to the request (i.e. 400 errors) are returned normally and do not result in the fallback redirect
fallback_urlDefaults to the following fallback images: fullthumb450thumb

string

A custom fallback image to display in case of errors. This must be an absolute URL, URL encoded and have a recognizable image extension. Query parameters are not supported. The image should be accessible publicly without the need for authentication
Errors
400 Bad Request
404 Not Found - when the email_guid is not found. This can occur when email assets or stored captures have expired having exceeded their lifetime
500 Internal Server Error - in particular when email clients fail unexpectedly
503 Service Unavailable
504 Timeout - this can occur when an email client takes too long to respond

WARNING

Some failure cases can take significantly longer to return than the typical 6 seconds for a successful case.

Examples

html
<img src="https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2019/full">
sh
curl -X "GET" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2019/full" -v
*   Trying 216.126.40.158...
* Connected to instant-api.litmus.com (216.126.40.158) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: instant-api.litmus.com
* Server certificate: RapidSSL SHA256 CA - G4
* Server certificate: GeoTrust Primary Certification Authority - G3
> GET /v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2019/full HTTP/1.1
> Host: instant-api.litmus.com
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx
< Date: Tue, 16 Feb 2016 09:53:39 GMT
< Content-Type: application/json;charset=utf-8
< Content-Length: 0
< Connection: keep-alive
< Location: https://OL2019.capture.litmuscdn.com/87bf47f2-600e-40eb-8ccb-c9649f17644d/results/ol2019-vertical-allowed-1366.png
< Strict-Transport-Security: max-age=3600; includeSubdomains; preload
< X-Frame-Options: DENY
< X-Content-Type-Options: nosniff
<
sh
# failure with default fallback behaviour

curl -X "GET" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2019/full" -v
*   Trying 216.126.40.158...
* Connected to instant-api.litmus.com (216.126.40.158) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: instant-api.litmus.com
* Server certificate: RapidSSL SHA256 CA - G4
* Server certificate: GeoTrust Primary Certification Authority - G3
> GET /v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2019/full HTTP/1.1
> Host: instant-api.litmus.com
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 302 Moved Temporarily
< Server: nginx
< Date: Tue, 16 Feb 2016 09:57:24 GMT
< Content-Type: application/json;charset=utf-8
< Content-Length: 0
< Connection: keep-alive
< X-Litmus-Error: 500 Server error
< Location: https://instant-api.litmuscdn.com/images/placeholder-full.png
< Strict-Transport-Security: max-age=3600; includeSubdomains; preload
< X-Frame-Options: DENY
< X-Content-Type-Options: nosniff
<
sh
# failure with fallback disabled

curl -X "GET" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2019/full?fallback=false" -v
*   Trying 216.126.40.158...
* Connected to instant-api.litmus.com (216.126.40.158) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: instant-api.litmus.com
* Server certificate: RapidSSL SHA256 CA - G4
* Server certificate: GeoTrust Primary Certification Authority - G3
> GET /v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/OL2019/full?fallback=false HTTP/1.1
> Host: instant-api.litmus.com
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Server: nginx
< Date: Tue, 16 Feb 2016 10:02:09 GMT
< Content-Type: application/json;charset=utf-8
< Content-Length: 496
< Connection: keep-alive
<
{
  "status": 500,
  "title": "Server error",
  "description": "An unknown error occurred. We know this is frustrating, but we ran into a problem and we don’t yet have a way to categorize and report it to you as this type of error hasn’t occurred before. This type of error is logged on our end, but if you see this while in development, please do reach out to us at resellers@litmus.com with details of your request and we’ll have a Support Engineer get back to you as soon as possible."
}
ruby
@preview_url = Litmus::Instant.preview_image_url(email_guid, "OL2010")
# => "https://OL2010.instant-api.litmus.com/v1/emails/755d1f9f-ad28-460f-8e45-632e0eceab32/previews/OL2010/full"
# Which could be used in a view template eg
# <%= image_tag @preview_url %>

Delete an email and its previews

DELETE https://instant-api.litmus.com/v1/emails

This method allows deleting a batch of emails and any previews associated with them.

The request is accepted if well formed, but the response itself provides no indication of the state of the emails before or after the request. An email may already have been deleted, or have never existed, and the request would still be Accepted.

Deletion is scheduled shortly after an accepted request (usually completing within seconds).

Confirmation of deletion requires attempted requests to the original resource URLs.

Body parametersDescription
email_guidsarray of strings

An array of up to 1,000 email_guids provided by the API at email creation time
Errors
400 Bad Request
401 Unauthorized

Examples

sh
curl -X "DELETE" "https://instant-api.litmus.com/v1/emails" \
  -H "Content-Type: application/json" \
  -u "$API_KEY:" \
  -d "{\"email_guids\":[\"3fefaeb4-8c99-4779-8594-8d441ab07a1e\"]}"

Result Format

202 Accepted

json
{
  "status": "Accepted",
  "email_guids": [
    "3fefaeb4-8c99-4779-8594-8d441ab07a1e"
  ]
}

Pre-request previews before download

POST https://instant-api.litmus.com/v1/emails/:email_guid/previews/prefetch

This method is provided as an optional performance enhancement, typically useful before embedding a set of previews within a browser, where connection limits might otherwise delay the start of capture of some previews. For more detail on when this might be useful see performance.

The method does not block while capture occurs, a 202 Accepted response is returned immediately.

Note that should capture failure occur for a preview, it will only be discovered when the preview is later requested. Request errors, for instance attempting to prefetch an invalid client, will result in a 400 Bad Request however.

Path parametersDescription
email_guidREQUIRED

string

Provided on email creation
Body parametersDescription
configurationsREQUIRED

array of objects

An array of capture configurations as JSON objects, see table below
Capture configurationDescription
clientREQUIRED

An identifier present in available clients
imagesoptional

One of allowed (default), blocked. Refer to configurations to determine what's valid for for each client
orientationoptional

One of vertical (default), horizontal. Refer to configurations to determine what's valid for for each client
Errors
400 Bad Request - if the request body is malformed, or if any requested capture configuration is invalid
404 Not Found - when the email_guid is not found. This can occur when email assets or stored captures have expired having exceeded their lifetime
JSON response body attributesDescription
configurationsConfirmation of capture configurations that will be prefetched

Examples

sh
curl -X "POST" "https://instant-api.litmus.com/v1/emails/87bf47f2-600e-40eb-8ccb-c9649f17644d/previews/prefetch"\
-H "Content-Type: application/json" -v\
-d '{"configurations":[
 {"client":"OL2010"},
 {"client":"OL2010", "images":"blocked"},
 {"client":"IPAD"}
 ]}'
ruby
Litmus::Instant.prefetch_previews(
  email_guid, [
    { client: "OL2010" },
    { client: "OL2013", images: "blocked" }
  ]
)
# => {"configurations"=>
#     [{"orientation"=>"vertical", "images"=>"allowed", "client"=>"OL2010"},
#      {"orientation"=>"vertical", "images"=>"blocked", "client"=>"OL2013"}]}

Result Format

202 Accepted

json
{
  "configurations": [
    {
      "orientation": "vertical",
      "images": "allowed",
      "client": "OL2010"
    },
    {
      "orientation": "vertical",
      "images": "blocked",
      "client": "OL2010"
    },
    {
      "orientation": "vertical",
      "images": "allowed",
      "client": "IPAD"
    }
  ]
}

Identifying End Users

INFO

In earlier API versions "End User Identifier" was referred to as "User GUID".

You may find it useful to partition your API usage data by your end users. If you are offering an unlimited previews facility to your users, we need to be able to identify the number of unique users of your application.

To do this, you can associate emails (and, as a consequence, any previews), with a unique identifier of your choosing—an end_user_id.

WARNING

The identifier used must be unique to that user. The identifier should be stored in a unique field within your database and should not change for the life of that user's account.

This information is never shared with anyone, not even your user. It will only be shown in your billing reports and confirmed in the response to a POST request that provides it.

Do not use a hash of your user's details unless you can ensure that this will remain unchanged and unique for that user. You'll want to refrain from hashing user details because, by doing so, a hash of their email address could change over time and cause them to be identified twice in one month.

Standard UUIDs make a good choice for this field, but any uniquely identifying string of 64 characters or less may be used.

sh
# An example of identifying an end user when POSTing a new email
$ curl -X "POST" "https://instant-api.litmus.com/v1/emails" \
       -H "Content-Type: application/json" \
       -u "$API_KEY:" \
       -d "{\"plain_text\":\"Hello World\",\"end_user_id\":\"a5725576-07d5-4e28-9e6c-2f1851825c14\"}" -v
> POST /v1/emails HTTP/1.1
> User-Agent: curl/7.37.1
> Host: instant-api.litmus.com
> Accept: */* > Content-Type: application/json
> Authorization: Basic XXXXXXXXXXXXXXXXXXXXXX
> Content-Length: 28
>
< HTTP/1.1 200 OK
< Server: nginx
< Date: Thu, 16 Jul 2015 12:35:02 GMT
< Content-Type: application/json;charset=utf-8
< Content-Length: 58
< Connection: keep-alive
< Strict-Transport-Security: max-age=3600;
< 
{ "email_guid": "ce6ba90f-cf28-4772-ab09-30a1d48a5e12""end_user_id": "a5725576-07d5-4e28-9e6c-2f1851825c14"}

Performance

Working with long running requests

To avoid complexity, the first request for a new preview blocks for a number of seconds until the capture has completed. However, this introduces some complications.

Captures are only initiated when a request for a preview has been made. If you make your requests in serial and wait for responses before proceeding, then they'll stack behind each other. This will multiply your overall load time.

Requesting multiple previews in parallel can be used to initiate capture for all desired configurations at once. In this case, your load time will be limited to the longest running query. Alternatively, you could choose to show those ready earlier as soon as they're available.

At scale, this could lead to a large number of open waiting connections if these requests are made server-side. We can also run into client-side connection limits in the browser.

Working with browser connection limits

Requesting a single preview or two in parallel

If you're only requesting a single preview or two in parallel, then you can skip this section on working with browser connection limitations. All common browsers allow this to occur unrestricted.

Requesting 3-6 images in parallel

You can safely ignore this unless you're concerned about the performance of your web application in legacy browsers where per-host connection limits will impact users.

However, if you're concerned about the following browsers, we have a solution:

  • IE6 or IE7 – Maximum connections per host is 2
  • Opera 9.x – Maximum connections per host is 4
  • Safari 3 and 4 – Maximum connections per host is 4

To remedy this, we allow access to the API assets using domain sharding.

Requesting 7-10 images in parallel

At 7 concurrent connections many browsers start to reach per host limits. As above, see domain sharding.

Requesting 10+ images in parallel

When we reach 10 concurrent connections we start to hit all-host connection limits, particularly in Chrome. Domain sharding doesn't stop our 11th request being queued, so it's best to pre-request any images required before embedding.

Domain sharding

We allow GET requests against the API at custom subdomains, which allows you to circumvent browser per-host connections limits at the small cost of additional DNS lookups.

For instance, if the following hit a per-host connection limit:

html
<img src="https://instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2000/thumb">
<img src="https://instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2002/thumb">
<img src="https://instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2003/thumb">
<img src="https://instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2007/thumb">
<img src="https://instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2010/thumb">
<img src="https://instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/NOTES9/thumb">

The limit could be circumvented with:

html
<img src="https://OL2000.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2000/thumb">
<img src="https://OL2002.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2002/thumb">
<img src="https://OL2003.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2003/thumb">
<img src="https://OL2007.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2007/thumb">
<img src="https://OL2010.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2010/thumb">
<img src="https://NOTES9.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/NOTES9/thumb">

Note that the choice of subdomain is arbitrary. You only need to ensure that they are distinct. You could equally use:

html
<img src="https://1.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2000/thumb">
<img src="https://2.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2002/thumb">
<img src="https://3.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2003/thumb">
<img src="https://4.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2007/thumb">
<img src="https://5.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/OL2010/thumb">
<img src="https://6.instant-api.litmus.com/emails/ce6ba90f-cf28-4772-ab09-30a1d48a5e12/previews/NOTES9/thumb">

Pre-request

Pre-requesting allows for requesting that a capture (or set of captures) is initiated for specified configurations with an immediate (non-blocking) response.

Because the API guards against duplicate captures, this means that any requests queued due to browser connection limits will yield the preview as soon as the pre-requested capture has completed, rather than initiating then waiting the full duration of capture.

See the API method for further information.

Managing server-side connections

Downloading large volumes of raw image data or holding large numbers of open connections server-side could place unwanted burden on your infrastructure.

The simple solution to alleviate these concerns is to ensure capture requests are only made in-browser or in-app. This will distribute the bulk of the network and bandwidth strain.

If your use case doesn't allow for this approach, the bandwidth requirements are difficult to avoid. However, the number of open connections can be reduced by employing a pre-request along with a delay before attempting download of the captured previews.