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

# Laporan Kuesioner: Skema JSON Jawaban

> Referensi laporan kuesioner Didit untuk bagian, item, tipe elemen, visibilitas bersyarat, dan jawaban per item pada respons keputusan V3.

Laporan kuesioner berisi formulir terstruktur yang ditampilkan kepada pengguna, jalur yang mereka ambil melalui cabang kondisional mana pun, dan jawaban untuk setiap item yang terlihat. Laporan ini dikembalikan per node, sehingga alur kerja multi-instans (misalnya, satu kuesioner per UBO) membawa satu entri per kemunculan.

![Didit KYC questionnaire report showing structured answers, sections and element types](https://mintcdn.com/didit-0f962782/z6T2GHM4Zh-iSj-K/images/questionnaire-report.png?fit=max\&auto=format\&n=z6T2GHM4Zh-iSj-K\&q=85\&s=9e483a61e829c6b94dd2dc7592a2c59b)

## Gambaran umum

Setiap respons kuesioner menjelaskan:

* **Versi kuesioner** yang dilihat pengguna (judul, deskripsi, bahasa, metadata versi, bagian).
* **Item yang terlihat** untuk jalur yang benar-benar diambil pengguna melalui graf formulir — item yang disembunyikan oleh logika kondisional akan dihapus dari respons.
* **Jawaban** untuk setiap item interaktif yang terlihat, dalam bentuk yang sesuai dengan `element_type` miliknya.
* Sebuah **status** tunggal untuk respons secara keseluruhan.

Elemen tata letak dibentuk ulang alih-alih dijawab: setiap `SECTION_HEADER` menjadi batas bagian (judul dan deskripsinya menjadi `title`/`description` bagian tersebut), sementara `HEADING`, `PARAGRAPH`, dan `SEPARATOR` tetap berada di `items[]` tanpa kunci `answer` sehingga laporan mempertahankan struktur visual yang sama seperti yang dilihat pengguna.

## Lokasi kemunculan

Laporan kuesioner muncul sebagai array dalam bentuk jamak **`questionnaire_responses[]`** di `GET /v3/session/{sessionId}/decision/`, baik untuk sesi KYC maupun KYB, setiap kali fitur kuesioner dijalankan. Kolom ini bernilai `null` sampai setidaknya satu instans kuesioner dimulai. Setiap entri membawa `node_id` sehingga alur kerja multi-instans dapat membedakan langkah graf mana yang menghasilkannya.

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

## Bentuk item

Lihat [Respons kuesioner di referensi Model Data](https://docs.didit.me/id/reference/data-models.md#respons-kuesioner) untuk skema kanonik.

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

Elemen `SECTION_HEADER` tidak pernah muncul di `items[]` — elemen ini membuka bagian baru serta menyediakan `title` dan `description` bagian tersebut.

### Jenis elemen

| Jenis elemen | Bentuk jawaban | Catatan |
| - | - | - |
| `SHORT_TEXT`, `LONG_TEXT` | `{ value: string }` | Teks bebas. |
| `EMAIL`, `DATE_PICKER`, `TIME` | `{ value: string }` | Varian teks bertipe. |
| `NUMBER` | `{ value: number }` | Angka JSON — divalidasi di sisi server sebagai numerik. |
| `COUNTRY` | `{ value: string }` | Kode ISO 3166-1 alpha-3 (misalnya `"ESP"`), divalidasi di sisi server. |
| `PHONE` | `{ value: { countryCode, callingCode, number } }` | Objek telepon terstruktur. |
| `ADDRESS` | `{ value: { street, streetExtraInfo, city, state, postalCode, country } }` | Objek alamat terstruktur. |
| `DROPDOWN`, `SINGLE_CHOICE` | `{ value: string, text?: string }` | `value` adalah nilai pilihan; `text` diisi saat pilihan yang diambil memiliki `requires_text_input: true`. |
| `MULTIPLE_CHOICE` | `{ value: string[], text?: string }` | Array nilai pilihan. |
| `CONSENT` | `{ value: boolean }` | Boolean JSON. |
| `FILE_UPLOAD`, `IMAGE` | `{ files: string[] }` | Setiap entri adalah URL yang telah ditandatangani sebelumnya. |
| `REPEATABLE_GROUP` | `{ items: Array<{ [fieldValue]: Answer }> }` | Satu objek per pengulangan, menggunakan `value` masing-masing sub-kolom sebagai kunci dengan objek jawabannya sendiri. |
| `HEADING`, `PARAGRAPH`, `SEPARATOR` | *(tanpa kunci `answer`)* | Tata letak murni — dipertahankan di `items[]` untuk struktur. |

Item interaktif yang terlihat yang tidak pernah dijawab oleh pengguna akan dikembalikan dengan `"answer": null`.

### Visibilitas kondisional

Ketika kuesioner mendefinisikan graf (logika kondisional), hanya item pada jalur yang benar-benar diambil pengguna yang disertakan. Item yang disembunyikan oleh cabang yang tidak diikuti pengguna **tidak** akan muncul di `sections[].items` — bahkan jika item tersebut ada di templat. Bagian yang tersisa tanpa item yang terlihat akan dihilangkan sepenuhnya.

## Nilai status

Nilai `status` di tingkat respons adalah salah satu dari tiga nilai. Secara internal, status dasar (`Approved`, atau `In Review` ketika alur kerja mengharuskan peninjauan manual) digabungkan dengan aturan status kustom yang cocok menggunakan prioritas seluruh platform Declined > In Review > Approved; hasil `Declined` di tingkat kuesioner kemudian dipetakan ke `In Review` sehingga operator menangani disposisi akhir selama peninjauan.

| Status | Arti |
| - | - |
| `Not Finished` | Pengguna belum mengirimkan kuesioner. |
| `In Review` | Telah dikirimkan dan menunggu peninjauan manual (alur kerja mengharuskan peninjauan manual, atau aturan status mengeskalasi respons). |
| `Approved` | Telah dikirimkan dan diterima. |

## Peringatan

Kuesioner memunculkan satu kode peringatan, yang dihasilkan saat **aturan status kustom** yang dikonfigurasi pada node kuesioner cocok dengan sebuah jawaban:

| Tag | Deskripsi |
| - | - |
| `CUSTOM_STATUS_RULE_TRIGGERED` | Aturan status alur kerja mengevaluasi jawaban kuesioner dan mengubah (atau mengonfirmasi) status fitur. |

`additional_data` pada peringatan membawa `field`, `operator`, `rule_value`, `actual_value`, `target_status`, dan `score` saat aturan tersebut menentukannya. `log_type`-nya mengikuti status target aturan: `error` untuk Declined, `warning` untuk In Review, `information` untuk status lainnya.

Tidak seperti fitur lainnya, entri kuesioner tidak menyematkan array `warnings[]` — log aturan yang terpicu dicatat pada sesi di bawah `feature: "QUESTIONNAIRE"` dan muncul di layar peninjauan Console (lihat juga [daftar peringatan Verifikasi Bisnis](https://docs.didit.me/id/business-verification/warnings.md#kuesioner); kode yang sama berlaku untuk sesi KYC).

## Contoh — Kuesioner sumber dana

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

## Contoh — Belum selesai

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

Ketika pengguna telah mencapai langkah kuesioner tetapi belum mengirimkan jawaban, respons dikembalikan dengan `status: "Not Finished"` dan `"answer": null` pada setiap item yang terlihat. Sesi yang tidak pernah mencapai langkah tersebut tidak menghasilkan entri sama sekali — `questionnaire_responses` tetap bernilai `null` ketika tidak ada instans.

## Catatan

* **URL file kedaluwarsa.** Entri dalam `answer.files` adalah URL yang telah ditandatangani sebelumnya (masa berlaku default 4 jam). Panggil ulang endpoint keputusan saat Anda memerlukan URL baru.
* **Lokalisasi.** Item `title`, `description`, `placeholder`, pilihan `label`, serta bagian `title`/`description` dikembalikan dalam bahasa Inggris jika kuesioner mendukungnya, jika tidak, dalam `default_language` kuesioner. Nilai `value` dari sebuah pilihan tetap stabil di seluruh bahasa sehingga Anda dapat mendasarkan logika bisnis padanya dengan aman.
* **`description` item adalah teks bantuan untuk elemen.** Item apa pun dapat memilikinya, termasuk pertanyaan, dan bernilai `null` jika tidak diatur. `SEPARATOR` tidak pernah memilikinya.

## Terkait

> [card] [Gambaran umum Kuesioner](https://docs.didit.me/id/core-technology/questionnaires/overview.md)
>
> Cara menyusun, membuat versi, dan melampirkan kuesioner ke alur kerja.

> [card] [Model data — Respons kuesioner](https://docs.didit.me/id/reference/data-models.md#respons-kuesioner)
>
> Skema kanonis kolom demi kolom untuk objek ini.

> [card] [Ambil sesi](https://docs.didit.me/id/sessions-api/retrieve-session.md)
>
> Referensi endpoint untuk payload keputusan V3.


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