Area: Optimizely Add-ons
Applies to versions: 2 and higher

Using Forms Service API

Recommended reading 

The Optimizely Forms Service API integration with the Optimizely Service API provides a RESTful API for accessing form data, submission and metadata. The Optimizely Forms Service API depends on the Optimizely Service API and helps a developer access form data like submission and metadata.

Note: Optimizely Forms is only supported by MVC-based websites and HTML5-compliant browsers.

How it works

The Forms.ServiceAPI has the following attributes:

  • Exposes RESTful API for reading data of a form.
    • If you specify neededLanguage, only expose data where SYSTEMCOLUMN-language="neededLanguage"; you do not need to show the SYSTEMCOLUMN-language column.
    • If you do not specify neededLanguage, show data for all languages, and also show SYSTEMCOLUMN-language.
  • Supports CSV, XML, XLSX, and JSON formats.
  • Supports pagination.
  • Compatible with OData.
    • $filter defined by OData can be used to filter on SYSTEMCOLUMN_SubmitUser and SYSTEMCOLUMN_FinalizedSubmission. For example: http://localhost:56908/EPiServer.Forms.ServiceApi/GetFormData(Id=114,Language=null)?$filter=SYSTEMCOLUMN_SubmitUser eq 'admin'.
      The SYSTEMCOLUMN_SubmitTime is not compatible with OData serializing. You should use $filter without SYSTEMCOLUMN_SubmitTime and filter the data by code.

  • For implementation, writes the extension on top of the ServiceAPI to use its OAuth2 handling.

Note: If you enable Allow Exposing Data Feeds in a form container, allowed credentials can fetch data with the ServiceAPI.

Working with the API

