Table of Contents
- Dynamic Content
- Dynamic Fields
- Implementation Example
- Frequently Asked Questions:
- "What happens to an API response that contains more than 30 items?"
- "What if one item has a name more than 100 chars long?"
- "What if one of the item's identifiers has more than 50 chars?"
- "What if the identifier is essential and it is more than 50 chars? What can we do about it?"
- "What if a dynamic field is required, but the given API is broken or throws an error?"
- "Adding previous field identifier to dynamic field seems complicated - are there any improvements planned?"
- "I can't find the service type in the Portal."
- "In the Portal, the dynamic field returns 'No results' or 'Something went wrong with this question'".
- "Is the property name within the JSON payload case sensitive?"
- "What happens to items or properties that have exceeded a limit?"
- "Why do we need dynamic content rather than put an iframe inside of a field's description?"
- "Will dynamic content be able to refresh based on the answer from another field?"
- "How do we add a field ID from a previous section to the statement content API query?"
- "Where can I set up dynamic content?"
- "Have you considered allowing dynamic content under other fields?"
Dynamic Form Content
Updated
by Niamh Ferns
- Dynamic Content
- Dynamic Fields
- Implementation Example
- Frequently Asked Questions:
- "What happens to an API response that contains more than 30 items?"
- "What if one item has a name more than 100 chars long?"
- "What if one of the item's identifiers has more than 50 chars?"
- "What if the identifier is essential and it is more than 50 chars? What can we do about it?"
- "What if a dynamic field is required, but the given API is broken or throws an error?"
- "Adding previous field identifier to dynamic field seems complicated - are there any improvements planned?"
- "I can't find the service type in the Portal."
- "In the Portal, the dynamic field returns 'No results' or 'Something went wrong with this question'".
- "Is the property name within the JSON payload case sensitive?"
- "What happens to items or properties that have exceeded a limit?"
- "Why do we need dynamic content rather than put an iframe inside of a field's description?"
- "Will dynamic content be able to refresh based on the answer from another field?"
- "How do we add a field ID from a previous section to the statement content API query?"
- "Where can I set up dynamic content?"
- "Have you considered allowing dynamic content under other fields?"
Dynamic Content
Dynamic content is similar to dynamic fields, where our form will hit an API defined by you and render content based on your API's result. It is a great way to display custom content when a user is filling in a form. It is secure and customisable.
Similar to Microsoft's Adaptive cards, it can render different types of content based on the API result.
API Design Blueprint
The API you create should meet the following requirements:
- Your API should accept POST request calls
- Optionally, you can consume the
access_tokenandticketIdfrom a POST request's JSON body payload to see who is submitting the form and which ticket it belongs to. That way, you can render more customised content. - Respond with the correct CORS header. This is because our API will be under a different host from our Client Portal; thus, the browser will ask your permission to allow our Client Portal to view the response. Without a valid CORS header within the HTTP response, our Client Portal won't be able to render any content.
- Valid response format (see below).
Example: HTTP Request Initialised by Client Portal.
POST https://your.host/path
Origin: https://xxx.deskdirector.com
Content-Type: application/json
{
"ticketId": 3032,
"access_token": "token",
"access_token_expiration": 3600
}
Example: HTTP Response From Your API
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json
{
"value": [
{
"type": "markdown",
"text": "### Content you would like to **render**.",
"color": "accent"
},
{
"type": "list",
"value": [
{
"title": "Title of the list item",
"description": "Optional description",
"url": "https://your.host/optional/link"
},
{
"title": "Second item without link",
"description": "Optional description"
},
]
},
{
"type": "stats",
"value": [
{
"title": "Num of open tickets",
"value": "34",
"color": "accent",
"secondary": {
"value": "from 100",
"color": "light"
}
}
]
}
],
"request": {
"ticketId": 3032
}
}
Response Definition (TypeScript)
Below is an example in TypeScript that would produce the above example API response:
interface ContentRequest {
ticketId?: number;
access_token: string;
[key:string]: string[] | number | string;
}
type ContentType = 'list' | 'stats' | 'markdown';
type ContentColor = 'default' | 'accent' | 'good' | 'warning' | 'attention' | 'light';
type Content = ListContent | StatsContent | MarkdownContent;
interface ContentResponse {
// maximum of 5 contents.
value: Array<Content>;
request: ContentRequest;
}
// List
interface ListItem {
// max length of 200 chars
title: string;
// max length of 1_000 chars.
description?: string;
url?: string;
}
interface ListContent {
type: 'list';
// max of 30 items
value: Array<ListItem>;
}
// Stats
interface StatsItem {
// max of 50 chars
title: string;
// max of 50 chars.
value: string;
color?: ContentColor;
secondary?: {
value: string;
color?: ContentColor;
}
}
interface StatsContent {
type: 'stats';
// max of 30 items
value: Array<StatsItem>;
}
interface MarkdownContent {
type: 'markdown';
// maximum of 5_000 chars.
text: string;
color?: ContentColor;
}Rendered Example

