> ## Documentation Index
> Fetch the complete documentation index at: https://docs.didit.me/llms.txt
> Use this file to discover all available pages before exploring further.

# Questionnaire Report

> Didit questionnaire report reference covering sections, items, element types, conditional visibility, and per-item answers in V3 decision responses.

The questionnaire report contains the structured form a user was shown, the path they took through any conditional branches, and the answer for each visible item. It is returned per node, so multi-instance workflows (for example, one questionnaire per UBO) carry one entry per occurrence.

<Frame>
  <img src="https://mintcdn.com/didit-0f962782/z6T2GHM4Zh-iSj-K/images/questionnaire-report.png?fit=max&auto=format&n=z6T2GHM4Zh-iSj-K&q=85&s=9e483a61e829c6b94dd2dc7592a2c59b" alt="Didit KYC questionnaire report showing structured answers, sections and element types" width="2450" height="1621" data-path="images/questionnaire-report.png" />
</Frame>

## Overview

Each questionnaire response describes:

* The **questionnaire version** the user saw (title, description, languages, version metadata, sections).
* The **visible items** for the path the user actually took through the form's graph — items hidden by conditional logic are dropped from the response.
* The **answer** for every visible interactive item, in the shape that matches its `element_type`.
* A single **status** for the response as a whole.