EPiServer.Forms.ServiceApi is based on EPiServer.ServiceApi.

  1. Install the EPiServer.Forms.ServiceApi NuGet package with Visual Studio and rebuild the solution.
  2. Update the EPiServer.ServiceApi to latest version by running the following command in the Package Manager Console.
    update-package EPiServer.ServiceApi
  3. Correct the assembly binding in your web.config as shown in the following code.
      <assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
      <bindingRedirect oldVersion="" newVersion="" />
      <assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
      <bindingRedirect oldVersion="" newVersion="" />
      <assemblyIdentity name="System.Web.Http.WebHost" publicKeyToken="31bf3856ad364e35" culture="neutral" />
      <bindingRedirect oldVersion="" newVersion="" />
  4. Bind HTTPS for your site.

    EPiServer.Forms.ServiceApi depends on EPiServer.ServiceApi, which requires using https for consuming APIs, so you need go to IIS and bind https for your website.

  5. Verify that EPiServer.Forms.ServiceApi is working.

    Before you can use the ServiceApi, access https://YourSite/episerverapi/token from a browser. If it returns unsupported_grant_type, then it is working. If it does not return anything, delete ASP.NET temporary files in the folder: C:/windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files. Correct it to fit your environment, then try again.

  6. Grant permission for the Config user to use ServiceApi.
    1. Go to the admin view > Config > Security > Permissions for Functions.
    2. Add the user or group to the EPiServerServiceApi Read Access right. This user is for authenticating when you consume the ServiceApi.

  7. Implement OAuth2 client to access the service.
    using Newtonsoft.Json.Linq;
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text;
    using System.Threading.Tasks;
    namespace EPiServer.Forms.ServiceApi.Test
       public class OAuth2Client
           private string _baseUrl, _username, _password, _accessTokenUri;
           public OAuth2Client(string baseUrl, string username, string password, string accessTokenUri)
               _baseUrl = baseUrl;
               _username = username;
               _password = password;
               _accessTokenUri = accessTokenUri;
           public string GetData(string uri, string accessToken)
               using (var client = new HttpClient())
                   client.BaseAddress = new Uri(_baseUrl);
                   client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                   var response = client.GetAsync(uri).Result;
                   if (response.StatusCode == HttpStatusCode.OK)
                       var content = response.Content.ReadAsStringAsync().Result;
                       return content;
               return string.Empty;
           public string GetAccessToken()
               var token = string.Empty;
               using (var client = new HttpClient())
                   client.BaseAddress = new Uri(_baseUrl);
                   var fields = new Dictionary<string, string>
                       { "grant_type", "password" },
                       { "username", _username },
                       { "password", _password }
                   var response = client.PostAsync(_accessTokenUri, new FormUrlEncodedContent(fields)).Result;
                   if (response.StatusCode == HttpStatusCode.OK)
                       var content = response.Content.ReadAsStringAsync().Result;
                       token = (string)JObject.Parse(content).GetValue("access_token");
               return token;

    You can use the OAuth2Client class to access the service to get data. The service exposes three methods:

    • GetFormsInfo. Gets forms in the system. Accept language as parameter; if the language parameter is null, it returns form information in the master language. The requesting user must have read-access with the form to get data.
    • GetFormData. Fetches posted data of a specified form. You need to specify form id and language as parameters; language can be null, which returns data from all languages.
    • GetFieldMapping. Gets mappings between field name and their friendly name. You need to specify form id and form language.
    • DeleteFormData. [New in Forms Service API 3.1.0] Deletes posted data of a specified form. You need to specify form Id and SubmissionIds as parameters.
      To invoke DeleteFormData action, use a POST request and JSON data format for the parameters in the request body. Example:

    The service is compatible with OData 4.0. The following example shows how to use these methods.

    private const string AccessTokenURI = "/episerverapi/token";
    private const string FormDataURI = "/EPiServer.Forms.ServiceApi/GetFormData(Id={0},Language=null)?$top=10";
    private const string FormMappingURI = "/EPiServer.Forms.ServiceApi/GetFieldMapping(Id={0},Language=null)";
    private const string FormsInfoURI = "/EPiServer.Forms.ServiceApi/GetFormsInfo(Language=null)";
    private const string FormsDeleteURI = "/EPiServer.Forms.ServiceApi/DeleteFormData";
    private static readonly string Username = ConfigurationManager.AppSettings["username"]; // user who added to access ServiceApi on step 3
    private static readonly string Password = ConfigurationManager.AppSettings["password"]; // the user’s passowrd
    private static readonly string SiteUrl = ConfigurationManager.AppSettings["siteUrl"]; // ex: https://vnwks30:17005/
    protected void FetchData_Click(object sender, EventArgs e)
        if (string.IsNullOrEmpty(FormId.Text))
        // for request to https site
        System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
        var oAuthClient = new OAuth2Client(SiteUrl, Username, Password, AccessTokenURI);
        var accessToken = oAuthClient.GetAccessToken();
        var formsInfo = oAuthClient.GetData(FormsInfoURI, accessToken);
        var mappings = oAuthClient.GetData(string.Format(FormMappingURI, FormId.Text), accessToken);
        var data = oAuthClient.GetData(string.Format(FormDataURI, FormId.Text), accessToken);
        // get the first record return from above function and delete it
        if (data != null) 
            var dataObj = JObject.Parse(data);
            var firstId = dataObj["value"].First["Id"];
            var recordIds = new List<string> { firstId.ToString() };
            var deleteFirstRecord = oAuthClient.DeleteData(FormsDeleteURI, accessToken, int.Parse(FormId.Text), recordIds);
          // delete all records
          //var dataObj = JObject.Parse(data);
          //var recordIds = new List<string>();
          //foreach (var obj in dataObj["value"])
          //    recordIds.Add(obj["Id"].ToString());
          //var deleteAllRecord = oAuthClient.DeleteData(FormsDeleteURI, accessToken, int.Parse(FormId.Text), recordIds);
Do you find this information helpful? Please log in to provide feedback.

Last updated: Sep 16, 2019

Recommended reading