Guides
Submit Documentation FeedbackJoin Developer CommunityLog In

Using the Authentication API

The simplest and fastest way to get access to Enriched Events Export is by using our Authentication API, where you can exchange an Optimizely-issued token for temporary AWS credentials. These credentials can then be used to access the Enriched Events S3 buckets associated with your account, where you can programmatically download your data.

Authentication API Endpoint

https://api.optimizely.com/v2/export/credentials

Query Parameters

Parameter

Description

duration

This is the expiration window for your credentials. The default and maximum value is 1 hour. You may select anything between 15 minutes and 1 hour for this parameter, using [H,h] for hours or [M,m] for minutes.

https://api.optimizely.com/v2/export/credentials?duration=1h

Refresh these credentials as often as needed, using your original Personal Access Token.

REST API Reference here.

Acquiring temporary AWS credentials with the Authentication API

Step 1: Generate a Personal Access Token.

Generate a Personal Access Token (PAT) within the Optimizely application, by following these instructions.

Step 2: Make a request to the Authentication API, using your PAT.

Copy your Personal Access Token into an Authorization header of a GET request to the Authentication API:

Sample cURL request

curl -H "Authorization: Bearer {PAT}" -X GET https://api.optimizely.com/v2/export/credentials\?duration\=1h

Sample response

{
 "credentials": {
   "accessKeyId": "access_key_id",
   "secretAccessKey": "access_secret_key",
   "sessionToken": "session_token",
   "expiration": 1591026407394
 },
 "s3Path": "s3://optimizely-events-data/v1/account_id=123"
}

The response contains an accessKeyId, a secretAccessKey, and a sessionToken, which you will use in the next step to validate your credentials.

📘

Note

If you already have credentials for the other data export services, you can skip this step. You can reuse the same credentials to access your Enriched Events Export data, though those credentials will be less secure than the ones issued using the above method.

Step 3: Validate your credentials.

Verify you can access Enriched Events Export data using your credentials:

  1. Install AWS command line tools.

  2. Export your access key, secret access key, and session token as environment variables:

    export AWS_ACCESS_KEY_ID={access_key_id}
    export AWS_SECRET_ACCESS_KEY={access_secret_key}
    export AWS_SESSION_TOKEN={session_token}

  3. Copy your Optimizely account ID (can be found under account settings)

  4. List the files in your S3 decisions directory, using your account id and a given date:

    aws s3 ls s3://optimizely-events-data/v1/account_id=<account id>/type=decisions/date=<YYYY-MM-DD>/

    • You should see a list of all experiments for which users received decisions that day. Note that the final forward-slash is necessary because your credentials will only provide access to one folder inside the Optimizely Amazon S3 bucket.
  5. Since your Data Export data is encrypted, inspect and access the data with one of the following clients:

    • AWS CLI version 1.11.108 and later
    • AWS SDKs released after May 2016

Step 4: Start pulling down your data!

When setting up access to your Enriched Events data programmatically, you’ll need the accessKeyID, secretAccessKey, and sessionToken values from the Authentication API to be able to copy files from Optimizely’s S3 buckets over to your own. These credentials expire every hour, so you'll also need to set up a process for refreshing them. AWS documentation is provided here.

Sample code for a boto3 S3 client that uses the Authentication API, and refreshes credentials once an hour:

#!/usr/bin/env python3

from botocore.credentials import RefreshableCredentials
from botocore.session import get_session
from datetime import datetime
import requests as r
import boto3
import pytz
import sys


class BearerAuth(r.auth.AuthBase):
    """
    Bearer authentication class that integrates with requests'
    native authentication mechanism.
    """

    def __init__(self, token):
        """
        Args:
            token (str): Bearer token used to authenticate requests to an API
        """
        self.token = token

    def __call__(self, request):
        """Sets the Authorization header on the current HTTP request.
        Args:
            request (request): The current HTTP request object.
        Returns:
            request: The current HTTP request with additional
                     Authorization header
        """
        request.headers['Authorization'] = f"Bearer {self.token}"
        return request


class OptimizelyS3Client(object):
    """
    AWS S3 client using credentials from Optimizely
    """

    EXPORT_CREDENTIALS_URL = 'https://api.optimizely.com/v2/export/credentials'
    CREDENTIALS_IDENTIFIER = 'Optimizely'
    EVENT_EXPORT_BUCKET_REGION = 'us-east-1'

    def __init__(self, token: str):
        """
        Args:
            token (str): Optimizely personal access token
        """
        self.token = token

    def get_bucket_prefix(self, account_id: str) -> str:
        """Get the bucket prefix for a given Optimizely account ID
        Args:
            account_id (str): Optimizely account ID
        Returns:
            str: The S3 bucket prefix to access events data
        """
        return f"v1/account_id={account_id}/"

    def get_creds(self) -> dict:
        """Get AWS credentials from the Optimizely public API
        Returns:
            dict: The AWS credentials for a given Optimizely account
        """
        response = r.get(
            OptimizelyS3Client.EXPORT_CREDENTIALS_URL,
            auth=BearerAuth(self.token)
        )

        node = response.json()
        return node['credentials']

    def as_boto3_s3_client(self):
        """
        Convert the Optimizely S3 client to a standard boto s3
        client with refreshable credentials
        Returns:
            botocore.client.S3: Standard boto3 S3 client
        """
        creds = self.get_creds()

        # The API response is in milliseconds
        expiry_time = int(creds['expiration'] / 1000)

        # boto expects the expiry time to be a UTC datetime
        expiry_time = datetime.fromtimestamp(expiry_time, pytz.utc)

        opz_refreshable_credentials = RefreshableCredentials(
            creds['accessKeyId'],
            creds['secretAccessKey'],
            creds['sessionToken'],
            expiry_time,
            self.get_creds,
            OptimizelyS3Client.CREDENTIALS_IDENTIFIER
        )

        session = get_session()
        session._credentials = opz_refreshable_credentials
        session.set_config_variable('region', OptimizelyS3Client.EVENT_EXPORT_BUCKET_REGION)
        opz_session = boto3.Session(botocore_session=session)
        s3_client = opz_session.client('s3')

        return s3_client


def main():
    EVENT_EXPORT_BUCKET_NAME = 'optimizely-events-data'
    OPTIMIZELY_ACCOUNT_ID = '8506653257'
    OPTIMIZELY_PERSONAL_ACCESS_TOKEN = '2:4gLnqLABma8j2B4hyJ1ssvRJNvDR_YX1LfNjwS742PNKgOs0GNcU'

    optimizely_s3_client = OptimizelyS3Client(OPTIMIZELY_PERSONAL_ACCESS_TOKEN)
    s3_client = optimizely_s3_client.as_boto3_s3_client()

    all_objects = s3_client.list_objects(
        Bucket=EVENT_EXPORT_BUCKET_NAME,
        Prefix=optimizely_s3_client.get_bucket_prefix(OPTIMIZELY_ACCOUNT_ID)
    )
    print(all_objects)


if __name__ == '__main__':
    main()