The availability of features may depend on your plan type. Contact your Customer Success Manager if you have any questions.

Dev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideLegal TermsProduct feedbackGitHubNuGetDev CommunitySubmit a ticketLog In

API Conventions

This topic describes conventions used for Optimizely's REST API.


There are two methods of authenticating with Optimizely Web Experimentation API: using OAuth 2.0 and generating a personal token. Anyone building an application that is customer-facing should use OAuth 2.0. If you are building on the 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.

curl -H "Authorization: Bearer abcdefg123456" \

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 see our OAuth 2.0 guide.

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

Get OAuth 2.0 access token with easy-access:

easy_access optimizely

Personal Tokens

Personal Tokens are an easy way to authenticate with the Optimizely Web Experimentation API . If you are an Administrator in your account, you can generate a token for yourself that will not 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.

Classic Tokens (deprecated)

Optimizely Web Experimentation version 1 API used a token system where an Administrator could generate tokens on behalf of anyone in an account. This authentication mechanism is no longer available for the Optimizely Web Experimentation API and has been replaced by Personal Tokens (see the previous section).


Optimizely Web Experimentation 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 API (2.0) includes a JSON body in the response with the property UUID. If you contact Optimizely with a question regarding a failing request, be sure to mention the UUID of the error.

{} 4xx Error

Parameter and TypeDescription
A message with more information about the error that occurred.
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 uuidvalue.
A unique identifier for the category of the error. This is sometimes the HTTP status code.

HTTP status code summary

ResponseWhat to expect
200 - OKYour request was correctly formatted and the resource you requested is returned
201 - CreatedReturned when a POST request was successful
202 - AcceptedReturned when a PUT request was successful
204 - No ContentReturned when your DELETE request was successful
400 - BadRequestCan happen if your request did not have a valid JSON body. It might help to specify a Content-Type: application/json header in your request. If you sent valid JSON, the error may also reference specific fields that were invalid
401 - UnauthorizedYour API token was missing or not in the correct format
403 - ForbiddenYou provided an API token but it was invalid or revoked or you don't have read/write access to the entity you're trying to view/edit
404 - Not FoundThe id used in the request was inaccurate or you didn't have permission to view/edit it
409 - ConflictThe resources you are trying to reach is in conflict
413 - Payload Too LargeThe data that you want to send to Optimizely is too large
429 - Too Many RequestsYou went over your rate limit. Wait until the X-RATELIMIT-RESET header reaches 0 and X-RATELIMIT-REMAINING is reset to X-RATELIMIT-LIMIT. See the rate limiting section for more info
5xx - Server ErrorSomething went horribly wrong! Optimizely engineers have been informed, but please don't hesitate to contact us.

Example error response body

  "message": "Authentication failed",
  "code": "403",
  "uuid": "1f910547-5587-42ff-9e53-76c71d582983"


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.

Example request

curl -H \
  "Authorization: Bearer abcdefg123456" \
  "" --verbose

Link Header

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.

nextThe link relation for the immediate next page of results
lastThe link relation for the last page of results
prevThe link relation for the immediate previous page of results

Link header example

LINK: <>; rel=next, <>; rel=last

Rate limiting

Optimizely Web Experimentation API has a Global rate limit and some endpoints have an 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.

Currently, Optimizely Web Experimentation only has a rate limit for the e3-auth-service API endpoint, which is 100 requests per hour.

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:

X-RATELIMIT-LIMITThe limit for this endpoint
X-RATELIMIT-REMAININGThe amount of calls remaining for this endpoint
X-RATELIMIT-RESETThe X-RateLimit-Reset header provides a Unix UTC timestamp, letting you know the exact time that your fresh new rate limit kicks in.
Status: 200 OK
X-RATELIMIT-RESET: 1477716420.0


When we make backward-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 Web is around.

VersionWorks with
v1 Optimizely Classic Web
Optimizely DCP (Dynamic Customer Profiles)
v2 Optimizely Classic Web (READ-ONLY)
Optimizely Web Experimentation
Soon: Optimizely Feature Experimentation
Soon: Optimizely Mobile
Soon: Optimizely 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 backward-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 backward-incompatible changes as possible.

Optimizely Classic Web objects

Optimizely Web Experimentation REST API is designed for Optimizely Web Experimentation which shares some of the data models with Optimizely Classic Web. Other data models are replaced by a similar concept.

When you request a Classic Web object through Optimizely Web Experimentation REST API, we will try to map the Classic Web fields as close as possible to Optimizely Web Experimentation fields. Because Optimizely Web Experimentation introduces many new concepts, it is not possible to write to Optimizely Classic Web objects with the Optimizely Web Experimentation REST API.

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

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

If you are migrating from Optimizely Classic Web to Optimizely Web Experimentation 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 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

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

Read more about Swagger and Open API on the OpenAPI website.

Location of swagger.json

Example use of the JavaScript client

var token = 'abcdefg123456';
var swaggerPromise = new SwaggerClient({
  url: "",
  usePromise: true

var authentication = {
  clientAuthorizations: {
    token: new SwaggerClient.ApiKeyAuthorization('Authorization', "Bearer " + token, 'header'),
swaggerPromise.then(function(client) {
  return client.Projects.list_projects({
    responseContentType: 'application/json'
  }, authentication);
}).then(function(result) {

Required fields

Some of the fields are not marked as required but have a conditional requirement. There are situations where if field A is set, field B needs to be set as well. Another example is that Experiments within a Optimizely Web Experimentation Project require the actions to be set on Variations within the Experiment. Experiments in a Optimizely Feature Experimentation 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.