Skip to main content
To capture structured feedback, you author reusable Questions once, then assemble them into a Questionnaire (a form). Each Question also declares where its answers are routed, so a single form can update a Profile, create a Rating, and record an Interaction at the same time. This guide covers authoring both layers. For the model behind them, see Questions and questionnaires. All endpoints are bearer authenticated and live under https://api.[tenant].getomneo.com/api/v3.

The three layers

Creating a Question

Author a Question independently of any form:
A successful create returns 201.

Field reference

Availability and re-asking

live_from and live_to bound the dates a question is asked. Either can be null, and a null bound means the question stays live on that side, so leaving both null keeps the question always live. answer_ttl_days sets how long an answer stays valid before the same question can be asked again. Set a number of days for facts that go stale, such as a preference you want to refresh each season. Leave it null for stable facts you only need once, such as gender, so the question is never re-asked after it is answered.

Choice and slider inputs

single_select and multi_select questions render their options. A slider needs validation.min and validation.max to define its range:
Routing lives on the Question, not on the form. Three fields decide what happens to each answer once it is captured: link_type accepts these destinations: For how link_target is shaped per destination, the write policies, and the observable result of each route, see Routing answers in the concept and Submitting questionnaires and routing answers.
Link configuration is not versioned. It lives on the Question directly, so changing where answers route affects future submissions only. Answers already written keep the destination they were routed to.

Versioning

Questions are versioned. Editing a question’s wording, type, or options creates a new immutable version and advances the question’s current version. Answers already captured stay pinned to the version that was active when they were given, so editing a question never rewrites historical responses.

The question response shape

Reading a question with GET /questions/{question} returns the versioned shape. The rendering fields you sent at the top level on create come back nested under current_version, and every version the question has had is listed in versions[]:
Create and read use different shapes. On create you send the rendering fields (label, type, options, validation, default_value, live_from, live_to, answer_ttl_days, help_text, icon, image_url) at the top level of the request body. On read those same fields come back nested under current_version, because each edit produces a new version. Identity and routing fields (handle, name, is_active, link_type, link_target, link_write_policy) stay at the top level and are never versioned.

Top-level fields

Version fields

current_version and every entry in versions[] share this shape:

Reading, updating, and deleting a question

Update a question by sending only the fields you want to change:
Editing any rendering field (label, type, options, validation, default_value, help_text, icon, image_url, live_from, live_to, answer_ttl_days) creates a new version and advances current_version. Editing an identity or routing field (name, is_active, link_type, link_target, link_write_policy) updates it in place with no new version. Delete a question with DELETE /questions/{question}.

Custom fields on questions and questionnaires

Both questions and questionnaires accept custom fields, the same typed-metadata pattern used elsewhere in Omneo (see Custom attributes). A custom field extends the resource with a value addressed by a namespace and a handle, so you can attach integration-specific data without changing the question or questionnaire shape. Create a custom field on a question:
A successful create returns 200:

Request fields

Response fields

Managing custom fields

Questionnaires expose the same collection at /questionnaires/{questionnaire}/custom-fields, with the same request and response shape. The custom_fieldable_type comes back as questionnaire there.

Creating a Questionnaire

A Questionnaire groups questions into an ordered form. Create one with a purpose and a nested questions array of slots:
A successful create returns 201.

Field reference

Ownership

A questionnaire can be owned three ways: At most one active questionnaire exists per owner and purpose, so an owner cannot have two active post_visit forms at once.

Question slots

Each entry in questions is a slot that pins a question into the form:

Slot keys

mapping_key is the slot’s name inside the form. You set it when you add the slot.
Deleting a slot does not free its mapping_key. The delete is a soft delete, and the deleted row keeps its claim on the key for that version, so adding a slot with the same key against the same version returns 422 even though the key is no longer visible in the form. Use a different key, or replace the whole form with a PUT, which builds a new version where the key is free again.
A visibility_condition reads an earlier answer through the slot’s key, as answers.<mapping_key>:
That rule shows its slot only when the slot keyed reason was answered repair. This is what mapping_key exists for: it is the variable name a condition uses. Reads return visibility_dependencies next to visibility_condition on every slot. It lists the mapping_keys the condition refers to, extracted server side, so a front end does not have to parse the rule to know which fields to watch.
Renaming a mapping_key does not update conditions that refer to the old name. A condition pointing at a key that no longer exists reads null, so an equality check against a value fails and the slot it guards stays hidden. Update the conditions in the same change.Renaming also splits reporting. Answers keep the key they were captured under, so answers to the same slot end up filed under two keys either side of the rename. Treat a mapping_key as fixed once a form is live, and carry it unchanged into each new version.
A mapping_key names the answer. It does not route it: where an answer is written comes from the question’s link configuration. A submission never addresses an answer by mapping_key either. See Addressing each answer.

Pages

Multi-step forms group slots into pages. Each page carries a title, optional description, image_url, section_header, sort_order, and its own questions array of slots.

Versioning

Questionnaires are versioned like questions. Each change to the slot list creates a new version, and every submission is pinned to the version it was filled under.

The questionnaire response shape

Reading a questionnaire with GET /questionnaires/{questionnaire} returns its identity, ownership, and the pages[] of the current version, each page carrying its own question slots:

Top-level fields

Page fields

Each entry in pages[] has this shape:

Adding a question slot to an existing questionnaire

To add a slot without rebuilding the form, post to the questionnaire’s questions endpoint:
A successful create returns 201.

Managing questionnaire pages

Pages group question slots into steps for a multi-step form. Manage them under the questionnaire’s pages endpoint. Add a page:
A successful create returns 201 and responds with the questionnaire and its updated pages[].

Request fields

Managing pages

Place a slot on a page by setting questionnaire_page_id to the page id when you add a question slot, as shown above.

Reading, updating, and deleting a questionnaire

Editing the slot list or pages creates a new version and advances the current version. In-flight submissions stay pinned to the version they were filled under, so a change never rewrites answers already recorded.

Errors