Skip to content
On this page

OAuth Integration Guide


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.

OAuth2 is a protocol that allows external applications to act on behalf of Litmus users without the user having to reveal their Litmus username, password or API key, instead the user grants permissions to an application.

Litmus currently supports the OAuth2.0 Web Application Flow (also known as "Authorization Code Grant" flow).

Worked example

A minimal example of a partner app is available which can be used to walk through the flow using your own Litmus account. The source for this is also provided.

Before you start

  1. Contact to request a new API application.
    You'll need to provide us:

    • application name
    • OAuth callback URI --- whitelist a URI within your application that will handle exchanging an authorization code for a token (must be HTTPS, multiple can be provided)
  2. In return we'll provide you:

    • client_id
    • client_secret (must be kept private)

The Web Application Flow

1. Redirect the user to request authorization to access Litmus

      state=xxxxxxxx&      # nonce (this should be a random unguessable string)

When logged in to Litmus, the user will be presented with your authorization request, eg


A user is only asked to authorize your application once. If you later repeat the flow (eg to get a new token after the last had expired) we skip to the next step, so later token requests should generally be invisible to your user. Because the Litmus session could end it's generally preferable to first try using a refresh token for this purpose.

2. Litmus redirects the user back to your application with a temporary code

Assuming the user authorizes your request, Litmus will send a temporary code to your redirect uri (along with relaying the state param which you provided, which should be checked to avoid cross site request forgery):


If the user does not approve the request you'll instead receive an error:


Because the request is made from the context of the end user's browser, their existing session with your web application should be used to tie this request back to them.

3. Exchange the code for an access token

Your application server should POST using its client_secret and the code to obtain a token:


JSON POST body parameters:


The client ID you received from Litmus

The client secret you received from Litmus

The code you received in the previous step
redirect_uriThis must match redirect_uri provided in step 1, it should be omitted if this was not provided there

This must be authorization_code

JSON response body

  "access_token": "XYZ",
  "expires_in": 7200,     // The remaining lifetime of the token in seconds
  "token_type": "Bearer"  // The token type, currently always Bearer

  // More fields may be provided

Like your client_secret the token should be stored securely.

4. Call Litmus API methods passing the token

Make authenticated calls to our APIs from your application server using the HTTP Authorization header:

$ curl -X "POST" ""\
       -H "Content-Type: application/json"\
       -H "Authorization: Bearer a66841f0a212c0afb6344c6377df4dde0389922511540d9e3c1d11e2ab811a2e"\
       -d "{\"plain_text\":\"Hello World\"}" -v

> POST /v1/emails HTTP/1.1
> Host:
> 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"


Currently only one scope, full ("Use all Litmus features on your behalf") is currently provided (this is also the default when none is specified).

Token expiration and refresh

Token expiry should be anticipated (the default token time-to-live is 2hrs, but this may change).

Refresh tokens are supported and are the recommended approach to obtaining a new bearer token. Restarting the flow above will also issue a fresh token where the current litmus user has authorized your application already.

Token revocation

Token revocation should also be anticipated and handled gracefully by restarting the flow.


A list of battle tested client libraries for simplifying integration can be found on the OAuth project site.

For integrating with ruby applications we also provide an omniauth-litmus strategy.

Request user identity data


Retrieve the name and unique identifier of the Litmus user associated with the current authorization credentials.


curl -X "GET" ""\
     -H "Authorization: Bearer $TOKEN"

Result Format

200 OK

  "user": {
    "id": 123456,
    "full_name": "John Doe",
    "first_name": "John",
    "last_name": "Doe"

List a user's default email clients


Obtain a list of a user's default clients configured via

If a user has never configured default clients, this defaults to a set of popular clients.


curl -X "GET" ""\
     -H "Authorization: Bearer $TOKEN"

Result Format

200 OK

  "clients": [

Request a user-specific client configuration URL


This is useful when you wish to link out to Litmus to allow your users to alter their default Litmus testing client set (which can be retrieved with the /v2/user_settings/clients endpoint above).

If you simply link the user associated with the OAuth token may not match the user for the current Litmus session (as they may have switched subaccounts at some point, or they may have logged in with an entirely different account).

This endpoint allows you to retrieve a client settings URL which when followed will ensure the user is prompted to switch to a Litmus account that matches the OAuth token used to make the API request.

Generated URL Lifetime

Each generated URL has a valid lifetime of at least 1 day. It can be used multiple times before expiry.


curl -X "GET" ""\
     -H "Authorization: Bearer $TOKEN"

Result Format

200 OK

  "configuration_url": ""