Skip to content

OAuth Web Application 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.

The Web Application Flow

1. Redirect the user to request authorization to access Litmus

GET https://litmus.com/oauth/authorize?
      response_type=code&
      client_id=XYZ&
      redirect_uri=https://yourapp.com/oauth/litmus/callback&
      state=xxxxxxxx&      # nonce (this should be a random unguessable string)
      scope=full

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

INFO

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):

GET https://yourapp.com/oauth/litmus/callback?code=ABCD...&state=xxxxxxxx

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

GET https://yourapp.com/oauth/litmus/callback?error=access_denied

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:

POST https://litmus.com/oauth/token

JSON POST body parameters:

FieldDescription
client_idREQUIRED

The client ID you received from Litmus
client_secretREQUIRED

The client secret you received from Litmus
codeREQUIRED

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
grant_typeREQUIRED

This must be authorization_code

JSON response body

json
{
  "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:

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"
}

Scopes

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.

Request user identity data

GET https://api.litmus.com/v2/users/current

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

Examples

sh
curl -X "GET" "https://api.litmus.com/v2/users/current"\
     -H "Authorization: Bearer $TOKEN"

Result Format

200 OK

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

List a user's default email clients

GET https://api.litmus.com/v2/user_settings/clients

Obtain a list of a user's default clients configured via https://litmus.com/settings/clients.

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

Examples

sh
curl -X "GET" "https://api.litmus.com/v2/user_settings/clients"\
     -H "Authorization: Bearer $TOKEN"

Result Format

200 OK

json
{
  "clients": [
    {"code":"APPMAIL5"},
    {"code":"APPMAIL6"}
  ]
}

Request a user-specific client configuration URL

GET https://api.litmus.com/v2/user_settings/clients/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 https://litmus.com/settings/clients 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.

Examples

sh
curl -X "GET" "https://api.litmus.com/v2/user_settings/clients/configuration_url"\
     -H "Authorization: Bearer $TOKEN"

Result Format

200 OK

json
{
  "configuration_url": "https://litmus.com/ensured_user/eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkExMjhHQ00iLCJhbGdvIjoiUlNBLU9BRVAifQ.dgGgBTD-ZgcMFZ2Fg_ywYOiWDUe6wZU7WJdUzkVSJ29K3nYj13NdrSQAOC67op8HZkACMWTTsx_K5iwDgkINRlnmatzb2q7_OKc6OHiFMVoTudSLxzLUdu-RKkkjdEKr54F03xju6jiewWPVBmX2Cf1bNSIE9VHgaKI5nZay6xHmO2Fe-sDzNvZqfF9Yp4vQEj6AtD0DlLTW4pNGUb7f2JgX3cJzchbb6d5TSzgtiCgO6c76tdzd5BMm6h2RdncfAsztGf4xJoAdaYsMF_Z_ruMijiEHOXIdYydxwKyewvE6VNRD3REXgk1ADOCX0nqHGyxjgu8s7UbBLtHK-Vg9Pw.zXJ6JAni_sovilZp.x07WQ2K-6GvSMITa7H-j5Wsc9M2fiH1FhOhZhP7jWeAcII_EWtpQy6p37_6o55kwrDHtBvo5qVL69zdLEDwHw0ckujOPZK2PFFD0kmRlt_nni-_XxtVuVbEhipqcuAGC9PPmMlsh7u2KEET9tXdx3ozKo9-pAh233P73iB-aBxWUupfqVvSoeh9E08jZ2QPp0rXx8pOwKiV6pbhK9CRAjOn6HHyYEGPoFesnMECRbUvrkgoPly17QuxjxO50cFx3VX3wFcw7BNt-LZEQUsIbzqhnQlK9b00QeVoyJn1EvLQLFdM6N2aflZ2vFHDIGiDRUWBvvA98xR4nXmzOCNXZTehGKT_v9VT0nCOw3NQRfxFleoGG0Y_wZ5r_tD5YSsux1X6-vchuQxo7l7I3cLV5NTnW63twDpfHXj9ce25bOc2QjoZ7a6ulwxMwzVA7McsVLcVOis6Ut79ST-RbAUfoNuI6717MYchqduI2_hcruQDxLP53tgyyUd_LAUT8nHWGeo7CA4JT57TazIb6hXII0P7veQbfqyq1-JWI-_DfJYyJunHB2NPJSO3mP3Ny68jDkcikwQmT-r2NqD4hZ7QnAUZKAJ8td1oDETrdU-BZBw.DfIvjD1NLlADracTQMXi-A"
}