Layout elements are reshaped rather than answered: each `SECTION_HEADER` becomes a section boundary (its title and description become the section's `title`/`description`), while `HEADING`, `PARAGRAPH`, and `SEPARATOR` stay in `items[]` without an `answer` key so the report keeps the same visual structure the user saw.

## Where it appears

The questionnaire report appears as the plural array **`questionnaire_responses[]`** in `GET /v3/session/{sessionId}/decision/`, for both KYC and KYB sessions, whenever a questionnaire feature ran. The field is `null` until at least one questionnaire instance has started. Each entry carries a `node_id` so multi-instance workflows can disambiguate which graph step produced it.

```text theme={null}
GET /v3/session/{sessionId}/decision/
  ──▶ { "questionnaire_responses": [ { node_id, questionnaire_id, title, status, sections, … }, … ] }
```

## Item shape

See [Questionnaire response in the Data Models reference](/reference/data-models#questionnaire-response) for the canonical schema.

```typescript theme={null}
interface QuestionnaireResponse {
  questionnaire_id: string;          // UUID of the questionnaire version that was answered
  title: string;                     // Questionnaire name, as set in the Console
  description: string | null;
  languages: string[];               // Supported language codes
  default_language: string;          // Default language code
  is_active: boolean;
  is_simple_questionnaire: boolean;  // true = flat list, false = branching graph
  questionnaire_group_id: string;    // UUID shared by all versions of the same questionnaire
  version: number;                   // Version number within the group
  published_at: string | null;       // ISO 8601 — when this version was published
  status: "Approved" | "In Review" | "Not Finished";
  sections: Array<{
    title: string | null;            // From the SECTION_HEADER that opens the section
    description: string | null;
    items: QuestionnaireItem[];
  }>;
  node_id: string | null;            // Workflow graph node that ran this questionnaire
}

interface QuestionnaireItem {
  uuid: string;                      // Form element UUID
  value: string;                     // Stable node id of the element within the questionnaire graph
  element_type:
    | "SHORT_TEXT" | "LONG_TEXT"
    | "DROPDOWN" | "SINGLE_CHOICE" | "MULTIPLE_CHOICE"
    | "NUMBER" | "EMAIL" | "PHONE" | "ADDRESS" | "COUNTRY"
    | "DATE_PICKER" | "TIME"
    | "CONSENT"
    | "FILE_UPLOAD" | "IMAGE"
    | "REPEATABLE_GROUP"
    | "HEADING" | "PARAGRAPH" | "SEPARATOR";   // layout-only — no answer key
  is_required: boolean;
  title: string | null;              // Localized
  description: string | null;        // Only populated on HEADING / PARAGRAPH text blocks
  placeholder: string | null;        // Localized
  choices: Array<{                   // DROPDOWN / SINGLE_CHOICE / MULTIPLE_CHOICE
    label: string;                   // Localized
    value: string;                   // Stable across languages
    requires_text_input?: boolean;   // Selecting this option triggers a free-text follow-up
  }> | null;
  max_files: number | null;          // FILE_UPLOAD / IMAGE upload cap (1–5)
  required_if: {                     // Conditional requirement rule, or null
    rules: Array<{ field: string; operator: string; value?: unknown }>;
    logic: "and" | "or";
  } | null;
  repeatable_config: {               // REPEATABLE_GROUP only, or null
    min_items?: number;
    max_items?: number;
    item_label?: string;             // Localized
    fields: Array<object>;           // Sub-field definitions (value, element_type, title, …)
  } | null;
  answer?: Answer | null;            // Omitted on HEADING / PARAGRAPH / SEPARATOR; null when unanswered
}
```

`SECTION_HEADER` elements never appear in `items[]` — they open a new section and supply its `title` and `description`.

### Element types

| Element type                        | Answer shape                                                               | Notes                                                                                                 |
| ----------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| `SHORT_TEXT`, `LONG_TEXT`           | `{ value: string }`                                                        | Free text.                                                                                            |
| `EMAIL`, `DATE_PICKER`, `TIME`      | `{ value: string }`                                                        | Typed text variants.                                                                                  |
| `NUMBER`                            | `{ value: number }`                                                        | JSON number — validated server-side as numeric.                                                       |
| `COUNTRY`                           | `{ value: string }`                                                        | ISO 3166-1 alpha-3 code (e.g. `"ESP"`), validated server-side.                                        |
| `PHONE`                             | `{ value: { countryCode, callingCode, number } }`                          | Structured phone object.                                                                              |
| `ADDRESS`                           | `{ value: { street, streetExtraInfo, city, state, postalCode, country } }` | Structured address object.                                                                            |
| `DROPDOWN`, `SINGLE_CHOICE`         | `{ value: string, text?: string }`                                         | `value` is the choice value; `text` is filled when the picked choice has `requires_text_input: true`. |
| `MULTIPLE_CHOICE`                   | `{ value: string[], text?: string }`                                       | Array of choice values.                                                                               |
| `CONSENT`                           | `{ value: boolean }`                                                       | JSON boolean.                                                                                         |
| `FILE_UPLOAD`, `IMAGE`              | `{ files: string[] }`                                                      | Each entry is a pre-signed URL.                                                                       |
| `REPEATABLE_GROUP`                  | `{ items: Array<{ [fieldValue]: Answer }> }`                               | One object per repetition, keyed by each sub-field's `value` with its own answer object.              |
| `HEADING`, `PARAGRAPH`, `SEPARATOR` | *(no `answer` key)*                                                        | Pure layout — kept in `items[]` for structure.                                                        |

A visible interactive item the user never answered is returned with `"answer": null`.

### Conditional visibility

When a questionnaire defines a graph (conditional logic), only items on the path the user actually took are included. An item hidden by a branch the user did not follow does **not** appear in `sections[].items` — even if it exists in the template. Sections left with no visible items are dropped entirely.

## Status values

The response-level `status` is one of three values. Internally, the base status (`Approved`, or `In Review` when the workflow forces manual review) is combined with any matching custom status rules using the platform-wide precedence Declined > In Review > Approved; a questionnaire-level `Declined` outcome is then mapped to `In Review` so operators handle the final disposition during review.

| Status         | Meaning                                                                                                              |
| -------------- | -------------------------------------------------------------------------------------------------------------------- |
| `Not Finished` | The user has not submitted the questionnaire yet.                                                                    |
| `In Review`    | Submitted and waiting on manual review (the workflow forces manual review, or a status rule escalated the response). |
| `Approved`     | Submitted and accepted.                                                                                              |

## Warnings

Questionnaires emit a single warning code, produced when a **custom status rule** configured on the questionnaire node matches an answer:

| Tag                            | Description                                                                                            |
| ------------------------------ | ------------------------------------------------------------------------------------------------------ |
| `CUSTOM_STATUS_RULE_TRIGGERED` | A workflow status rule evaluated a questionnaire answer and changed (or confirmed) the feature status. |

The warning's `additional_data` carries `field`, `operator`, `rule_value`, `actual_value`, `target_status`, and `score` when the rule defines one. Its `log_type` follows the rule's target status: `error` for Declined, `warning` for In Review, `information` otherwise.

Unlike other features, the questionnaire entry does not embed a `warnings[]` array — triggered-rule logs are recorded on the session under `feature: "QUESTIONNAIRE"` and surface in the Console review screen (see also the [Business Verification warnings listing](/business-verification/warnings#questionnaire); the same code applies to KYC sessions).

## Example — Source-of-funds questionnaire

```json theme={null}
{
  "questionnaire_responses": [
    {
      "questionnaire_id": "9f7485e0-b00b-4d56-9d3e-7859b68d1213",
      "title": "Source of Funds",
      "description": "Reply to this questionnaire to help us understand the source of funds.",
      "languages": ["en"],
      "default_language": "en",
      "is_active": true,
      "is_simple_questionnaire": true,
      "questionnaire_group_id": "2b6a9d40-13a8-4b1e-9a6c-3f1d2e4b5a60",
      "version": 1,
      "published_at": "2025-11-02T09:14:55.000000Z",
      "status": "Approved",
      "sections": [
        {
          "title": null,
          "description": null,
          "items": [
            {
              "uuid": "618636d9-7d5c-41ce-b8d0-1ab2a4be20db",
              "value": "question_1",
              "element_type": "DROPDOWN",
              "is_required": true,
              "title": "What is your primary source of funds?",
              "description": null,
              "placeholder": null,
              "choices": [
                { "label": "Salary", "value": "salary" },
                { "label": "Business Income", "value": "business_income" },
                { "label": "Savings", "value": "savings" },
                { "label": "Investments", "value": "investments" },
                { "label": "Inheritance/Gift", "value": "inheritance_gift" },
                { "label": "Other", "value": "other", "requires_text_input": true }
              ],
              "max_files": 1,
              "required_if": null,
              "repeatable_config": null,
              "answer": { "value": "salary" }
            },
            {
              "uuid": "2d16b527-72be-42e0-8e96-b164b818386c",
              "value": "question_2",
              "element_type": "LONG_TEXT",
              "is_required": true,
              "title": "Provide details of the primary source.",
              "description": null,
              "placeholder": null,
              "choices": null,
              "max_files": 1,
              "required_if": null,
              "repeatable_config": null,
              "answer": { "value": "Software engineer at Acme Ltd since 2018." }
            },
            {
              "uuid": "1bf8a2a3-14ee-48a8-bb3d-175481aae4aa",
              "value": "question_3",
              "element_type": "SINGLE_CHOICE",
              "is_required": true,
              "title": "Will any funds originate from third parties?",
              "description": null,
              "placeholder": null,
              "choices": [
                { "label": "Yes", "value": "yes", "requires_text_input": true },
                { "label": "No", "value": "no" }
              ],
              "max_files": 1,
              "required_if": null,
              "repeatable_config": null,
              "answer": { "value": "yes", "text": "One-off gift from parents, EUR 8,000." }
            },
            {
              "uuid": "a90a073d-e098-404c-bbce-5130d8b12a13",
              "value": "question_4",
              "element_type": "FILE_UPLOAD",
              "is_required": true,
              "title": "Upload a proof of funds document",
              "description": null,
              "placeholder": null,
              "choices": null,
              "max_files": 3,
              "required_if": null,
              "repeatable_config": null,
              "answer": {
                "files": [
                  "https://<media-host>/.../payslip-jul.pdf",
                  "https://<media-host>/.../payslip-aug.pdf"
                ]
              }
            }
          ]
        }
      ],
      "node_id": "feature_questionnaire"
    }
  ]
}
```

## Example — Not finished

```json theme={null}
{
  "questionnaire_responses": [
    {
      "questionnaire_id": "9f7485e0-b00b-4d56-9d3e-7859b68d1213",
      "title": "Source of Funds",
      "description": "Reply to this questionnaire to help us understand the source of funds.",
      "languages": ["en"],
      "default_language": "en",
      "is_active": true,
      "is_simple_questionnaire": true,
      "questionnaire_group_id": "2b6a9d40-13a8-4b1e-9a6c-3f1d2e4b5a60",
      "version": 1,
      "published_at": "2025-11-02T09:14:55.000000Z",
      "status": "Not Finished",
      "sections": [
        {
          "title": null,
          "description": null,
          "items": [
            {
              "uuid": "618636d9-7d5c-41ce-b8d0-1ab2a4be20db",
              "value": "question_1",
              "element_type": "DROPDOWN",
              "is_required": true,
              "title": "What is your primary source of funds?",
              "description": null,
              "placeholder": null,
              "choices": [
                { "label": "Salary", "value": "salary" },
                { "label": "Other", "value": "other", "requires_text_input": true }
              ],
              "max_files": 1,
              "required_if": null,
              "repeatable_config": null,
              "answer": null
            }
          ]
        }
      ],
      "node_id": "feature_questionnaire"
    }
  ]
}
```

When the user has reached the questionnaire step but not submitted answers yet, the response is returned with `status: "Not Finished"` and `"answer": null` on every visible item. A session that never reached the step produces no entry at all — `questionnaire_responses` stays `null` when no instance exists.

## Notes

* **File URLs expire.** Entries in `answer.files` are pre-signed URLs (4-hour validity by default). Re-fetch the decision endpoint when you need fresh URLs.
* **Localization.** Item `title`, `placeholder`, choice `label`, and section `title`/`description` are returned in English when the questionnaire supports it, otherwise in the questionnaire's `default_language`. The `value` of a choice remains stable across languages so you can key business logic off it safely.
* **Item `description` is layout-only.** It is populated only on `HEADING`/`PARAGRAPH` text blocks; interactive items always return `description: null`.

## Related

<CardGroup cols={3}>
  <Card title="Questionnaires overview" icon="clipboard-list" href="/core-technology/questionnaires/overview">
    How to build, version, and attach questionnaires to a workflow.
  </Card>

  <Card title="Data models — Questionnaire response" icon="table" href="/reference/data-models#questionnaire-response">
    Canonical field-by-field schema for this object.
  </Card>

  <Card title="Retrieve session" icon="arrow-down" href="/sessions-api/retrieve-session">
    Endpoint reference for the V3 decision payload.
  </Card>
</CardGroup>
