Developer Reference
This page is for developers who connect Omniform to their own systems. You may need to build two endpoints:
A choices endpoint that returns the choices for a dropdown, if your admin loads choices from your API.
A webhook that receives each form submission.
How admins set up forms is described in Build a Form.
To let customers fill a form from a link, your system creates the link with the Form Links API. Its documentation is linked as Public API Documentation at the top of the API Tokens menu in Omniform settings. Submissions from a link arrive at the same webhook described below, with a few extra keys.
Choices endpoint
The Nested API Dropdown, and Dropdown and Multi-select with From API as their choices source, load their choices from an endpoint you provide.
Response format
Return a JSON array of objects with label and value:
labelis the text the agent sees.valueis what your webhook receives for that choice, for example an ID from your system.Return the array itself, not an object that wraps it (such as
{ "data": [...] }). Other shapes are not displayed correctly.For the Nested API Dropdown, if the request fails or the response is not valid JSON, the agent sees Failed to get options.
For Dropdown and Multi-select with From API as their choices source:
labelandvaluemay be text or numbers.valueis always sent to your webhook as text.Items with the same
valueare shown once. Items with an emptyvalueare skipped.If the request fails, or the response is not an array of
label/valueobjects, the agent sees Couldn't load choices. Close and reopen this list to try again. They can still remove choices they already selected and submit the form.If the response is an empty array, the list shows that there is no data.
A choice the agent selected earlier that your endpoint no longer returns stays in the field, marked Not in list. It is still sent to your webhook unless the agent removes it, and it counts toward the Choice Limit.
How the request is sent
Method:
GET, with the headers and query parameters configured on the field.Where the request comes from depends on who fills the form. In the agent widget, it is sent from the agent's browser (see the next points). On the customer page, it is sent from Omniform's servers, so the customer never sees the endpoint, headers, or query parameters.
Added automatically: the query parameters
room_id(the room the agent is working in) andapp_id(your Omnichannel App ID). Test API in the builder does not sendroom_id, because no room is open.From the agent's browser (agent widget): the request is sent directly from the browser of the agent who opens the form, not from Qiscus servers. Your endpoint must be reachable from the agent's network and must allow cross-origin requests (CORS), including the headers configured on the field.
Headers are visible: because the request runs in the browser, the configured header values (for example an API key) can be seen with the browser's developer tools by anyone who opens the form. They are also included in the webhook body, in the field's
payload. Use a key that can only read this list.When it is called: when the field is shown to the agent. Searching filters the choices already loaded and does not call your endpoint again. For Dropdown and Multi-select, if the call fails, the agent can close and reopen the list to retry.
Nested levels: each level of a Nested API Dropdown calls its own endpoint: the first level when the field is shown, and each next level when the choice in the level before it changes. The admin passes that choice as a query parameter using a placeholder such as
{[Category]}, which is replaced with the selectedvalue. Until the previous level has a choice, the agent sees Please complete the previous field first.From Omniform's servers (customer page):
Your endpoint must be reachable from the internet. An endpoint that only answers on your office network or VPN works in the agent widget but not on the customer page.
Private, loopback, and link-local addresses, and redirects to them, are refused.
Each request must answer within 10 seconds and with at most 1 MB; otherwise the customer sees that the choices could not be loaded.
Only
labelandvalueof each choice reach the customer's browser. Other keys in your response are dropped.CORS does not apply, because the request does not come from a browser.
Changing the source of a saved field
An admin can switch a saved Dropdown or Multi-select field between Manual and From API at any time. The builder does not ask for confirmation. After the form is saved, new submissions change as follows:
Dropdown:
valuechanges from the choice label to thevaluefrom your API, for example from"Shipping"to"CAT-14". If your system stores or matches the label, readselected_option.labelinstead.Multi-select:
valuekeeps the same shape, but eachvalueinside it changes from the label to thevaluefrom your API, for example from{ "label": "Price inquiry", "value": "Price inquiry" }to{ "label": "Price inquiry", "value": "TAG-104" }.Payload keys:
sourcechanges to"api",apiis added, anddropdownsis no longer sent.Switching back to Manual reverses all of the above.
Submissions that were already sent are not changed. Agents who have the form open while the change is saved see This form was just updated. Check your answers, then submit again. when they submit; their answers to unchanged fields are kept.
Webhook
Each submission is sent to the Webhook URL configured in the form's Submit Action step.
Request
The form can define up to 5 custom headers. Use them to verify that a request comes from Omniform. Submissions from customer links use the same URL and headers. The Webhook URL must use HTTPS for new forms and for URLs changed in the builder, and must point to a public address: private, loopback, and link-local addresses, and redirects to them, are refused.
Body
attachments, conversation_file, additional_info, customer_properties, and room_info are included only when the matching option is turned on in the form. source is always included; form_link only for submissions from a customer link. The sample is shortened: each field's payload also carries that field's settings, such as its choice list or endpoint configuration.
Key | Description |
|---|---|
| The form's name and short description |
| Who submitted the form: |
| One object per field, in form order. See Field values by type |
| Files attached to the submission, by the agent or by the customer. Up to 5 files, 50 MB each |
| Link to the conversation history of the current session. Available only when the room is already resolved; otherwise |
| The room's additional information. |
| The selected customer properties |
| The selected room details. Only the items ticked in the form are included |
|
|
| Customer link submissions only. See Submissions from a customer link |
Submissions from a customer link
A submission from a customer link goes to the same webhook URL, with the same headers and the same fields format. Two things differ.
author is the customer, taken from the room:
idis the customer's ID in the channel (for example a phone number), sent as a string. For agents,idis a number.nameis the room name, usually the customer's name.emailis empty when the room has no customer email.If your integration uses
author.emailto find or assign an agent, checksourcefirst.
form_link describes the link that was used:
Key | Description |
|---|---|
| The link token, the last part of the link URL |
| Always |
| The API token that created the link: |
| The |
| When the link was created and when it expires, in UTC |
Other things to know:
A customer usually fills the form while the chat is still open, so
conversation_fileis normallynull.An agent and a customer who submit the same form in the same room overwrite each other's stored answers in Omniform. You still receive a webhook for each submission.
Treat customer attachments as untrusted files. Omniform checks the file type and size, but does not scan for viruses. Office files can contain macros, and CSV files can contain formulas that run when opened in a spreadsheet.
Field values by type
Each field's answer is in fields[].payload.value:
Field type |
|
|
|---|---|---|
Single-line Text |
| Text |
Multi-line Text |
| Text |
Phone Number |
| Text with digits only, country code first, no |
Checkbox |
| A JSON-encoded string of the selected labels ( |
Dropdown |
| Text: the selected choice. With a From API source, the |
Nested API Dropdown |
| Array with one object per level: the level's |
Date and Time |
| ISO 8601 timestamp in UTC ( |
Number and Decimal |
| Number. The type is |
Multi-select |
| Array of the selected choices as |
For Checkbox and Dropdown,
payload.choices/payload.dropdownscontain only the selected choices.identifieris a stable key for each field. Map fields byidentifierrather thanlabel, because a label can be renamed.
Dropdown and Multi-select payload keys
Key | Fields | Description |
|---|---|---|
|
|
|
|
| Endpoint configuration: |
|
| The Choice Limit. Present only when set |
|
|
|
|
| The selected choices, in the same format as before |
Multi-select sends the same {label, value} shape for both sources. For a Manual source, each value equals its label.
Dropdown also sends payload.selected_option with both the label and the value of the selected choice. payload.value stays a plain string, so existing integrations keep working.
Responding to Omniform
Respond with any HTTP 2xx status (200–299) once you have accepted the submission. Any other status is treated as a failure. Until this release, only 200 counted as success.
To show your own error message to the agent, return one of these structures. If more than one is present, Omniform uses the first match in this order: error.data.message, error.message, message.
Preferred:
Alternative 1:
Alternative 2:
messageis shown to the agent.detailsis optional and is not shown to the agent. Use it for debugging.
These messages are shown only in the agent widget. On the customer page, a failed submission always shows a generic message, so your error text never reaches the customer.
If none of these structures is returned, the agent sees:
When a submission fails
Omniform sends each submission once and does not retry it automatically.
Omniform waits 15 seconds for your response. A slower response counts as a failure.
The agent sees the error message, and their answers stay in the form, so they can correct them and submit again. Each attempt is a new request to your webhook.
The agent waits for your response before seeing the result, so respond quickly.
On a customer link, a failure keeps the link usable, and the customer can submit again. Use
form_link.tokento avoid creating a duplicate record for the same link.
If your service has already processed a submission but responds with a non-2xx status, the agent or customer will likely submit it again. Return a 2xx status as soon as you accept the data, and make sure a repeated submission does not create a duplicate record.
Troubleshooting
The agent sees "unexpected error when sending data to webhook url …"
Your webhook responded with a non-2xx status, did not respond within 15 seconds, or returned a body Omniform does not recognize. Check the status code in the message, and see Responding to Omniform.
Choices load for agents but not on the customer page
On the customer page, choices are requested from Omniform's servers, not from a browser. Check that your endpoint is reachable from the internet (not only from your office network or VPN), does not redirect to a private address, and answers within 10 seconds with at most 1 MB. See How the request is sent.
author.id is a string instead of a number
That is a submission from a customer link: author.id is the customer's ID in the channel. Check source to tell agent and customer submissions apart.
Choices from my API don't load in the agent widget
Check that the endpoint allows cross-origin requests (CORS), including the headers configured on the field, and that it returns a plain JSON array of {label, value} objects. Use Test API in the builder to see the response.
The Checkbox value is a string, not an array
That is the Checkbox format. Parse payload.value as JSON to get the list of selected labels.
Dates are a few hours off
Date and Time values are sent in UTC. Convert them to your timezone.
Qiscus Technology