Dynamic Fields
Dynamic fields provide a way to add and display dynamic content within your DeskDirector forms.
For example, you may consider an automation that pulls in emails from Active Directory via a dynamic field. You can then use the information to base other automations on this email when your form is submitted (i.e, adding a user to a mailbox, granting permissions, etc).
Usage & Limitations
Before continuing, it's important to provide some context regarding what these dynamic fields can and can't do.
- The dropdown menu for a dynamic field can display up to
30items. - Each item's name is limited to a maximum of 100 characters and must be a string.
- Each item's identifier is limited to a maximum of 50 characters and must be a string.
Web Service (API) Design Blueprint
Request (GET or POST):
https://{domain}/{path}?{query parameters}
Query parameters or properties in the JSON body payload
term: Search term, used for a type-ahead systemticketId: The ticket ID that the form is attached toaccess_token: The Access Token is a JWT token, where web service can use to gather user information. Such as user ID, email, company ID, etc. It can be verified with a public hash key.access_token_expirationHow long before the access token expires (in seconds)
Example GET Request:
https://test.deskdirector.com/api/v2/ddforms/dynamic/contacts?term=john&ticketId=&access_token={token}
Example POST Request:
POST requests are more secure than GET requests, since anything within the body payload is encrypted and secured by HTTPS. In comparison, anything passed through query parameters is in plain text and easy to read by malicious actors. Thus, an access token is better passed through an HTTPS request's body.
// POST https://host/api/path
{
"term": "john",
"ticketId": 3032,
"access_token": "token",
"access_token_expiration": 3600
}
Response
The response payload must be according to the following JSON schema. It is case insensitive:
{
"value": [
{
"name": "max length of 100 chars",
"identifier": "max length of 50 chars"
},
{
"name": "max length of 100 chars",
"identifier": "max length of 50 chars"
}
],
"request": {
"term": "search term",
"ticketId": number
}
}Fallback "Other" Choice
Due to the inherently unreliable nature of web services, an escape option is provided to the user for all dynamic fields. This is so that a user won't be prevented from completing a form in the event of API failure or the inability to find the correct choice (e.g. the contact they are looking for is not presented in the list, even though it should be).
The format of the other choice will be:
{
"name": "Other",
"identifier": "{field_identifier}_other",
"selected": true
}In the case where the "Other" choice is selected, a new choice will appear in the choices collection on the field, and their answer will be placed into the value property on the field.
Example:
{
"type": "api_single_choice",
"name": "Choose a contact",
"identifier": "d4ptmn",
"required": false,
"choices": [
{
"name": "Other",
"identifier": "d4ptmn_other",
"selected": true
}
],
"meta": {
"render": "radio"
},
"value": "Bob Smith"
}Error Response
Any service API error should be according to the following schema. If the error format is incorrect, the portal should display a generic error.
{
error: string,json
errorDescription: string
}
If an error is returned from the API, the form will allow the user to skip the question. They will be presented with an "Other" choice.
The error will be reported to Application Insights.
{
"name": 'DynamicFieldError';
"customDimensions": {
"form_entity_id": string;
"field_identifier": string;
"field_type": 'api_multi_select' | 'api_single_select';
"url": string;
[queryParamKey: string]: string;
}
}
Deliver Answer from Previous Fields
Dynamic fields are able to deliver answers from previous fields. To achieve delivery of answers to the target API, you should specify previous field identifier as query parameter.
- The field has to be before the current field. It can be from previous sections.
- It can be any field, including other dynamic fields
- Field identifier should be recorded as a parameter key inside an API URL.
For Example:

You can either set the identifier to something custom or see it in the JSON version of the form:

