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

# Informe de cuestionario: esquema JSON de las respuestas

> Informe de cuestionario de Didit: secciones, ítems, tipos de elementos, visibilidad condicional y respuestas por ítem en las decisiones V3.

El informe de cuestionario contiene el formulario estructurado que se mostró al usuario, el recorrido que siguió por las ramas condicionales y la respuesta a cada elemento visible. Se devuelve por nodo, de modo que los workflows con varias instancias (por ejemplo, un cuestionario por UBO) incluyen una entrada por cada ocurrencia.

![Informe de cuestionario KYC de Didit con respuestas estructuradas, secciones y tipos de elemento](https://mintcdn.com/didit-0f962782/z6T2GHM4Zh-iSj-K/images/questionnaire-report.png?fit=max\&auto=format\&n=z6T2GHM4Zh-iSj-K\&q=85\&s=9e483a61e829c6b94dd2dc7592a2c59b)

## Descripción general

Cada respuesta de cuestionario describe:

* La **versión del cuestionario** que vio el usuario (título, descripción, idiomas, metadatos de versión, secciones).
* Los **elementos visibles** del recorrido que el usuario siguió realmente por el grafo del formulario: los elementos ocultos por la lógica condicional se eliminan de la respuesta.
* La **respuesta** a cada elemento interactivo visible, con la estructura que corresponde a su `element_type`.
* Un único **estado** para la respuesta en su conjunto.

Los elementos de diseño se reorganizan en lugar de incluir respuestas: cada `SECTION_HEADER` se convierte en un límite de sección (su título y su descripción pasan a ser el `title`/`description` de la sección), mientras que `HEADING`, `PARAGRAPH` y `SEPARATOR` permanecen en `items[]` sin clave `answer`, para que el informe conserve la misma estructura visual que vio el usuario.

## Dónde aparece

El informe de cuestionario aparece como el array en plural **`questionnaire_responses[]`** en `GET /v3/session/{sessionId}/decision/`, tanto en sesiones KYC como KYB, siempre que se haya ejecutado una función de cuestionario. El campo es `null` hasta que se haya iniciado al menos una instancia de cuestionario. Cada entrada incluye un `node_id` para que los flujos con varias instancias puedan distinguir qué paso del grafo la generó.

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

## Estructura de los elementos

Consulta [Respuesta de cuestionario en la referencia de modelos de datos](https://docs.didit.me/es/reference/data-models.md#respuesta-de-cuestionario) para ver el esquema canónico.

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

Los elementos `SECTION_HEADER` nunca aparecen en `items[]`: abren una nueva sección y aportan su `title` y su `description`.

### Tipos de elemento

| Tipo de elemento | Estructura de la respuesta | Notas |
| - | - | - |
| `SHORT_TEXT`, `LONG_TEXT` | `{ value: string }` | Texto libre. |
| `EMAIL`, `DATE_PICKER`, `TIME` | `{ value: string }` | Variantes de texto tipadas. |
| `NUMBER` | `{ value: number }` | Número JSON, validado como numérico en el servidor. |
| `COUNTRY` | `{ value: string }` | Código ISO 3166-1 alfa-3 (por ejemplo, `"ESP"`), validado en el servidor. |
| `PHONE` | `{ value: { countryCode, callingCode, number } }` | Objeto de teléfono estructurado. |
| `ADDRESS` | `{ value: { street, streetExtraInfo, city, state, postalCode, country } }` | Objeto de dirección estructurado. |
| `DROPDOWN`, `SINGLE_CHOICE` | `{ value: string, text?: string }` | `value` es el valor de la opción; `text` se rellena cuando la opción elegida tiene `requires_text_input: true`. |
| `MULTIPLE_CHOICE` | `{ value: string[], text?: string }` | Array de valores de opción. |
| `CONSENT` | `{ value: boolean }` | Booleano JSON. |
| `FILE_UPLOAD`, `IMAGE` | `{ files: string[] }` | Cada entrada es una URL prefirmada. |
| `REPEATABLE_GROUP` | `{ items: Array<{ [fieldValue]: Answer }> }` | Un objeto por repetición, con la clave correspondiente al `value` de cada subcampo y su propio objeto de respuesta. |
| `HEADING`, `PARAGRAPH`, `SEPARATOR` | *(sin clave `answer`)* | Solo de diseño: se mantienen en `items[]` por la estructura. |

Un elemento interactivo visible al que el usuario nunca respondió se devuelve con `"answer": null`.

### Visibilidad condicional

Cuando un cuestionario define un grafo (lógica condicional), solo se incluyen los elementos del recorrido que el usuario siguió realmente. Un elemento oculto por una rama que el usuario no siguió **no** aparece en `sections[].items`, aunque exista en la plantilla. Las secciones que se quedan sin elementos visibles se eliminan por completo.

## Valores de estado

El `status` a nivel de respuesta es uno de tres valores. Internamente, el estado base (`Approved`, o `In Review` cuando el flujo fuerza la revisión manual) se combina con las reglas de estado personalizadas que coincidan, según la precedencia de toda la plataforma: Declined > In Review > Approved; después, un resultado `Declined` a nivel de cuestionario se convierte en `In Review` para que los operadores decidan el resultado final durante la revisión.

| Estado | Significado |
| - | - |
| `Not Finished` | El usuario todavía no ha enviado el cuestionario. |
| `In Review` | Enviado y pendiente de revisión manual (el flujo fuerza la revisión manual o una regla de estado escaló la respuesta). |
| `Approved` | Enviado y aceptado. |

## Advertencias

Los cuestionarios emiten un único código de advertencia, que se genera cuando una **regla de estado personalizada** configurada en el nodo del cuestionario coincide con una respuesta:

| Etiqueta | Descripción |
| - | - |
| `CUSTOM_STATUS_RULE_TRIGGERED` | Una regla de estado del flujo evaluó una respuesta del cuestionario y cambió (o confirmó) el estado de la función. |

El `additional_data` de la advertencia incluye `field`, `operator`, `rule_value`, `actual_value`, `target_status` y `score` cuando la regla define una puntuación. Su `log_type` depende del estado objetivo de la regla: `error` para Declined, `warning` para In Review e `information` en los demás casos.

A diferencia de otras funciones, la entrada del cuestionario no incluye un array `warnings[]`: los registros de reglas activadas se guardan en la sesión con `feature: "QUESTIONNAIRE"` y se muestran en la pantalla de revisión de la consola (consulta también el [listado de advertencias de Verificación de empresas](https://docs.didit.me/es/business-verification/warnings.md#cuestionario); el mismo código se aplica a las sesiones KYC).

## Ejemplo — Cuestionario de origen de los fondos

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

## Ejemplo — Sin finalizar

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

Cuando el usuario ha llegado al paso del cuestionario pero todavía no ha enviado sus respuestas, la respuesta se devuelve con `status: "Not Finished"` y `"answer": null` en cada elemento visible. Una sesión que nunca llegó a ese paso no genera ninguna entrada: `questionnaire_responses` sigue siendo `null` cuando no existe ninguna instancia.

## Notas

* **Las URL de los archivos expiran.** Las entradas de `answer.files` son URL prefirmadas (con una validez de 4 horas por defecto). Vuelve a consultar el endpoint de decisión cuando necesites URL nuevas.
* **Localización.** Los campos `title`, `description` y `placeholder` de cada elemento, el `label` de cada opción y los campos `title`/`description` de cada sección se devuelven en inglés cuando el cuestionario lo admite y, en caso contrario, en el `default_language` del cuestionario. El `value` de una opción se mantiene igual en todos los idiomas, así que puedes basar tu lógica de negocio en él con seguridad.
* **El campo `description` de un elemento es su texto de ayuda.** Cualquier elemento puede tenerlo, incluidas las preguntas, y es `null` cuando no se ha definido. Un `SEPARATOR` nunca lo tiene.

## Relacionado

> [card] [Visión general de los cuestionarios](https://docs.didit.me/es/core-technology/questionnaires/overview.md)
>
> Cómo crear cuestionarios, gestionar sus versiones y añadirlos a un flujo (workflow).

> [card] [Modelos de datos: respuesta del cuestionario](https://docs.didit.me/es/reference/data-models.md#respuesta-de-cuestionario)
>
> Esquema canónico de este objeto, campo por campo.

> [card] [Obtener sesión](https://docs.didit.me/es/sessions-api/retrieve-session.md)
>
> Referencia del endpoint para el payload de decisión V3.


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