HomeDev GuideAPI Reference
Dev GuideAPI ReferenceUser GuideGitHubNuGetDev CommunitySubmit a ticketLog In
GitHubNuGetDev CommunitySubmit a ticket

Forms Service API

The Optimizely Forms Service API depends on the Optimizely Service API and helps a developer access form data like submission and metadata.



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

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.
    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.



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


Work 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. Update appsetting.json to config ClientId and ClientSecret

    "EPiServer": {
            "ServiceApi": {
                "RequireSsl": true,
                "ClientId": "cli",
                "ClientSecret": "cli"
  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//EPiServer.Forms.ServiceApi from a browser. If it returns JSON like this:

    ...then it is working. If it does not return anything, re-install nuget 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.
  1. Implement OAuth2 client to access the service.
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;

namespace EPiServer.Forms.ServiceApi.WebTest {
  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 DeleteData(string uri, string accessToken, int formsId, IEnumerable < string > recordIds) {
      using(var client = new HttpClient()) {
        client.BaseAddress = new Uri(_baseUrl);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        var content = JsonConvert.SerializeObject(new {
          Id = formsId,
            SubmissionIds = recordIds

        var postContent = new StringContent(content, Encoding.UTF8, "application/json");
        var response = client.PostAsync(uri, postContent).Result;
        return response.StatusCode.ToString();

    public string GetAccessToken() {
      var token = string.Empty;
      using(var client = new HttpClient()) {
        client.BaseAddress = new Uri(_baseUrl);
        var fields = new Dictionary < string,
          string > {
        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 the following methods:

  • GetFormsInfo – Gets forms in the system. Accept language as a parameter; if the language parameter is null, it returns form information in the master language. The requesting user must have read access to 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 specified form data. 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 8.0. The following example shows how to use these methods.

private const string AccessTokenURI = "/api/episerver/connect/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"]; // clientId added to access ServiceApi on step 3
private static readonly string Password = ConfigurationManager.AppSettings["password"]; // clientSecret added to access ServiceApi on step 3
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 > {
    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);