When your dynamic field calls the endpoint URL provided, it will pass in this field's current answer as a key: value in the request's body.
Implementation Example
Using dynamic fields in DeskDirector forms requires an API endpoint to be created. This may be a barrier to people who don't necessarily have the time or expertise to develop such an API. In this section, we will be going through a simple endpoint implementation using Power Automate, with our data source being an Excel sheet in Excel Online.
Prerequisites
- Power Automate licensing with access to standard connectors.
- For this example, we are only using a standard connector: Excel Online (Business)
- Download the source Flow template and Excel sheet (click to download)
Video Guide
Step-by-step guide in video form. No audio.
Step-by-Step Guide
- Upload the Excel file into a document library in one of the supported locations as specified by the Excel connector: OneDrive for Business, SharePoint Sites, Office 365 Groups. We are using SharePoint in this demo.
- Create an Excel Online (Business) connection in Power Automate. The account you use needs to have access to the document library where you saved the Excel fileYou'll want to use service accounts for all connections and flow ownership to prevent any issues.
- Import the flow in Power Automate
- Upload the template zip file and map the required connection.
- The import is expected to fail as the Excel action placeholders point to a non-existent file. Click 'Save as a new flow' to continue. This should open up the flow editor.
- Find the 'List rows present in a table' action. Navigate to the source data table in the Excel sheet. The table is called 'DatesTable'.
- Save.
- Copy the HTTP trigger endpoint URL. Needed in the next step.
- Turn on the flow.
- Create a form in DeskDirector
- Add a new field of Dynamic type. It should be at the bottom of the dropdown menu.
- Change the HTTP method to POST.
- Remove the
/from the input box before pasting the HTTP trigger endpoint URL in. - Save.
- Create a request type in DeskDirector
- Attach the form you just created.
- Enable the request type.
- Save.
- Test the dynamic field in Portal
- Impersonate a Portal user from the admin console
- Find the request type. Click on the field without typing to see the top 30 dates. Type something to search, e.g 'Monday'.
- Exercise for the reader: The dates are currently returned in descending order. Try to edit the flow to show the dates in ascending order.
- Congratulations! You have now implemented a dynamic field API endpoint for DeskDirector forms.
Pros & Cons of Using Power Automate Over a Bespoke API
Pros:
- Fast to implement, low code
- Easy to deploy and maintain
- Connectors to other Microsoft and third-party services. Any potential auth is managed within Power Automate.
Cons:
- Slow due to action overhead
- May get capped by action limits if the endpoint is busy
- Limitations of available data actions and expressions may require you to do clunky workarounds/hacks for things that are trivial in code
Conclusion
You should now have some basic understanding of what is required to implement an API endpoint for a dynamic field, along with a working, practical example that you can build out from.
This template, along with others, is available in our template gallery.
Frequently Asked Questions:
"What happens to an API response that contains more than 30 items?"
From a user experience point of view, too many items will give the users a hard time scanning through, which is why the dropdown of a dynamic field will only display the first 30 items. It is best to provide search capability at an API level if there are more than 30 items."
"What if one item has a name more than 100 chars long?"
The dropdown of a dynamic field is limited to displaying 100 characters only. Extra characters will be chopped off upon form submission.
"What if one of the item's identifiers has more than 50 chars?"
Similar to an item's name, on form submission, any extra characters will be chopped off.
"What if the identifier is essential and it is more than 50 chars? What can we do about it?"
You can hash those identifiers into a fixed length, then store them inside a key-value pair data table.
"What if a dynamic field is required, but the given API is broken or throws an error?"
Forms would allow submission without an answer from the API. The error would be submitted alongside the ticket.
"Adding previous field identifier to dynamic field seems complicated - are there any improvements planned?"
Yes, we are planning to improve UI/UX to support that. Once implemented, you no longer have to specify an identifier inside the API URL. Until it's implemented, parameter key is an alternative way to achieve it ahead of Admin Portal improvements.
"I can't find the service type in the Portal."
Make sure the service type is enabled and the contact you are impersonating has access to it.
"In the Portal, the dynamic field returns 'No results' or 'Something went wrong with this question'".
This could be for one of many possible reasons. If you are familiar with your browser's dev tools, it is easy to check if your endpoint was successfully called and diagnose the issue. You can read more here.
If you are not familiar with dev tools, you could check the following:
- Is the flow on?
- Is the HTTP method set to POST?
- Did you remove the / (forward slash) from the URL input box before pasting in your own endpoint? If the forward slash is still at the front, it gets treated as a relative URL, and the dynamic field will try call an endpoint that looks like this:
https://subdomain.deskdirector.com/https://prod-06.australiasoutheast.logic.azure... - If your flow is on and was triggered (there is run history), then check the run logs for any issues.
"Is the property name within the JSON payload case sensitive?"
Yes, it is case sensitive.
"What happens to items or properties that have exceeded a limit?"
Our client portal will truncate any additional characters or items.
"Why do we need dynamic content rather than put an iframe inside of a field's description?"
iframe inside Markdown is insecure content. We have recently disallowed any raw HTML from being rendered inside markdown.
"Will dynamic content be able to refresh based on the answer from another field?"
No, not at the moment. For now, you can put a field ID within your API URL's query parameters. We will pass the value to your API at the time of rendering. Thus, content based on a previous section is the way to go.
"How do we add a field ID from a previous section to the statement content API query?"
Depends on your API URL, whether it already contains a query parameter or not. I will give two examples below. The field ID we will use is field_id_one and field_id_two as an example. The purple part in the examples below is your API URL, where pink is a suffix for the additional query parameter we have added.
https://your.api.domain/path?field_id_one&field_id_two
https://your.api.domain/path?your_query=xxxx&another_query=yyyy&field_id_one&field_id_two
"Where can I set up dynamic content?"
You can set up within a statement field. The statement field was originally designed for content play. Thus, it makes sense to introduce under that field.
"Have you considered allowing dynamic content under other fields?"
No, not at the moment. Since dynamic content allows multiple pieces of content to be returned and rendered. There are too many content types that could impact the readability of form fields.