Set up headless Optimizely Forms API
Describes the most important steps to get started with Optimizely Headless Form API.
Install packages
Optimizely Headless Form API consists of one main NuGet package, Optimizely.Cms.Forms.Service
, and some additional NuGet packages let you install only the necessary functionality.
Install the NuGet packages in your solution using the NuGet Package Manager in Visual Studio or with the command line:
dotnet add package Optimizely.Cms.Forms.Service
For authentication, install Episerver.OpenIDConnect
package using the NuGet Package Manager in Visual Studio or with the command line:
dotnet add package Episerver.OpenIDConnect
Configure form headless API options
Configure the API in ConfigureServices
in startup.cs
.
services.AddOptimizelyFormsService(options => {
options.EnableOpenApiDocumentation = true;
options.FormCorsPolicy = new FormCorsPolicy {
AllowOrigins = new string[] {
"*"
}, //Enter '*' to allow any origins, multiple origins separate by comma
AllowCredentials = true
};
options.OpenIDConnectClients.Add(new() {
Authority = "" //Enter the client's domain that requires authentication. The domain must include the protocol, for example, https://localhost:3000.
});
});
Configure encryption key for OpenIDConnect
.
public class FormServiceOptionsPostConfigure : IPostConfigureOptions<OptimizelyFormsServiceOptions>
{
private readonly OpenIddictServerOptions _options;
public FormServiceOptionsPostConfigure(IOptions<OpenIddictServerOptions> options)
{
_options = options.Value;
}
public void PostConfigure(string name, OptimizelyFormsServiceOptions options)
{
foreach (var client in options.OpenIDConnectClients)
{
foreach (var key in _options.EncryptionCredentials.Select(c => c.Key))
{
client.EncryptionKeys.Add(key);
}
foreach (var key in _options.SigningCredentials.Select(c => c.Key))
{
client.SigningKeys.Add(key);
}
}
}
}
Configure OpenIdConnect
in Startup.cs
.
services.AddOpenIDConnect<ApplicationUser> (
useDevelopmentCertificate: true,
signingCertificate: null,
encryptionCertificate: null,
createSchema: true,
options => {
options.AllowResourceOwnerPasswordFlow = true;
options.AccessTokenLifetime = TimeSpan.FromHours(8);
options.RequireHttps = false;
options.Applications.Add(new OpenIDConnectApplication {
ClientId = "ClientId",
Scopes = {
Scopes.OpenId,
},
});
});
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<OptimizelyFormsServiceOptions>, FormServiceOptionsPostConfigure>());
See OpenID Connect Authentication quick guide for details.
Test and verify the API.
PUT or GET endpoint description
You should have the following endpoints available on your host site:
- GET –
/_forms/v1/forms/{ContentGuid}?language={Language}
– Retrieve form data with form elements by content guid - PUT –
/_forms/v1/forms/
– Submit the form.
To verify that the API is working properly, open the Form Headless API in your browser:
http://<your-site-url>/_forms/v1/forms/<ContentGuid>?language=en
You should now get a 200 OK response and see the site and its associated properties:
{
"key": "41A07E4D3A634CC581F399CAAC75789C",
"properties": {
"title": "",
"allowToStoreSubmissionData": true,
"description": "",
"showSummarizedData": false,
"confirmationMessage": "",
"resetConfirmationMessage": "",
"redirectToPage": "",
"submitSuccessMessage": "",
"allowAnonymousSubmission": false,
"allowMultipleSubmission": false,
"showNavigationBar": false
},
"formElements": [{
"key": "2933aa8d3e794ccf89ff63bd9746d9f8",
"contentType": "SelectionElementBlock",
"displayName": "Selection",
"properties": {
"label": "Selection",
"description": "",
"validators": [{
"type": "RequiredValidator",
"description": null,
"model": {
"message": "This field is required.",
"validationCssClass": "ValidationRequired",
"additionalAttributes": {
"required": "",
"aria-required": "true"
}
}
}],
"allowMultiSelect": false,
"feed": "FormsFeed_UseManualInput",
"items": [{
"caption": "Value1",
"value": "Value1",
"checked": true
},
{
"caption": "Value2",
"value": "Value2",
"checked": false
}
],
"placeHolder": "",
"autoComplete": "",
"satisfiedAction": "",
"conditionCombination": "All",
"conditions": ""
},
"localizations": {
"selectionDefaultPlaceholder": "-- Select an option --"
}
},
{
"key": "362b97255ed0483aa096f062e189d857",
"contentType": "NumberElementBlock",
"displayName": "Number",
"properties": {
"label": "Number",
"description": "",
"validators": [{
"type": "NumericValidator",
"description": null,
"model": {
"message": "Enter a valid number.",
"validationCssClass": null,
"additionalAttributes": null
}
}],
"placeHolder": "",
"autoComplete": "",
"satisfiedAction": "",
"conditionCombination": "All",
"conditions": ""
},
"localizations": {}
},
{
"key": "05524d25f3084ba6b2437e4529ddcdcb",
"contentType": "FormStepBlock",
"displayName": "Form step",
"properties": {
"label": "",
"description": "",
"attachedContentLink": "",
"dependCondition": "",
"dependValue": ""
},
"localizations": {
"previousButtonLabel": "Previous step",
"nextButtonLabel": "Next step",
"pageButtonLabel": "Step"
}
},
{
"key": "426f2661d0da4751955bfc67503c556d",
"contentType": "TextareaElementBlock",
"displayName": "Text area",
"properties": {
"label": "Text area",
"description": "",
"validators": [],
"placeHolder": "",
"autoComplete": "",
"satisfiedAction": "",
"conditionCombination": "All",
"conditions": ""
},
"localizations": {}
},
{
"key": "97dd12c78d88450695dd231216c8dc1d",
"contentType": "SubmitButtonElementBlock",
"displayName": "Submit button",
"properties": {
"finalizeForm": false,
"label": "Submit",
"image": "",
"description": "",
"redirectToPage": "",
"satisfiedAction": "",
"conditionCombination": "All",
"conditions": ""
},
"localizations": {
"label": "Submit"
}
}
],
"locale": "en",
"localizations": {
"allowAnonymousSubmissionErrorMessage": "You must be logged in to submit this form. If you are logged in and still cannot post, make sure \"Do not track\" in your browser settings is disabled.",
"allowMultipleSubmissionErrorMessage": "You already submitted this form."
}
}
PUT /_forms/v1/forms
Submit single or multiple step form. The API accepts both application/json
and multipart/form-data
content types.
URL
/_forms/v1/forms
Method
PUT
Headers
- Content-Type –
application/json
ormultipart/form-data
- Authorization –
Bearer {token}
Request Body for application/json
When using the application/json
content type, the request body should be a JSON object with the following fields:
{
"formKey":"",
"locale":"",
"isFinalized": true,
"submissionKey":"",
"hostedPageUrl":"",
"currentStep":0,
"fields":{
"keyOfField1":"value1",
"keyOfField1":"value2",
...
}
}
Example:
{
"formKey":"6001a245d28a4419baf28f36fc3cf2a9",
"locale":"en",
"isFinalized": true,
"submissionKey":"",
"hostedPageUrl":"",
"currentStep":0,
"fields":{
"fd8c0ce15f56440abee3358a9fe9c9d8":"test1",
"b176ccda9f9f4ea4b87d57cf1eac8210":"test2",
}
}
Parameters for request
formKey
– The key of the form's submitted data.locale
– The locale of the submitted form.isFinalized
– Indicate whether the form submission is finalized.submissionKey
– The key of the form's submitted data. ThissubmissionKey
is used in multi-step forms and is returned from the previous step's submitted response.hostedPageUrl
– The URL of the page hosted the form step.currentStep
– The index of the current form step in submission.fields
– Key value collection of submitted data.
Request Body for multipart/form-data
When using the multipart/form-data
content type, the request body should include:
- A list of files, each identified by a unique GUID key.
- A data field containing a JSON string that conforms to the structure defined in the
application/json
part.
Example request
PUT /_forms/v1/forms HTTP/1.1
Host: api.example.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Authorization: Bearer YOUR_TOKEN
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="data"
{
"formKey":"6001a245d28a4419baf28f36fc3cf2a9",
"locale":"en",
"isFinalized":true,
"submissionKey":"",
"hostedPageUrl":"",
"currentStep":0,
"fields": {
"fd8c0ce15f56440abee3358a9fe9c9d8":"test1",
"b176ccda9f9f4ea4b87d57cf1eac8210":"test2"
}
}
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="123e4567-e89b-12d3-a456-426614174000"; filename="file1.jpg"
Content-Type: image/jpeg
(binary data)
------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="123e4567-e89b-12d3-a456-426614174001"; filename="file2.jpg"
Content-Type: image/jpeg
(binary data)
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Authentication
Configure the signing or encryption key and authority to verify the authentication JSON WebToken (jwt) in the back end:
services.AddOptimizelyFormsService(options => {
options.OpenIDConnectClients.Add(new() {
Authority = http://host:port,
EncryptionKeys = ,
SigningKeys =
});
});
Configure Swagger
Install the NuGet packages in your solution using the NuGet Package Manager in Visual Studio or with the command line:
dotnet add package Swashbuckle.AspNetCore
Configure Swagger in startup.cs
.
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new OpenApiInfo {
Title = "AlloySampleSite Custom API",
Version = "v1",
});
});
app.UseSwagger();
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("/_forms/v1/docs/openapi.json", "Optimizely Headless Form API V1");
options.SwaggerEndpoint("/swagger/v1/swagger.json", "AlloySampleSite Custom API V1");
options.OAuthClientId("ClientId");
options.OAuthClientSecret("ClientSecret");
});
Use Postman
Postman (postman.com) is a free tool that you can use as an API client to send REST calls. With Postman, you can connect to APIs and simulate calls to endpoints and their responses without setting up a backend server.
To test the Form Headless API, you can use a tool such as Postman and send a request to one of the endpoints mentioned in the above section.
Updated 2 months ago