> ## 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.

# Отчёт по анкете: JSON-схема ответов

> Справочник Didit по отчёту анкет: разделы, поля, типы элементов, условная видимость и ответы по каждому пункту в ответах решений V3.

Отчёт по анкете содержит структурированную форму, показанную пользователю, пройденный им путь по условным ветвям и ответ на каждый видимый элемент. Он возвращается для каждого узла, поэтому сценарии с несколькими экземплярами (например, по одной анкете на каждого UBO) содержат по одной записи на каждый экземпляр.

![Отчёт Didit по KYC-анкете, показывающий структурированные ответы, разделы и типы элементов](https://mintcdn.com/didit-0f962782/z6T2GHM4Zh-iSj-K/images/questionnaire-report.png?fit=max\&auto=format\&n=z6T2GHM4Zh-iSj-K\&q=85\&s=9e483a61e829c6b94dd2dc7592a2c59b)

## Обзор

Каждый ответ на анкету описывает:

* **Версию анкеты**, которую видел пользователь (название, описание, языки, метаданные версии, разделы).
* **Видимые элементы** на пути, который пользователь фактически прошёл по графу формы, — скрытые условной логикой элементы исключаются из ответа.
* **Ответ** на каждый видимый интерактивный элемент в формате, соответствующем его `element_type`.
* Единый **статус** для ответа в целом.

Элементы разметки преобразуются в структуру, а не заполняются ответами: каждый `SECTION_HEADER` становится границей раздела (его заголовок и описание становятся `title`/`description` раздела), а `HEADING`, `PARAGRAPH` и `SEPARATOR` остаются в `items[]` без ключа `answer`, чтобы отчёт сохранял ту же визуальную структуру, которую видел пользователь.

## Где отображается

Отчёт по анкете возвращается в виде массива во множественном числе **`questionnaire_responses[]`** в `GET /v3/session/{sessionId}/decision/` как для сессий KYC, так и для KYB, если выполнялась функция анкеты. Поле имеет значение `null` до тех пор, пока не будет запущен хотя бы один экземпляр анкеты. Каждая запись содержит `node_id`, благодаря чему сценарии с несколькими экземплярами могут однозначно определить, какой шаг графа её создал.

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

## Формат элементов

Каноническую схему см. в разделе [Ответ на анкету в справочнике моделей данных](https://docs.didit.me/ru/reference/data-models.md#ответ-на-анкету).

```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;        // Localized help text, or null when none is set
  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` никогда не появляются в `items[]` — они открывают новый раздел и задают его `title` и `description`.

### Типы элементов

| Тип элемента | Формат ответа | Примечания |
| - | - | - |
| `SHORT_TEXT`, `LONG_TEXT` | `{ value: string }` | Произвольный текст. |
| `EMAIL`, `DATE_PICKER`, `TIME` | `{ value: string }` | Типизированные текстовые варианты. |
| `NUMBER` | `{ value: number }` | Число в формате JSON — валидируется на стороне сервера как числовое значение. |
| `COUNTRY` | `{ value: string }` | Код ISO 3166-1 alpha-3 (например, `"ESP"`), валидируется на стороне сервера. |
| `PHONE` | `{ value: { countryCode, callingCode, number } }` | Структурированный объект телефона. |
| `ADDRESS` | `{ value: { street, streetExtraInfo, city, state, postalCode, country } }` | Структурированный объект адреса. |
| `DROPDOWN`, `SINGLE_CHOICE` | `{ value: string, text?: string }` | `value` представляет собой выбранное значение; `text` заполняется, если для выбранного варианта указано `requires_text_input: true`. |
| `MULTIPLE_CHOICE` | `{ value: string[], text?: string }` | Массив выбранных значений. |
| `CONSENT` | `{ value: boolean }` | Логическое значение JSON. |
| `FILE_UPLOAD`, `IMAGE` | `{ files: string[] }` | Каждая запись представляет собой предварительно подписанный URL. |
| `REPEATABLE_GROUP` | `{ items: Array<{ [fieldValue]: Answer }> }` | Один объект на каждое повторение, где ключом является `value` каждого подполя со своим объектом ответа. |
| `HEADING`, `PARAGRAPH`, `SEPARATOR` | *(без ключа `answer`)* | Исключительно разметка — сохраняется в `items[]` для структуры. |

Видимый интерактивный элемент, на который пользователь так и не ответил, возвращается с `"answer": null`.

### Условная видимость

Если анкета определяет граф (условную логику), включаются только элементы на пути, который пользователь фактически прошёл. Элемент, скрытый ветвью, по которой пользователь не пошёл, **не** появляется в `sections[].items` — даже если он есть в шаблоне. Разделы, в которых не осталось видимых элементов, полностью опускаются.

## Значения статуса

Поле `status` на уровне ответа принимает одно из трёх значений. Внутри системы базовый статус (`Approved` или `In Review`, если сценарий принудительно требует ручной проверки) объединяется с любыми сработавшими пользовательскими правилами статуса в соответствии с единым для всей платформы порядком приоритета Declined > In Review > Approved; затем результат уровня анкеты `Declined` преобразуется в `In Review`, чтобы операторы вынесли окончательное решение в ходе проверки.

| Статус | Значение |
| - | - |
| `Not Finished` | Пользователь ещё не отправил анкету. |
| `In Review` | Отправлена и ожидает ручной проверки (сценарий принудительно требует ручной проверки или правило статуса эскалировало ответ). |
| `Approved` | Отправлена и принята. |

## Предупреждения

Анкеты генерируют единственный код предупреждения, возникающий при совпадении ответа с **пользовательским правилом статуса**, настроенным на узле анкеты:

| Тег | Описание |
| - | - |
| `CUSTOM_STATUS_RULE_TRIGGERED` | Правило статуса сценария проверило ответ на анкету и изменило (или подтвердило) статус функции. |

Поле `additional_data` предупреждения содержит `field`, `operator`, `rule_value`, `actual_value`, `target_status` и `score`, если правило его определяет. Его `log_type` зависит от целевого статуса правила: `error` для Declined, `warning` для In Review и `information` в остальных случаях.

В отличие от других функций, запись анкеты не содержит встроенный массив `warnings[]` — журналы сработавших правил записываются в сессии под `feature: "QUESTIONNAIRE"` и отображаются на экране проверки в Консоли (см. также [список предупреждений функции «Верификация бизнеса (KYB)»](https://docs.didit.me/ru/business-verification/warnings.md#анкета); тот же код применяется к сессиям KYC).

## Пример — анкета об источнике средств

```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"
    }
  ]
}
```

## Пример — не завершено

```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"
    }
  ]
}
```

Когда пользователь дошёл до шага с анкетой, но ещё не отправил ответы, ответ возвращается со `status: "Not Finished"` и `"answer": null` для каждого видимого элемента. Сессия, которая так и не дошла до этого шага, вообще не создаёт записей — `questionnaire_responses` остаётся `null`, если ни одного экземпляра не существует.

## Примечания

* **Срок действия URL файлов истекает.** Записи в `answer.files` представляют собой предварительно подписанные URL (со сроком действия 4 часа по умолчанию). Повторно вызовите endpoint решения, когда вам понадобятся свежие URL.
* **Локализация.** Элементы `title`, `description`, `placeholder`, варианты выбора `label`, а также `title`/`description` разделов возвращаются на английском языке, если анкета это поддерживает, в противном случае на языке, указанном в `default_language` анкеты. Значение `value` варианта выбора остаётся неизменным для всех языков, поэтому вы можете безопасно использовать его в бизнес-логике.
* **Поле элемента `description` представляет собой вспомогательный текст элемента.** Любой элемент может содержать его, включая вопросы, и оно равно `null`, если текст не задан. У `SEPARATOR` его никогда не бывает.

## Связанные материалы

> [card] [Обзор анкет](https://docs.didit.me/ru/core-technology/questionnaires/overview.md)
>
> Как создавать, версионировать и прикреплять анкеты к сценарию.

> [card] [Модели данных — Ответ на анкету](https://docs.didit.me/ru/reference/data-models.md#ответ-на-анкету)
>
> Каноническая схема объекта с описанием каждого поля.

> [card] [Получить сессию](https://docs.didit.me/ru/sessions-api/retrieve-session.md)
>
> Справочник по endpoint для payload решения V3.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.