The Optimizely v2 REST API has been implemented with the intention to make the lives of developers easy. Below is a list of all the important API conventions that apply to our entire API.


There are two methods of authenticating with the v2 API: using OAuth 2.0 and by generating a personal token. Anyone building an application that will be customer facing should use OAuth 2.0. If you are building on our API for an internal tool or you just want to explore what is possible it is easier to use a Personal Token. Personal Tokens are for server-to-server communication only and should NOT be shared with anyone else under any circumstances.

OAuth 2.0

OAuth 2.0 provides a friendly interface for the users of your app to allow your tool to make API requests on their behalf.

If you want to set up OAuth 2.0 authentication for your app, please visit our OAuth 2.0 step-by-step guide on https://developers.optimizely.com/x/authentication/oauth/.

You can use easy-access to easily get an access token.

Personal Tokens

Personal Tokens are an easy way to authenticate with the Optimizely API. If you are an Admin in your account, you can generate a token for yourself that won't expire until you revoke the token. Personal Tokens can be used with the same headers as OAuth 2.0 access tokens.

Personal Tokens are for server-to-server communication only and should NOT be shared with anyone else under any circumstances.

Read here how you can generate and use a Personal Token: https://developers.optimizely.com/x/authentication/personal-token/.

Classic Tokens (deprecated)

The v1 API used a token system where an Admin could generate tokens on behalf of anyone in an account. The tokens were generated on https://app.optimizely.com/tokens. This authentication mechanism is no longer available for the v2 API and has been replaced by Personal Tokens (see previous section).


Optimizely uses conventional HTTP response codes to indicate the success or failure of an API request. In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, a change failed, etc.), and codes in the 5xx range indicate an error with Optimizely's servers.

When a 4xx or 5xx status code is returned, Optimizely includes a JSON body in the response with a property uuid. If you contact Optimizely with a question regarding a failing request, be sure to mention the uuid of the error.

{} 4xx Error

Type: string

A message with more information about the error that occurred.

Type: string

A unique identifier for the error that you experienced. All relevant information regarding your error is stored in Optimizely's systems and can be found with this unique identifier. When you contact Optimizely about your error, be sure to mention the uuid value.

Type: string

A unique identifier for the category of the error. This is sometimes the HTTP status code./p>


List requests will be paginated to 25 items by default. It is possible to adjust the amount of returned objects by using the ?per_page parameter. The maximum value for ?per_page is 100. By using the ?page parameter you can access all the pages.

The ?page value will default to 1.

Every response to a list request has LINK headers to relevant other pages.

This LINK response header contains one or more Hypermedia link relations, some of which may require expansion as URI templates. If there are less than per_page objects at that endpoint and they are on page 1, there will be no Link header in the response because there are no relevant links to be returned.

Header Value
next The link relation for the immediate next page of results
last The link relation for the last page of results
prev The link relation for the immediate previous page of results

Rate limiting

Rate Limit enforcement has been temporarily disabled.

Current Rate Limits:

REST API Endpoint Rate Limit (per minute)
/v1/experiments/{experiment_id}/results 20
/v1/experiments/{experiment_id}/stats 20
/v2/campaigns/{campaign_id}/results 20
/v2/experiments/{experiment_id}/results 20
All other /v2 endpoints 100

The Optimizely API has a Global rate limit and some endpoints have a endpoint specific rate limit. The global rate limit is a limit for the total amount of calls you are making to our API, regardless of which endpoint. An endpoint-specific rate limit is always less than the global rate limit.

When you have reached your limit, you will get a 429 - Too Many Requests response code.

Every response contains three headers that indicate where you are against your rate limit:

Header Value
X-RATELIMIT-LIMIT The limit for this endpoint
X-RATELIMIT-REMAINING The amount of calls remaining for this endpoint
X-RATELIMIT-RESET The X-RateLimit-Reset header provides a Unix UTC timestamp, letting you know the exact time that your fresh new rate limit kicks in.


When we make backwards-incompatible changes to the API, we release a new major version of the API. The latest major version is v2.

At the moment of writing (October 29 2016) there are two major versions: v1 and v2.

The most important difference between v1 and v2 is how they interact with our various products.

The v1 API will keep working as long as Optimizely Classic is around.

Version Works with
  • Optimizely Classic Web
  • Optimizely DCP (Dynamic Customer Profiles)
  • Optimizely Classic Web (READ-ONLY)
  • Optimizely X Web
  • Soon: Optimizely X Full Stack
  • Soon: Optimizely X Mobile
  • Soon: Optimizely X OTT
  • Soon: Optimizely DCP


The main difference between backward compatible and backward incompatible changes is that backward compatible changes only enhance functionality and don't change the behavior of existing fields on all endpoints. This guarantees that your app is not impacted by changes done by us.

Changes that we do consider backwards-compatible are:

  • Adding new API resources.
  • Adding new optional request parameters to existing API methods.
  • Adding new properties to existing API responses.
  • Changing the order of properties in existing API responses.
  • Changing the length or format of object IDs or other opaque strings.

We aim to make as few backwards-incompatible changes as possible.

Optimizely Classic objects

The v2 API is designed for Optimizely X. Optimizely X shares some of the data models with Optimizely Classic. Other data models are replaced by a similar concept.

When you request a Classic object through the v2 API, we will try to map the Classic fields as close as possible to Optimizely X fields. Because Optimizely X introduces a lot of new concepts, it is not possible to write to Optimizely Classic objects with the v2 API.

Our goal is to give anyone access to their Optimizely Classic data through the v2 API. If a field for an old object is missing, please let us know by submitting a ticket to the developer support team.

When you request experiment results for a Classic experiment, you will get a redirect (302) to the v1 API result endpoint.

If you are migrating from Optimizely Classic to Optimizely X it will be helpful to check the migration section.

OpenAPI / Swagger

We have used the OpenAPI specification to define all our REST endpoints. By doing so, we made sure our REST API reference is always up to date and that API clients in any language can easily be generated.

By using the https://api.optimizely.com/v2/swagger.json file in a client, the client knows what actions are possible with the Optimizely API.

To generate a client in a specific language, go to http://generator.swagger.io/.

Some popular clients are the Node/JavaScript client swagger-js and the Python client Bravado.

Read more about Swagger and the OpenAPI here: http://swagger.io/.

Required fields

Some of the fields are not marked as required but have a conditional requirement. There are situation where if field A is set, field B needs to be set as well. Another example is that Experiments within a Web Project require the actions to be set on Variations within the Experiment. Experiments in a Full Stack project don't have this requirement. If you try to create an object without a field that is required, Optimizely will respond with an error that indicates which field is missing.