{"info":{"_postman_id":"36f227fd-3376-4362-be2e-37650b4510e8","name":"Survey Engine","description":"<html><head></head><body><p><strong>Version:</strong> 1.2.0</p>\n<p>The <strong>Survey Engine</strong> (<code>survey-builder-api</code>) is the backend for reward-based surveys:</p>\n<ul>\n<li>The <strong>Builder Portal / dashboard</strong> uses the <code>Dashboard</code> endpoints to create questions, assemble them into surveys, and run them through a maker/checker approval process.</li>\n<li>The <strong>campaign manager</strong> (<code>promotion-service-api</code>) creates a <strong>Survey campaign</strong> that points at an approved survey and issues <strong>survey coupons</strong> to eligible customers.</li>\n<li>The <strong>mobile app</strong> uses the <code>Mobile</code> endpoints to show the survey to a customer and record their answers. When the customer finishes, the Survey Engine tells promotion-service-api to <strong>assign</strong> the coupon (reward granted) or <strong>delete</strong> it (reward forfeited).</li>\n</ul>\n<p>Questions are reusable: a question is created once in the <strong>Question Bank</strong> and can then be used in any number of surveys.</p>\n<hr>\n<h2 id=\"key-concepts\">Key concepts</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Term</th>\n<th>Meaning</th>\n<th>Owned by</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Question</td>\n<td>One reusable question: binary, free text, single or multiple selection, or an information screen</td>\n<td>Survey Engine</td>\n</tr>\n<tr>\n<td>Question option</td>\n<td>One answer choice on a selection question. It has its own UUID, which the mobile app sends back when answering</td>\n<td>Survey Engine</td>\n</tr>\n<tr>\n<td>Survey</td>\n<td>An ordered list of approved questions, with a name and banner image</td>\n<td>Survey Engine</td>\n</tr>\n<tr>\n<td>Survey campaign</td>\n<td>A promotion-service-api campaign of type <code>Survey</code> whose external URL / <code>url</code> field holds the <strong>survey ID</strong></td>\n<td>promotion-service-api</td>\n</tr>\n<tr>\n<td>Survey coupon</td>\n<td>The customer's entry in a survey campaign. It holds the reward value (<code>offerValue</code>) and a status (<code>ELIGIBLE</code> → <code>ASSIGNED</code> / <code>DELETED</code>)</td>\n<td>promotion-service-api</td>\n</tr>\n<tr>\n<td>Activity</td>\n<td>What the customer sees in the app: a survey campaign + its coupon + the survey</td>\n<td>Both</td>\n</tr>\n<tr>\n<td>Sequence ID</td>\n<td>A human-friendly ID. Questions use <code>&lt;type prefix&gt;-&lt;6 digits&gt;</code> (B-000004, F-, S-, M-, I-). Surveys use 3 digits (007)</td>\n<td>Survey Engine</td>\n</tr>\n</tbody>\n</table>\n</div><hr>\n<h2 id=\"conventions\">Conventions</h2>\n<ul>\n<li><strong>JSON is snake_case</strong> in both requests and responses (e.g. <code>question_type</code>, <code>is_submitted</code>). promotion-service-api uses camelCase, which matters if you compare the two.</li>\n<li><strong>IDs</strong> of questions, options, surveys and answers are UUID strings. <code>campaign_id</code> is a number (the promotion-service-api campaign ID).</li>\n<li><strong><code>customer_id</code></strong> is the customer's <strong>wallet ID</strong>, i.e. their MSISDN, e.g. <code>64211234567</code>. It must be the same value promotion-service-api uses as <code>walletId</code>.</li>\n<li><strong>Timestamps</strong> (<code>created_date</code>, <code>updated_date</code>) are epoch milliseconds. <code>deleted_at</code> is a <code>\"yyyy-MM-dd HH:mm:ss\"</code> string.</li>\n<li><strong>Deleting is soft.</strong> Deleted questions and surveys are archived (they appear under <code>type=ARCHIVED</code>). Editing an archived item restores it.</li>\n<li><strong>Images</strong> live in S3 and are served by the <code>.../images/:name</code> endpoints. Upload, then reference the file name (see the Upload File requests).</li>\n</ul>\n<h2 id=\"collection-variables\">Collection variables</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Variable</th>\n<th>Used for</th>\n<th>Example</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>base_url</td>\n<td>Root of the <strong>Mobile</strong> endpoints: the gateway's <code>/survey/api</code> route. Set it on a Postman Environment to switch environments (local dev: <code>http://localhost:19422</code>)</td>\n<td><a href=\"https://gateway.youtap-test.net/survey/api\">https://gateway.youtap-test.net/survey/api</a></td>\n</tr>\n<tr>\n<td>dashboard_base_url</td>\n<td>Root of the <strong>Dashboard</strong> endpoints: the gateway's <code>/survey/sso</code> route (Azure AD sign-in). Local dev: <code>http://localhost:19422</code></td>\n<td><a href=\"https://gateway.test.youtap.systems/survey/sso\">https://gateway.test.youtap.systems/survey/sso</a></td>\n</tr>\n<tr>\n<td>question_id</td>\n<td>Question Bank requests. Set automatically by <strong>Question Bank &gt; Create</strong></td>\n<td>3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90</td>\n</tr>\n<tr>\n<td>survey_id</td>\n<td>Survey and Mobile requests. Set automatically by <strong>Survey &gt; Create</strong></td>\n<td>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</td>\n</tr>\n<tr>\n<td>customer_id</td>\n<td>Mobile requests: the customer's wallet ID (MSISDN)</td>\n<td>64211234567</td>\n</tr>\n<tr>\n<td>campaign_id</td>\n<td>Mobile requests: the promotion-service-api Survey campaign ID</td>\n<td>5001</td>\n</tr>\n<tr>\n<td>customer_password</td>\n<td>Get Customer Token: the code the customer logs in with</td>\n<td>(set it yourself)</td>\n</tr>\n<tr>\n<td>customer_token</td>\n<td>Mobile requests' bearer token. Set automatically by <strong>Authorization &gt; Get Customer Token</strong></td>\n<td>(set automatically)</td>\n</tr>\n<tr>\n<td>dashboard_token</td>\n<td>Dashboard requests' bearer token: an Azure AD access token copied from the portal</td>\n<td>(set it yourself)</td>\n</tr>\n<tr>\n<td>auth_url</td>\n<td>Youtap auth server used by Get Customer Token</td>\n<td><a href=\"https://auth.youtap-test.net\">https://auth.youtap-test.net</a></td>\n</tr>\n<tr>\n<td>consumer_client_id</td>\n<td>Consumer app OAuth client ID (Get Customer Token)</td>\n<td>(ask the platform team)</td>\n</tr>\n<tr>\n<td>consumer_client_secret</td>\n<td>Consumer app OAuth client secret (Get Customer Token)</td>\n<td>(ask the platform team)</td>\n</tr>\n</tbody>\n</table>\n</div><hr>\n<h2 id=\"authentication\">Authentication</h2>\n<p>On the gateway every request needs an <code>Authorization: Bearer &lt;token&gt;</code> header. Dashboard and Mobile requests go through different gateway routes, and each route takes a different kind of token:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Folder</th>\n<th>Gateway route</th>\n<th>Token</th>\n<th>Who can call it</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Dashboard</td>\n<td><code>https://gateway.test.youtap.systems/survey/sso</code> (<code>/survey/sso/...</code>)</td>\n<td>Azure AD (Microsoft Entra ID) access token from the Campaign Manager portal sign-in</td>\n<td>Users with the app role <code>Survey.Maker</code> or <code>Survey.Checker</code></td>\n</tr>\n<tr>\n<td>Mobile</td>\n<td><code>https://gateway.youtap-test.net/survey/api</code> (<code>/survey/api/...</code>)</td>\n<td>Customer token from the Youtap auth server, with the <code>consumer_ops</code> scope</td>\n<td>Only the customer the request is about: the gateway checks the customer ID against the token's MSISDN</td>\n</tr>\n</tbody>\n</table>\n</div><p>The folders already send the token: <strong>Dashboard</strong> uses <code></code> and <strong>Mobile</strong> uses <code></code> (Authorization tab, type <em>Bearer Token</em>). Local dev (<code>http://localhost:19422</code>) skips the gateway, so no token is needed there.</p>\n<h3 id=\"mobile-customer-token\">Mobile: customer token</h3>\n<ol>\n<li>Set <code>consumer_client_id</code> and <code>consumer_client_secret</code> to the consumer app's OAuth client (ask the platform team, and keep the secret in a Postman Environment or as a <em>current value</em> only, so it isn't shared with the collection).</li>\n<li>Set <code>customer_id</code> to the customer's wallet ID (MSISDN) and <code>customer_password</code> to the code the customer logs in with.</li>\n<li>Send <strong>Authorization &gt; Get Customer Token</strong>. Its test script copies <code>access_token</code> into <code>customer_token</code>.</li>\n<li>The token expires after <code>expires_in</code> seconds. When a Mobile request returns <strong>401</strong>, send Get Customer Token again.</li>\n</ol>\n<p>What the gateway checks on each Mobile request:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Request</th>\n<th>Scope</th>\n<th>Customer check</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Survey Detail</td>\n<td><code>consumer_ops</code></td>\n<td><code>customer_id</code> query parameter must be the token's MSISDN</td>\n</tr>\n<tr>\n<td>Fill Answer</td>\n<td><code>consumer_ops</code></td>\n<td><code>customer_id</code> query parameter must be the token's MSISDN</td>\n</tr>\n<tr>\n<td>Get Customer Answer List</td>\n<td><code>consumer_ops</code></td>\n<td><code>:customerId</code> path variable must be the token's MSISDN</td>\n</tr>\n<tr>\n<td>Answer Results</td>\n<td><code>consumer_ops</code></td>\n<td><code>:customerId</code> path variable must be the token's MSISDN</td>\n</tr>\n<tr>\n<td>Survey Image</td>\n<td><code>consumer_ops</code></td>\n<td>None</td>\n</tr>\n</tbody>\n</table>\n</div><p>So a customer token can only read and answer surveys for that customer.</p>\n<h3 id=\"dashboard-azure-ad-token\">Dashboard: Azure AD token</h3>\n<p>The dashboard signs in with Microsoft, so the token can't be requested from Postman with a username and password. To get one:</p>\n<ol>\n<li>Sign in to the Campaign Manager portal with an account that has the <code>Survey.Maker</code> or <code>Survey.Checker</code> role.</li>\n<li>Open the browser's developer tools, go to <strong>Network</strong>, and pick any request to <code>/survey/sso/...</code>.</li>\n<li>Copy its <code>Authorization</code> request header without the <code>Bearer </code> prefix, and paste it into <code>dashboard_token</code>.</li>\n<li>The token lasts about an hour. When a Dashboard request returns <strong>401</strong>, copy a new one.</li>\n</ol>\n<p>The gateway only checks that the user has <strong>one</strong> of the two roles. Which actions a maker or a checker may take (for example, only a checker approves) is enforced by the portal, not by the gateway or this API.</p>\n<h3 id=\"authentication-errors\">Authentication errors</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>When</th>\n<th>Body</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>401</td>\n<td>The <code>Authorization</code> header is missing, or the token is expired or invalid</td>\n<td>None</td>\n</tr>\n<tr>\n<td>403</td>\n<td>The token is valid but not allowed here: wrong scope or role, a customer ID that isn't the token's MSISDN, or a path the route doesn't allow (for example, a Dashboard path sent to <code>/survey/api</code>)</td>\n<td>Problem with <code>title</code> <em>Forbidden resource</em>, <code>errorKey</code> <code>forbidden</code> and the reason in <code>detail</code></td>\n</tr>\n</tbody>\n</table>\n</div><hr>\n<h2 id=\"lifecycle-status-and-approval-maker--checker\">Lifecycle: status and approval (maker / checker)</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>ID</th>\n<th>Meaning</th>\n<th>How it gets there</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>DRAFTED</td>\n<td>1</td>\n<td>Saved but not submitted</td>\n<td>Create/Edit with <code>is_submitted: false</code></td>\n</tr>\n<tr>\n<td>UNCHECKED</td>\n<td>2</td>\n<td>Waiting for a checker</td>\n<td>Create/Edit with <code>is_submitted: true</code></td>\n</tr>\n<tr>\n<td>APPROVED</td>\n<td>3</td>\n<td>Live and usable</td>\n<td>Submit Approval with <code>approval_status: true</code></td>\n</tr>\n<tr>\n<td>REJECTED</td>\n<td>4</td>\n<td>Rejected by the checker (<code>rejection_reason</code> says why)</td>\n<td>Submit Approval with <code>approval_status: false</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>Typical path: Create (DRAFTED) → Edit with <code>is_submitted: true</code> (UNCHECKED) → Submit Approval (APPROVED or REJECTED). A REJECTED item is fixed with Edit and resubmitted. Editing an APPROVED item sends it back to DRAFTED or UNCHECKED.</p>\n<ul>\n<li>A <strong>maker</strong> (role <code>Survey.Maker</code>) creates and edits items and submits them by sending <code>is_submitted: true</code>.</li>\n<li>A <strong>checker</strong> (role <code>Survey.Checker</code>) approves or rejects UNCHECKED items with <strong>Submit Approval</strong>.</li>\n<li><strong>Only APPROVED questions</strong> can be added to a survey. <strong>Only APPROVED surveys</strong> can be opened on mobile.</li>\n</ul>\n<hr>\n<h2 id=\"end-to-end-flow\">End-to-end flow</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>#</th>\n<th>Who / where</th>\n<th>Request</th>\n<th>What happens</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>Maker, dashboard</td>\n<td>Question Bank &gt; Upload File (optional), then Create with <code>is_submitted: true</code></td>\n<td>Questions become UNCHECKED</td>\n</tr>\n<tr>\n<td>2</td>\n<td>Checker, dashboard</td>\n<td>Question Bank &gt; Submit Approval</td>\n<td>Questions become APPROVED</td>\n</tr>\n<tr>\n<td>3</td>\n<td>Maker, dashboard</td>\n<td>Survey &gt; Upload File (optional), then Create with the approved <code>question_id</code>s</td>\n<td>Survey becomes UNCHECKED</td>\n</tr>\n<tr>\n<td>4</td>\n<td>Checker, dashboard</td>\n<td>Survey &gt; Submit Approval</td>\n<td>Survey becomes APPROVED, and the answer statistics counters are created</td>\n</tr>\n<tr>\n<td>5</td>\n<td>Campaign manager</td>\n<td>promotion-service-api (external)</td>\n<td>A campaign of type <strong>Survey</strong> is created with its <code>url</code> set to the <strong>survey ID</strong>. Eligible customers receive an <strong>ELIGIBLE</strong> coupon</td>\n</tr>\n<tr>\n<td>6</td>\n<td>Mobile app</td>\n<td>promotion-service-api <code>GET /customers/{walletId}/coupons</code> (external)</td>\n<td>The app lists the customer's coupons. A survey coupon has <code>campaignType: \"SURVEY\"</code>, its <code>campaignId</code>, and the survey ID in <code>launchUrl</code> (and <code>couponOfferMessage[].surveyId</code>)</td>\n</tr>\n<tr>\n<td>7</td>\n<td>Mobile app</td>\n<td>Mobile &gt; Survey Detail</td>\n<td>Checks the customer holds a coupon for that campaign, then returns the questions</td>\n</tr>\n<tr>\n<td>8</td>\n<td>Mobile app</td>\n<td>Mobile &gt; Survey Image</td>\n<td>Loads banner and option images</td>\n</tr>\n<tr>\n<td>9</td>\n<td>Mobile app</td>\n<td>Mobile &gt; Fill Answer (once per question)</td>\n<td>Saves each answer. After the <strong>last</strong> question, it assigns or deletes the coupon in promotion-service-api</td>\n</tr>\n<tr>\n<td>10</td>\n<td>Mobile app</td>\n<td>Mobile &gt; Get Customer Answer List / Answer Results</td>\n<td>Resume progress, show results and percentages</td>\n</tr>\n</tbody>\n</table>\n</div><hr>\n<h2 id=\"survey-coupons-promotion-service-api-integration\">Survey coupons (promotion-service-api integration)</h2>\n<p>The reward side of a survey lives in <strong>promotion-service-api</strong>. The Survey Engine never stores reward amounts. It only links answers to a <code>campaign_id</code> and tells promotion-service-api when the customer has finished.</p>\n<h3 id=\"how-a-survey-is-linked-to-a-campaign\">How a survey is linked to a campaign</h3>\n<ul>\n<li>In promotion-service-api, a <strong>Survey campaign</strong> is a coupon campaign whose <code>campaign_type</code> is <code>Survey</code> (case-insensitive, often stored as <code>SURVEY</code>).</li>\n<li>The campaign's <strong><code>url</code></strong> field (stored in <code>external_campaign_details.url</code>) holds the <strong>Survey Engine survey ID</strong>, e.g. <code>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</code>. The same value is exposed as:<ul>\n<li><code>externalUrl</code> on the integration endpoint below</li>\n<li><code>launchUrl</code> on the customer coupon endpoints (<code>GET /customers/{walletId}/coupons</code>)</li>\n<li><code>surveyId</code> in <code>couponOfferMessage[]</code> (when the campaign has offer messages)</li>\n</ul>\n</li>\n<li>Customers who meet the campaign's eligibility rules get a coupon with status <strong>ELIGIBLE</strong> and an <code>offerValue</code> (the reward). Survey campaigns are never auto-assigned; the Survey Engine does the assignment when the survey is completed.</li>\n</ul>\n<p>Example coupon, as the app sees it from promotion-service-api:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n    \"id\": 50001,\n    \"campaignId\": 5001,\n    \"campaignType\": \"SURVEY\",\n    \"status\": \"ELIGIBLE\",\n    \"offerValue\": 5.00,\n    \"launchUrl\": \"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37\",\n    \"couponOfferMessage\": [{ \"couponCampaignId\": 5001, \"surveyId\": \"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37\" }]\n}\n</code></pre>\n<p>The app then calls <strong>Survey Detail</strong> with <code>:id = launchUrl</code>, <code>customer_id = walletId</code> and <code>campaign_id = campaignId</code>.</p>\n<h3 id=\"coupon-lifecycle\">Coupon lifecycle</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Coupon status</th>\n<th>Meaning for a survey</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>ELIGIBLE</td>\n<td>The customer may take the survey. The reward is shown as potential balance</td>\n</tr>\n<tr>\n<td>ASSIGNED</td>\n<td>The survey was completed with no skipped questions. <code>offerValue</code> moves to the customer's available balance and a <code>WALLET_BALANCE_EARNED</code> business event is published</td>\n</tr>\n<tr>\n<td>DELETED</td>\n<td>The survey was finished but at least one question was answered with <code>SKIP_REWARD</code>. No reward is given, and the coupon (and the Activity) disappears from the app</td>\n</tr>\n<tr>\n<td>EXPIRED</td>\n<td>The campaign end date passed before completion (set by promotion-service-api's expiry job)</td>\n</tr>\n<tr>\n<td>REDEEMED</td>\n<td>An ASSIGNED reward was later spent. Not used by the Survey Engine</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"server-to-server-calls-made-by-the-survey-engine\">Server-to-server calls made by the Survey Engine</h3>\n<p>Both calls go to <code>{promotion-service.url}/integration/customers/{customerId}/campaign/{campaignId}</code>, where <code>customerId</code> is the <strong>wallet ID</strong>. They are configured under <code>promotion-service</code> in <code>application.yml</code>. promotion-service-api JSON is <strong>camelCase</strong>.</p>\n<p><strong>1. Eligibility check: <code>GET</code>.</strong> This is made by <strong>Survey Detail</strong>.</p>\n<p>promotion-service-api returns the campaign, customer and coupon:</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n    \"campaign\": { \"id\": 5001, \"name\": \"Coffee survey\", \"status\": \"ACTIVE\", \"campaignType\": \"SURVEY\", \"couponValue\": 5.00, \"externalUrl\": \"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37\" },\n    \"customer\": { \"id\": 123, \"walletId\": \"64211234567\", \"status\": \"ACTIVE\", \"availableBalance\": 0.00 },\n    \"coupon\":   { \"id\": 50001, \"status\": \"ELIGIBLE\", \"offerValue\": 5.00, \"endDate\": \"2026-12-31\" }\n}\n</code></pre>\n<ul>\n<li><strong>404 (customer not found, or no coupon for that campaign):</strong> Survey Detail returns 400 <em>Survey is not accessible</em>, with promotion-service-api's message as <code>detail</code>.</li>\n<li><strong>200:</strong> the Survey Engine checks that <code>campaign.id == campaign_id</code>, <code>campaign.status</code> is <code>ACTIVE</code> and <code>coupon.status</code> is <code>ELIGIBLE</code>. Otherwise Survey Detail returns 400 <em>Survey is not accessible</em>.</li>\n</ul>\n<p>promotion-service-api does <strong>not</strong> filter by coupon status here, which is why the Survey Engine checks it: a customer whose coupon is already EXPIRED, ASSIGNED or DELETED cannot open the survey.</p>\n<p><strong>2. Completion: <code>POST</code>.</strong> This is made by <strong>Fill Answer</strong> once every question has a final answer.</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{ \"status\": \"ASSIGNED\", \"initiator\": \"survey-builder\" }\n</code></pre>\n<p><code>status</code> is <code>ASSIGNED</code> if every answer is <code>COMPLETED</code>, or <code>DELETED</code> if any answer is <code>SKIP_REWARD</code>. <code>initiator</code> comes from config and is only used for audit (the coupon's <code>modifiedBy</code>, coupon history and business events).</p>\n<p>promotion-service-api checks that:</p>\n<ul>\n<li>the coupon is still <strong>ELIGIBLE</strong>: otherwise 400 <em>coupon is already assigned</em> or <em>coupon status is not eligible</em>;</li>\n<li>the campaign is <strong>ACTIVE</strong>: otherwise 400 <em>campaign not active</em>.</li>\n</ul>\n<p><strong>The call is not idempotent</strong> on the promotion-service-api side, so the Survey Engine makes it safe to retry. If the POST is rejected or its response is lost, it re-reads the coupon: if the coupon already has the requested status, the answer is saved as normal. Otherwise Fill Answer returns <strong>502</strong> <em>Survey could not be completed</em> and <strong>rolls back</strong> the answer it was saving, so the customer can retry the last question once the problem is fixed, e.g. a promotion-service-api outage.</p>\n<h3 id=\"whitelisted-test-customers\">Whitelisted test customers</h3>\n<p>Wallet IDs listed in <code>promotion-service.whitelisted-customer-ids</code> skip the eligibility and \"already filled\" checks in <strong>Survey Detail</strong>, so testers can open any approved survey repeatedly.</p>\n<p>Fill Answer also <strong>skips</strong> the completion <code>POST</code> for them, so their answers are saved but no coupon is assigned or deleted.</p>\n<hr>\n<h2 id=\"errors\">Errors</h2>\n<p>Errors use an RFC 7807 Problem body (<code>Content-Type: application/problem+json</code>):</p>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{\n    \"type\": \"\",\n    \"title\": \"Missing required body field\",\n    \"detail\": \"Question name should not be longer than 45 characters.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}\n</code></pre>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>type</td>\n<td>Unused (empty)</td>\n</tr>\n<tr>\n<td>title</td>\n<td>Short name of the error</td>\n</tr>\n<tr>\n<td>detail</td>\n<td>Specific explanation, safe to show to a dashboard user</td>\n</tr>\n<tr>\n<td>status</td>\n<td>HTTP status code</td>\n</tr>\n<tr>\n<td>instance</td>\n<td>Unused (empty)</td>\n</tr>\n<tr>\n<td>errorKey</td>\n<td><code>bad_request</code>, <code>resource_not_found</code>, <code>bad_gateway</code>, <code>BAD_REQUEST</code> or <code>INTERNAL_SERVER_ERROR</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>Things to know:</p>\n<ul>\n<li><strong>404</strong> with title <em>Resource Not Found</em> is used for unknown question, survey or option IDs, missing images, archived items in Submit Approval, and surveys that are not APPROVED on mobile.</li>\n<li><strong>400</strong> <em>Invalid parameter</em> is returned for a missing or non-numeric query parameter such as <code>campaign_id</code>.</li>\n<li><strong>502</strong> <em>Survey could not be completed</em> means promotion-service-api rejected or failed the coupon completion call. Its message is in <code>detail</code>.</li>\n<li><strong>500</strong> <em>Unexpected error</em> means an unexpected server fault.</li>\n<li><strong>401</strong> and <strong>403</strong> come from the API gateway, not this API. See <em>Authentication</em>.</li>\n</ul>\n</body></html>","schema":"https://schema.getpostman.com/json/collection/v2.0.0/collection.json","toc":[],"owner":"2765989","collectionId":"36f227fd-3376-4362-be2e-37650b4510e8","publishedId":"2sBYHSzgRM","public":true,"customColor":{"top-bar":"FFFFFF","right-sidebar":"303030","highlight":"FF6C37"},"publishDate":"2026-10-22T00:39:23.000Z"},"item":[{"name":"Authorization","item":[{"name":"Get Customer Token","event":[{"listen":"test","script":{"type":"text/javascript","exec":["if (pm.response.code === 200) {","    pm.collectionVariables.set(\"customer_token\", pm.response.json().access_token);","}"],"id":"371e7b99-f577-4071-b327-7205a918c6e1"}}],"id":"854b3dfb-c20f-4648-88fa-0dbf1ba82a9e","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"auth":{"type":"basic","basic":{"basicConfig":[{"key":"username","value":""},{"key":"password","value":""}]},"isInherited":false},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"password","type":"text","description":"<p>Always <code>password</code></p>\n"},{"key":"username","value":"64211234567","type":"text","description":"<p>The customer's wallet ID (MSISDN). Must be the same customer as the Mobile requests' <code>customer_id</code></p>\n"},{"key":"password","value":"","type":"text","description":"<p>The code the customer logs in with</p>\n"}]},"url":"https://auth.youtap-test.net/uaa/oauth/token","description":"<p>Logs a customer in to the Youtap auth server and returns a bearer token for the <strong>Mobile</strong> requests. This is the same call the mobile app makes when the customer logs in.</p>\n<ul>\n<li><strong>Client authentication:</strong> HTTP Basic with the consumer app's OAuth client (<code>consumer_client_id</code> / <code>consumer_client_secret</code>), set on this request's Authorization tab.</li>\n<li><strong>Body:</strong> <code>application/x-www-form-urlencoded</code> with <code>grant_type=password</code>, the customer's wallet ID as <code>username</code> and their login code as <code>password</code>.</li>\n<li><strong>Test script:</strong> on 200, copies <code>access_token</code> into the <code>customer_token</code> collection variable, which the Mobile folder sends.</li>\n</ul>\n<p>The token's scope includes <code>consumer_ops</code> and its MSISDN is the customer's, so it only works for that customer's Mobile requests.</p>\n<p><strong>Responses</strong></p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>When</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>200</td>\n<td>Logged in. <code>access_token</code> is the bearer token; it expires after <code>expires_in</code> seconds. Use <code>refresh_token</code> with <code>grant_type=refresh_token</code> to renew it, or call this again</td>\n</tr>\n<tr>\n<td>400 <code>invalid_grant</code></td>\n<td>Wrong wallet ID or login code</td>\n</tr>\n<tr>\n<td>401 <code>invalid_client</code></td>\n<td>Wrong client ID or secret</td>\n</tr>\n</tbody>\n</table>\n</div>","urlObject":{"path":["uaa","oauth","token"],"host":["https://auth.youtap-test.net"],"query":[],"variable":[]}},"response":[{"id":"4bffd248-5a3b-43ba-8481-bd58575157e0","name":"Logged in","originalRequest":{"auth":{"type":"basic","basic":{"username":"","password":""}},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"password","type":"text","description":"Always `password`"},{"key":"username","value":"64211234567","type":"text","description":"The customer's wallet ID (MSISDN). Must be the same customer as the Mobile requests' `customer_id`"},{"key":"password","value":"","type":"text","description":"The code the customer logs in with"}]},"url":"https://auth.youtap-test.net/uaa/oauth/token"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json;charset=UTF-8"}],"cookie":[],"responseTime":null,"body":"{\n    \"access_token\": \"eyJhbGciOiJSUzI1NiJ9.<payload>.<signature>\",\n    \"token_type\": \"bearer\",\n    \"refresh_token\": \"eyJhbGciOiJSUzI1NiJ9.<payload>.<signature>\",\n    \"expires_in\": 299,\n    \"scope\": \"consumer_ops\"\n}"},{"id":"bd37a7d6-8855-4879-bb51-6a9c5e401cbc","name":"Wrong login code","originalRequest":{"auth":{"type":"basic","basic":{"username":"","password":""}},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"password","type":"text","description":"Always `password`"},{"key":"username","value":"64211234567","type":"text","description":"The customer's wallet ID (MSISDN). Must be the same customer as the Mobile requests' `customer_id`"},{"key":"password","value":"","type":"text","description":"The code the customer logs in with"}]},"url":"https://auth.youtap-test.net/uaa/oauth/token"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json;charset=UTF-8"}],"cookie":[],"responseTime":null,"body":"{\n    \"error\": \"invalid_grant\",\n    \"error_description\": \"Bad credentials\"\n}"},{"id":"a91c6155-a615-4617-899d-e8539664bbc3","name":"Wrong client secret","originalRequest":{"auth":{"type":"basic","basic":{"username":"","password":""}},"method":"POST","header":[],"body":{"mode":"urlencoded","urlencoded":[{"key":"grant_type","value":"password","type":"text","description":"Always `password`"},{"key":"username","value":"64211234567","type":"text","description":"The customer's wallet ID (MSISDN). Must be the same customer as the Mobile requests' `customer_id`"},{"key":"password","value":"","type":"text","description":"The code the customer logs in with"}]},"url":"https://auth.youtap-test.net/uaa/oauth/token"},"status":"Unauthorized","code":401,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json;charset=UTF-8"}],"cookie":[],"responseTime":null,"body":"{\n    \"error\": \"invalid_client\"\n}"}],"_postman_id":"854b3dfb-c20f-4648-88fa-0dbf1ba82a9e"}],"id":"b3482030-82f6-4b39-a078-ead20d47e7eb","description":"<p>Gets the tokens the gateway needs. See <em>Authentication</em> in the collection description.</p>\n<p>There's no request for the Dashboard token: it's an Azure AD token, which you copy from the Campaign Manager portal into <code>dashboard_token</code>.</p>\n","_postman_id":"b3482030-82f6-4b39-a078-ead20d47e7eb"},{"name":"Dashboard","item":[{"name":"Question Bank","item":[{"name":"Upload File","id":"21843699-ace6-49eb-a84c-f495ea20e715","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PUT","header":[{"key":"Content-Type","value":"image/jpeg","description":"<p>Match the file, e.g. image/png. Any value is accepted; the bytes themselves are checked</p>\n","type":"text"}],"body":{"mode":"file","file":{"src":""}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/upload-image?file_name=coffee.jpeg&file_type=question_banner","description":"<p>Uploads an image for a question banner or answer option.</p>\n<p>Send the image as the <strong>raw binary request body</strong>. In Postman, choose Body &gt; binary and select a file. This is not multipart form data.</p>\n<h3 id=\"how-it-works\">How it works</h3>\n<ol>\n<li>The bytes are checked to be an image (PNG, JPEG or GIF), with a maximum size of <strong>150 KB</strong>.</li>\n<li>The file is stored in S3 as <strong><code>&lt;file_type&gt;_&lt;yyyyMMdd-HHmmss.SSS&gt;&lt;extension&gt;</code></strong>, e.g. <code>question_banner_20261013-093000.123.jpeg</code>. Your original file name only provides the extension.</li>\n<li>The response gives the path for <strong>Get Image</strong>.</li>\n</ol>\n<h3 id=\"linking-an-uploaded-image\">Linking an uploaded image</h3>\n<p>Upload File returns a <strong>path</strong> such as <code>/dashboard/question-banks/images/question_banner_20261013-093000.123.jpeg</code>.</p>\n<p>In create and edit requests, put <strong>only the file name</strong>, the part after the last <code>/</code> (e.g. <code>question_banner_20261013-093000.123.jpeg</code>). The API prefixes the correct images path when it returns the record. A full path or URL is also accepted: only the part after the last <code>/</code> is used when the path is returned. Use <code>\"\"</code> for \"no image\".</p>\n<h3 id=\"response-200\">Response: 200</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{ \"file_name\": \"/dashboard/question-banks/images/question_banner_20261013-093000.123.jpeg\" }\n</code></pre>\n<h3 id=\"errors\">Errors</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>title / detail</th>\n<th>Cause</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>400</td>\n<td>Invalid parameter / Invalid question image type.</td>\n<td><code>file_type</code> is not <code>question_banner</code> or <code>question_option_image</code></td>\n</tr>\n<tr>\n<td>400</td>\n<td>Invalid parameter / Image size cannot be larger than 150 KB.</td>\n<td>File too large</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Invalid parameter / Image extension is not supported</td>\n<td><code>file_name</code> has a non-image extension</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Invalid parameter / Data is not an image.</td>\n<td>Body is not a PNG, JPEG or GIF image</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Invalid parameter / Invalid filename.</td>\n<td><code>file_name</code> contains <code>/</code>, <code>\\</code> or <code>..</code></td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","question-banks","upload-image"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[{"description":{"content":"<p>Original file name. <strong>Only its extension is used</strong> (it must be an image extension such as <code>.jpeg</code>, <code>.jpg</code>, <code>.png</code> or <code>.gif</code>). Must not contain <code>/</code>, <code>\\</code> or <code>..</code></p>\n","type":"text/plain"},"key":"file_name","value":"coffee.jpeg"},{"description":{"content":"<p>What the image is for: <code>question_banner</code> (the question's <code>banner_image</code>) or <code>question_option_image</code> (an option's <code>image</code>). Lowercase, exact</p>\n","type":"text/plain"},"key":"file_type","value":"question_banner"}],"variable":[]}},"response":[{"id":"ece16d5d-7155-4f57-ac67-fcc1bd2eba3b","name":"Banner image","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"image/jpeg","type":"text","description":"Match the file, e.g. image/png. Any value is accepted; the bytes themselves are checked"}],"body":{"mode":"file","file":{}},"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/upload-image?file_name=coffee.jpeg&file_type=question_banner","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks","upload-image"],"query":[{"key":"file_name","value":"coffee.jpeg","type":"string","description":"Original file name. **Only its extension is used** (it must be an image extension such as `.jpeg`, `.jpg`, `.png` or `.gif`). Must not contain `/`, `\\` or `..`"},{"key":"file_type","value":"question_banner","type":"string","description":"What the image is for: `question_banner` (the question's `banner_image`) or `question_option_image` (an option's `image`). Lowercase, exact"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"file_name\": \"/dashboard/question-banks/images/question_banner_20261020-225927.087.jpeg\"\n}"},{"id":"51494ea0-f5b2-439f-be69-6a605ea03c40","name":"Option image","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"image/jpeg","type":"text","description":"Match the file, e.g. image/png. Any value is accepted; the bytes themselves are checked"}],"body":{"mode":"file","file":{}},"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/upload-image?file_name=coffee-cup.png&file_type=question_option_image","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks","upload-image"],"query":[{"key":"file_name","value":"coffee-cup.png","type":"string","description":"Original file name. **Only its extension is used** (it must be an image extension such as `.jpeg`, `.jpg`, `.png` or `.gif`). Must not contain `/`, `\\` or `..`"},{"key":"file_type","value":"question_option_image","type":"string","description":"What the image is for: `question_banner` (the question's `banner_image`) or `question_option_image` (an option's `image`). Lowercase, exact"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"file_name\": \"/dashboard/question-banks/images/question_option_image_20261020-225927.100.png\"\n}"},{"id":"62e66187-70c3-4e88-9f0f-8c5416d95637","name":"400 - too large","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"image/jpeg","type":"text","description":"Match the file, e.g. image/png. Any value is accepted; the bytes themselves are checked"}],"body":{"mode":"file","file":{}},"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/upload-image?file_name=huge.jpeg&file_type=question_banner","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks","upload-image"],"query":[{"key":"file_name","value":"huge.jpeg","type":"string","description":"Original file name. **Only its extension is used** (it must be an image extension such as `.jpeg`, `.jpg`, `.png` or `.gif`). Must not contain `/`, `\\` or `..`"},{"key":"file_type","value":"question_banner","type":"string","description":"What the image is for: `question_banner` (the question's `banner_image`) or `question_option_image` (an option's `image`). Lowercase, exact"}]}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Invalid parameter\",\n    \"detail\": \"Image size cannot be larger than 150 KB.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"},{"id":"d23c8f2b-d76d-4323-96be-d5c901c83691","name":"400 - not an image","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"image/jpeg","type":"text","description":"Match the file, e.g. image/png. Any value is accepted; the bytes themselves are checked"}],"body":{"mode":"file","file":{}},"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/upload-image?file_name=notes.jpeg&file_type=question_banner","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks","upload-image"],"query":[{"key":"file_name","value":"notes.jpeg","type":"string","description":"Original file name. **Only its extension is used** (it must be an image extension such as `.jpeg`, `.jpg`, `.png` or `.gif`). Must not contain `/`, `\\` or `..`"},{"key":"file_type","value":"question_banner","type":"string","description":"What the image is for: `question_banner` (the question's `banner_image`) or `question_option_image` (an option's `image`). Lowercase, exact"}]}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Invalid parameter\",\n    \"detail\": \"Data is not an image.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"21843699-ace6-49eb-a84c-f495ea20e715"},{"name":"Create","event":[{"listen":"test","script":{"type":"text/javascript","exec":["// Stores the new ID so the other requests in this collection can use it","if (pm.response.code === 200) {","    pm.collectionVariables.set('question_id', pm.response.json().id);","}"],"id":"874fb026-3938-46e2-844c-ba4524eb57b0"}}],"id":"b44e7b4f-146a-4a0e-b143-6aaba0b8c852","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"What do you drink in the morning?\",\n    \"question_type\": 3,\n    \"banner_image\": \"question_banner_20261013-093000.123.jpeg\",\n    \"information\": null,\n    \"show_feedback\": true,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Coffee\",\n            \"image\": \"question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\"\n        },\n        {\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"answer\": \"Juice\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Fruity!\"\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/create","description":"<p>Creates a new question in the Question Bank.</p>\n<ul>\n<li><code>is_submitted: true</code> creates it as <strong>UNCHECKED</strong> (sent straight to a checker).</li>\n<li><code>is_submitted: false</code> saves it as a <strong>DRAFTED</strong> draft.</li>\n</ul>\n<p>A checker must then approve it (<strong>Submit Approval</strong>) before it can be used in a survey. The test script saves the new <code>id</code> into the <code>question_id</code> collection variable.</p>\n<h3 id=\"body\">Body</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>title</td>\n<td>string</td>\n<td>Yes</td>\n<td>The question text. Max 45 characters</td>\n</tr>\n<tr>\n<td>question_type</td>\n<td>number</td>\n<td>Yes</td>\n<td>1 BINARY, 2 FREE_TEXT, 3 SINGLE_SELECTION, 4 MULTIPLE_SELECTION, 5 INFORMATION</td>\n</tr>\n<tr>\n<td>banner_image</td>\n<td>string</td>\n<td>Yes</td>\n<td>File name from <strong>Upload File</strong> (<code>file_type=question_banner</code>), or <code>\"\"</code> for none</td>\n</tr>\n<tr>\n<td>information</td>\n<td>string / null</td>\n<td>Type 5 only</td>\n<td>Text shown on an INFORMATION screen. Required and non-empty for type 5</td>\n</tr>\n<tr>\n<td>show_feedback</td>\n<td>boolean</td>\n<td>Yes</td>\n<td>Whether the app shows feedback after answering</td>\n</tr>\n<tr>\n<td>free_text_feedback</td>\n<td>string / null</td>\n<td>Type 2 + show_feedback</td>\n<td>Feedback shown after a free text answer. Max 340</td>\n</tr>\n<tr>\n<td>options</td>\n<td>array / null</td>\n<td>Types 1, 3, 4</td>\n<td>Answer choices: exactly 2 for BINARY, 2-10 for SINGLE/MULTIPLE. Must be <code>null</code> or <code>[]</code> for types 2 and 5</td>\n</tr>\n<tr>\n<td>options[].answer</td>\n<td>string</td>\n<td>Yes</td>\n<td>Choice text. Max 22 characters</td>\n</tr>\n<tr>\n<td>options[].image</td>\n<td>string</td>\n<td>Yes</td>\n<td>File name from <strong>Upload File</strong> (<code>file_type=question_option_image</code>), or <code>\"\"</code></td>\n</tr>\n<tr>\n<td>options[].answer_feedback</td>\n<td>string / null</td>\n<td>When <code>show_feedback</code></td>\n<td>Feedback for this choice. Must be non-empty when <code>show_feedback</code> is true. <code>null</code> or omitted is stored as <code>\"\"</code></td>\n</tr>\n<tr>\n<td>is_submitted</td>\n<td>boolean</td>\n<td>No (default false)</td>\n<td><code>true</code> gives UNCHECKED, <code>false</code> gives DRAFTED</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"linking-an-uploaded-image\">Linking an uploaded image</h3>\n<p>Upload File returns a <strong>path</strong> such as <code>/dashboard/question-banks/images/question_banner_20261013-093000.123.jpeg</code>.</p>\n<p>In create and edit requests, put <strong>only the file name</strong>, the part after the last <code>/</code> (e.g. <code>question_banner_20261013-093000.123.jpeg</code>). The API prefixes the correct images path when it returns the record. A full path or URL is also accepted: only the part after the last <code>/</code> is used when the path is returned. Use <code>\"\"</code> for \"no image\".</p>\n<h3 id=\"response-200\">Response: 200</h3>\n<p>The created question, with option <code>id</code>s assigned.</p>\n<ul>\n<li><code>question_type</code> is returned as its <strong>name</strong> (e.g. <code>SINGLE_SELECTION</code>).</li>\n<li>Image fields are returned as full image paths.</li>\n<li><code>sequence_id</code> is generated (e.g. <code>S-000012</code>) but is <strong>not</strong> in this response. Use <strong>Get Details</strong> to see it.</li>\n</ul>\n<h3 id=\"errors\">Errors</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>title</th>\n<th>detail</th>\n<th>Cause</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>400</td>\n<td>Missing required body field</td>\n<td>Question name should not be longer than 45 characters.</td>\n<td><code>title</code> too long</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field</td>\n<td>Answer should not be longer than 22 characters.</td>\n<td>An option <code>answer</code> is too long</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field</td>\n<td>Answer feedback is required.</td>\n<td><code>show_feedback</code> is true and an option has no <code>answer_feedback</code></td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field</td>\n<td>Answer feedback should not be longer than 340 characters.</td>\n<td><code>free_text_feedback</code> too long</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field</td>\n<td>Invalid question type.</td>\n<td><code>question_type</code> is not 1-5</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field</td>\n<td>Required field: ...</td>\n<td>Body missing, or a required field (e.g. <code>banner_image</code>) missing</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Invalid parameter</td>\n<td>Options count is invalid.</td>\n<td>Wrong number of <code>options</code> for the type</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Invalid parameters</td>\n<td>Empty information field provided.</td>\n<td>Type 5 without <code>information</code></td>\n</tr>\n<tr>\n<td>400</td>\n<td>Invalid parameters</td>\n<td>Free text feedback not provided.</td>\n<td>Type 2 with <code>show_feedback</code> true and no <code>free_text_feedback</code></td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","question-banks","create"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[]}},"response":[{"id":"6faeb7e2-2718-4182-857f-a0bf751185a0","name":"Single selection (submitted for approval)","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"What do you drink in the morning?\",\n    \"question_type\": 3,\n    \"banner_image\": \"question_banner_20261013-093000.123.jpeg\",\n    \"information\": null,\n    \"show_feedback\": true,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Coffee\",\n            \"image\": \"question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\"\n        },\n        {\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"answer\": \"Juice\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Fruity!\"\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/create"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"8ca091e8-e3d9-4ea4-a53c-2f4585a77274\",\n    \"title\": \"What do you drink in the morning?\",\n    \"banner_image\": \"/dashboard/question-banks/images/question_banner_20261013-093000.123.jpeg\",\n    \"question_type\": \"SINGLE_SELECTION\",\n    \"information\": \"\",\n    \"free_text_feedback\": null,\n    \"status\": \"UNCHECKED\",\n    \"created_date\": 1792537162223,\n    \"updated_date\": 1792537162223,\n    \"options\": [\n        {\n            \"id\": \"1764dd4b-75be-4d05-aa7c-cd22ce8514bc\",\n            \"answer\": \"Coffee\",\n            \"image\": \"/dashboard/question-banks/images/question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\"\n        },\n        {\n            \"id\": \"441ef0e3-b7c8-4f60-8116-5778dc41cc90\",\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"id\": \"f47254ca-9ecc-48b5-aa07-ca4e1d2dadf4\",\n            \"answer\": \"Juice\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Fruity!\"\n        }\n    ]\n}"},{"id":"680d02f0-b5c8-4007-b0f4-458a14312e1f","name":"Binary (saved as draft)","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"Do you own a smartphone?\",\n    \"question_type\": 1,\n    \"banner_image\": \"\",\n    \"information\": null,\n    \"show_feedback\": false,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Yes\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"answer\": \"No\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        }\n    ],\n    \"is_submitted\": false\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/create"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"930c2af3-0a42-43fc-b186-080f9a0c6ef5\",\n    \"title\": \"Do you own a smartphone?\",\n    \"banner_image\": \"\",\n    \"question_type\": \"BINARY\",\n    \"information\": \"\",\n    \"free_text_feedback\": null,\n    \"status\": \"DRAFTED\",\n    \"created_date\": 1792537162354,\n    \"updated_date\": 1792537162354,\n    \"options\": [\n        {\n            \"id\": \"ae3a59f3-3219-4219-babc-fae8b0e0e629\",\n            \"answer\": \"Yes\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"id\": \"358eb6dc-68d2-4b5b-abf4-a45baf2fdd3a\",\n            \"answer\": \"No\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        }\n    ]\n}"},{"id":"d77d3955-df6d-42b6-a1ad-26b7da550744","name":"Free text","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"How can we improve our app?\",\n    \"question_type\": 2,\n    \"banner_image\": \"\",\n    \"information\": null,\n    \"show_feedback\": true,\n    \"free_text_feedback\": \"Thanks, we read every suggestion.\",\n    \"options\": null,\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/create"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"1ffd900d-89f4-4e17-b43b-7d6e167bb796\",\n    \"title\": \"How can we improve our app?\",\n    \"banner_image\": \"\",\n    \"question_type\": \"FREE_TEXT\",\n    \"information\": \"\",\n    \"free_text_feedback\": \"Thanks, we read every suggestion.\",\n    \"status\": \"UNCHECKED\",\n    \"created_date\": 1792537162393,\n    \"updated_date\": 1792537162393,\n    \"options\": []\n}"},{"id":"8d6bda74-205b-4266-aad2-96de904a4f34","name":"Multiple selection","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"Which services do you use?\",\n    \"question_type\": 4,\n    \"banner_image\": \"\",\n    \"information\": null,\n    \"show_feedback\": false,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Mobile data\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"answer\": \"Home broadband\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"answer\": \"TV streaming\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/create"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"cf205a44-9aff-4234-ac89-57cdac2dc176\",\n    \"title\": \"Which services do you use?\",\n    \"banner_image\": \"\",\n    \"question_type\": \"MULTIPLE_SELECTION\",\n    \"information\": \"\",\n    \"free_text_feedback\": null,\n    \"status\": \"UNCHECKED\",\n    \"created_date\": 1792537162447,\n    \"updated_date\": 1792537162447,\n    \"options\": [\n        {\n            \"id\": \"514c3082-67d8-4103-b8ce-4edd175a1629\",\n            \"answer\": \"Mobile data\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"id\": \"4d418d79-2e63-4b9f-8dcf-3a797fd9c98f\",\n            \"answer\": \"Home broadband\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"id\": \"466b3599-e9f5-4895-8b51-75464aa05d90\",\n            \"answer\": \"TV streaming\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        }\n    ]\n}"},{"id":"0c9d0c9b-473e-48c5-a6ea-48048db618f0","name":"Information","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"Before you start\",\n    \"question_type\": 5,\n    \"banner_image\": \"\",\n    \"information\": \"This survey takes about 2 minutes. Answer every question to earn your reward.\",\n    \"show_feedback\": false,\n    \"free_text_feedback\": null,\n    \"options\": null,\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/create"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"34e20579-6c58-4e59-99dc-a9620bd5822c\",\n    \"title\": \"Before you start\",\n    \"banner_image\": \"\",\n    \"question_type\": \"INFORMATION\",\n    \"information\": \"This survey takes about 2 minutes. Answer every question to earn your reward.\",\n    \"free_text_feedback\": null,\n    \"status\": \"UNCHECKED\",\n    \"created_date\": 1792537162476,\n    \"updated_date\": 1792537162476,\n    \"options\": []\n}"},{"id":"4ec255d9-29c6-471e-87c1-d8aca248a19f","name":"400 - binary with 3 options","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"Do you own a smartphone?\",\n    \"question_type\": 1,\n    \"banner_image\": \"\",\n    \"information\": null,\n    \"show_feedback\": false,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Yes\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"answer\": \"No\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"answer\": \"Maybe\",\n            \"image\": \"\",\n            \"answer_feedback\": \"\"\n        }\n    ],\n    \"is_submitted\": false\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/create"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Invalid parameter\",\n    \"detail\": \"Options count is invalid.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"},{"id":"0288d22f-979f-4704-a6b4-de4ea390d983","name":"400 - feedback missing","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"What do you drink in the morning?\",\n    \"question_type\": 3,\n    \"banner_image\": \"question_banner_20261013-093000.123.jpeg\",\n    \"information\": null,\n    \"show_feedback\": true,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Coffee\",\n            \"image\": \"question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"\"\n        },\n        {\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"answer\": \"Juice\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Fruity!\"\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/create"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Missing required body field\",\n    \"detail\": \"Answer feedback is required.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"b44e7b4f-146a-4a0e-b143-6aaba0b8c852"},{"name":"Get List","id":"c68ed3dc-dcb2-4bbd-b301-d9caba63878a","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks?title=&question_type=&status=&type=DRAFT&sequence_id=&role_names=&page=0&size=10","description":"<p>Lists questions for the Question Bank tables, with filtering, paging and sorting.</p>\n<p>All query parameters are optional.</p>\n<h3 id=\"list-types\">List types</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>type</th>\n<th>Returns</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>DRAFT</code> (default, or <code>1</code>)</td>\n<td>Not archived and status is not APPROVED, so DRAFTED, UNCHECKED and REJECTED</td>\n<td>With a Checker-only <code>role_names</code>, DRAFTED items are hidden</td>\n</tr>\n<tr>\n<td><code>ACTIVE</code> (or <code>2</code>)</td>\n<td>Not archived and status is APPROVED</td>\n<td>Only these can go into a survey or campaign</td>\n</tr>\n<tr>\n<td><code>ARCHIVED</code> (or <code>3</code>)</td>\n<td>Archived (deleted) items in any status</td>\n<td></td>\n</tr>\n<tr>\n<td><code>ALL</code> (or <code>4</code>)</td>\n<td>Everything, archived items included</td>\n<td>With a Checker-only <code>role_names</code>, DRAFTED items are hidden</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"pagination-and-sorting\">Pagination and sorting</h3>\n<p>This uses standard Spring Data paging. Note that the parameter is <strong><code>size</code></strong>, not <code>limit</code>.</p>\n<ul>\n<li><code>page</code> is <strong>zero-based</strong>, so the first page is <code>page=0</code>. The default is <code>0</code>.</li>\n<li><code>size</code> is the page size. If you omit it, <strong>every matching row comes back in one page</strong> (capped at 1,000,000). A <code>size</code> of 10 is typical for a table.</li>\n<li><code>sort</code> takes database column names, as <code>sort=&lt;column&gt;,&lt;asc|desc&gt;</code>. The default is <code>created_date,desc</code>. Examples: <code>sort=sequence_id,asc</code>, <code>sort=updated_date,desc</code>.</li>\n</ul>\n<p>Example: <code>page=0&amp;size=10</code> returns rows 1-10, and <code>page=1&amp;size=10</code> returns rows 11-20. Use <code>total_elements</code> and <code>total_pages</code> in the response to build the pager.</p>\n<h3 id=\"response\">Response</h3>\n<p>The response is a Spring <code>Page</code> object. The rows are in <strong><code>content</code></strong>; there is no <code>data</code> field.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>content</td>\n<td>The rows for this page (fields below)</td>\n</tr>\n<tr>\n<td>number</td>\n<td>The current page index (zero-based)</td>\n</tr>\n<tr>\n<td>size</td>\n<td>The requested page size</td>\n</tr>\n<tr>\n<td>number_of_elements</td>\n<td>How many rows are in this page</td>\n</tr>\n<tr>\n<td>total_elements</td>\n<td>Total matching rows across all pages</td>\n</tr>\n<tr>\n<td>total_pages</td>\n<td>Total number of pages</td>\n</tr>\n<tr>\n<td>first / last</td>\n<td>Whether this is the first or last page</td>\n</tr>\n<tr>\n<td>empty</td>\n<td><code>true</code> if <code>content</code> is empty</td>\n</tr>\n<tr>\n<td>pageable, sort</td>\n<td>Echo of the paging and sort that were applied</td>\n</tr>\n</tbody>\n</table>\n</div><p>Each row in <code>content</code>:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>Question UUID</td>\n</tr>\n<tr>\n<td>title</td>\n<td>Question text</td>\n</tr>\n<tr>\n<td>banner_image</td>\n<td>Image path (<code>\"\"</code> if none)</td>\n</tr>\n<tr>\n<td>sequence_id</td>\n<td>e.g. S-000012</td>\n</tr>\n<tr>\n<td>question_type</td>\n<td>Type name</td>\n</tr>\n<tr>\n<td>status</td>\n<td>DRAFTED, UNCHECKED, APPROVED or REJECTED</td>\n</tr>\n<tr>\n<td>type</td>\n<td>Which tab the row belongs to: <code>DRAFT</code>, <code>ACTIVE</code> or <code>ARCHIVED</code></td>\n</tr>\n<tr>\n<td>deleted_at</td>\n<td>When it was archived (<code>yyyy-MM-dd HH:mm:ss</code>), or <code>null</code></td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"examples\">Examples</h3>\n<ul>\n<li>Active single-selection questions for the survey builder picker: <code>type=ACTIVE&amp;question_type=SINGLE_SELECTION&amp;page=0&amp;size=10</code></li>\n<li>A checker's review queue: <code>type=DRAFT&amp;status=UNCHECKED&amp;role_names=Survey.Checker</code></li>\n<li>Search by sequence ID: <code>type=ALL&amp;sequence_id=B-0000</code></li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","question-banks"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[{"description":{"content":"<p>Search text. Case-insensitive partial match on the question <strong>title or sequence ID</strong>. Example: <code>coffee</code> or <code>S-0000</code></p>\n","type":"text/plain"},"key":"title","value":""},{"description":{"content":"<p>Filter by type name or ID: <code>BINARY</code>/<code>1</code>, <code>FREE_TEXT</code>/<code>2</code>, <code>SINGLE_SELECTION</code>/<code>3</code>, <code>MULTIPLE_SELECTION</code>/<code>4</code>, <code>INFORMATION</code>/<code>5</code>. Empty means all types</p>\n","type":"text/plain"},"key":"question_type","value":""},{"description":{"content":"<p>Filter by status name or ID: <code>DRAFTED</code>/<code>1</code>, <code>UNCHECKED</code>/<code>2</code>, <code>APPROVED</code>/<code>3</code>, <code>REJECTED</code>/<code>4</code>. Applied within <code>type</code>. Empty means all</p>\n","type":"text/plain"},"key":"status","value":""},{"description":{"content":"<p>Which list tab: <code>DRAFT</code> (default), <code>ACTIVE</code>, <code>ARCHIVED</code> or <code>ALL</code> (see the description)</p>\n","type":"text/plain"},"key":"type","value":"DRAFT"},{"description":{"content":"<p>Like <code>title</code>: partial match on sequence ID or title. If both <code>title</code> and <code>sequence_id</code> are sent, a question must match <strong>both</strong></p>\n","type":"text/plain"},"key":"sequence_id","value":""},{"description":{"content":"<p>Comma-separated roles of the logged-in dashboard user, e.g. <code>Survey.Maker,Survey.Checker</code>. This is <strong>not a filter on data</strong>. It only controls whether DRAFTED items are visible: if <code>Survey.Checker</code> is present <strong>without</strong> <code>Survey.Maker</code>, DRAFTED items are hidden from <code>type=DRAFT</code> and <code>type=ALL</code> (a checker has nothing to review until the maker submits). Leave it empty to show everything.</p>\n","type":"text/plain"},"key":"role_names","value":""},{"description":{"content":"<p>Zero-based page index. Default 0</p>\n","type":"text/plain"},"key":"page","value":"0"},{"description":{"content":"<p>Page size. Omit it to get all matching rows in one page</p>\n","type":"text/plain"},"key":"size","value":"10"},{"disabled":true,"description":{"content":"<p>Sort column and direction. Default <code>created_date,desc</code></p>\n","type":"text/plain"},"key":"sort","value":"created_date,desc"}],"variable":[]}},"response":[{"id":"db754ec1-a632-48b0-a361-8d1956cebe1c","name":"Draft tab (maker)","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks?type=DRAFT&role_names=Survey.Maker&page=0&size=10","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks"],"query":[{"key":"type","value":"DRAFT","type":"string","description":"Which list tab: `DRAFT` (default), `ACTIVE`, `ARCHIVED` or `ALL` (see the description)"},{"key":"role_names","value":"Survey.Maker","type":"string","description":"Comma-separated roles of the logged-in dashboard user, e.g. `Survey.Maker,Survey.Checker`. This is **not a filter on data**. It only controls whether DRAFTED items are visible: if `Survey.Checker` is present **without** `Survey.Maker`, DRAFTED items are hidden from `type=DRAFT` and `type=ALL` (a checker has nothing to review until the maker submits). Leave it empty to show everything."},{"key":"page","value":"0","type":"number","description":"Zero-based page index. Default 0"},{"key":"size","value":"10","type":"number","description":"Page size. Omit it to get all matching rows in one page"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"content\": [\n        {\n            \"id\": \"c9366fed-0994-4b89-87fb-33f885a9b1f6\",\n            \"title\": \"Do you own a smartphone?\",\n            \"banner_image\": \"\",\n            \"sequence_id\": \"B-000001\",\n            \"question_type\": \"BINARY\",\n            \"status\": \"DRAFTED\",\n            \"type\": \"DRAFT\",\n            \"deleted_at\": null\n        },\n        {\n            \"id\": \"282eeb3f-93b4-4202-8263-a733ce038d45\",\n            \"title\": \"How can we improve our app?\",\n            \"banner_image\": \"\",\n            \"sequence_id\": \"F-000008\",\n            \"question_type\": \"FREE_TEXT\",\n            \"status\": \"REJECTED\",\n            \"type\": \"DRAFT\",\n            \"deleted_at\": null\n        },\n        {\n            \"id\": \"3924d6ef-1e20-48b8-bb17-2f302ee200a3\",\n            \"title\": \"Which services do you use?\",\n            \"banner_image\": \"\",\n            \"sequence_id\": \"M-000001\",\n            \"question_type\": \"MULTIPLE_SELECTION\",\n            \"status\": \"UNCHECKED\",\n            \"type\": \"DRAFT\",\n            \"deleted_at\": null\n        }\n    ],\n    \"pageable\": {\n        \"page_number\": 0,\n        \"page_size\": 10,\n        \"sort\": {\n            \"sorted\": true,\n            \"empty\": false,\n            \"unsorted\": false\n        },\n        \"offset\": 0,\n        \"paged\": true,\n        \"unpaged\": false\n    },\n    \"last\": true,\n    \"total_pages\": 1,\n    \"total_elements\": 3,\n    \"size\": 10,\n    \"number\": 0,\n    \"sort\": {\n        \"sorted\": true,\n        \"empty\": false,\n        \"unsorted\": false\n    },\n    \"first\": true,\n    \"number_of_elements\": 3,\n    \"empty\": false\n}"},{"id":"539ae990-d8fc-428c-9280-00fe088c3bf8","name":"Checker review queue (drafts hidden)","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks?type=DRAFT&status=UNCHECKED&role_names=Survey.Checker&page=0&size=10","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks"],"query":[{"key":"type","value":"DRAFT","type":"string","description":"Which list tab: `DRAFT` (default), `ACTIVE`, `ARCHIVED` or `ALL` (see the description)"},{"key":"status","value":"UNCHECKED","type":"string","description":"Filter by status name or ID: `DRAFTED`/`1`, `UNCHECKED`/`2`, `APPROVED`/`3`, `REJECTED`/`4`. Applied within `type`. Empty means all"},{"key":"role_names","value":"Survey.Checker","type":"string","description":"Comma-separated roles of the logged-in dashboard user, e.g. `Survey.Maker,Survey.Checker`. This is **not a filter on data**. It only controls whether DRAFTED items are visible: if `Survey.Checker` is present **without** `Survey.Maker`, DRAFTED items are hidden from `type=DRAFT` and `type=ALL` (a checker has nothing to review until the maker submits). Leave it empty to show everything."},{"key":"page","value":"0","type":"number","description":"Zero-based page index. Default 0"},{"key":"size","value":"10","type":"number","description":"Page size. Omit it to get all matching rows in one page"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"content\": [\n        {\n            \"id\": \"3924d6ef-1e20-48b8-bb17-2f302ee200a3\",\n            \"title\": \"Which services do you use?\",\n            \"banner_image\": \"\",\n            \"sequence_id\": \"M-000001\",\n            \"question_type\": \"MULTIPLE_SELECTION\",\n            \"status\": \"UNCHECKED\",\n            \"type\": \"DRAFT\",\n            \"deleted_at\": null\n        }\n    ],\n    \"pageable\": {\n        \"page_number\": 0,\n        \"page_size\": 10,\n        \"sort\": {\n            \"sorted\": true,\n            \"empty\": false,\n            \"unsorted\": false\n        },\n        \"offset\": 0,\n        \"paged\": true,\n        \"unpaged\": false\n    },\n    \"last\": true,\n    \"total_pages\": 1,\n    \"total_elements\": 1,\n    \"size\": 10,\n    \"number\": 0,\n    \"sort\": {\n        \"sorted\": true,\n        \"empty\": false,\n        \"unsorted\": false\n    },\n    \"first\": true,\n    \"number_of_elements\": 1,\n    \"empty\": false\n}"},{"id":"35718388-d0ce-43ba-a4a8-3cfd830a42ca","name":"Active single selection, searched by title","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks?title=drink&question_type=SINGLE_SELECTION&type=ACTIVE&page=0&size=10","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks"],"query":[{"key":"title","value":"drink","type":"string","description":"Search text. Case-insensitive partial match on the question **title or sequence ID**. Example: `coffee` or `S-0000`"},{"key":"question_type","value":"SINGLE_SELECTION","type":"string","description":"Filter by type name or ID: `BINARY`/`1`, `FREE_TEXT`/`2`, `SINGLE_SELECTION`/`3`, `MULTIPLE_SELECTION`/`4`, `INFORMATION`/`5`. Empty means all types"},{"key":"type","value":"ACTIVE","type":"string","description":"Which list tab: `DRAFT` (default), `ACTIVE`, `ARCHIVED` or `ALL` (see the description)"},{"key":"page","value":"0","type":"number","description":"Zero-based page index. Default 0"},{"key":"size","value":"10","type":"number","description":"Page size. Omit it to get all matching rows in one page"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"content\": [\n        {\n            \"id\": \"5c2e98fe-d8a2-4131-9a22-2b423325f561\",\n            \"title\": \"What do you drink in the morning?\",\n            \"banner_image\": \"/dashboard/question-banks/images/question_banner_20261013-093000.123.jpeg\",\n            \"sequence_id\": \"S-000001\",\n            \"question_type\": \"SINGLE_SELECTION\",\n            \"status\": \"APPROVED\",\n            \"type\": \"ACTIVE\",\n            \"deleted_at\": null\n        }\n    ],\n    \"pageable\": {\n        \"page_number\": 0,\n        \"page_size\": 10,\n        \"sort\": {\n            \"sorted\": true,\n            \"empty\": false,\n            \"unsorted\": false\n        },\n        \"offset\": 0,\n        \"paged\": true,\n        \"unpaged\": false\n    },\n    \"last\": true,\n    \"total_pages\": 1,\n    \"total_elements\": 1,\n    \"size\": 10,\n    \"number\": 0,\n    \"sort\": {\n        \"sorted\": true,\n        \"empty\": false,\n        \"unsorted\": false\n    },\n    \"first\": true,\n    \"number_of_elements\": 1,\n    \"empty\": false\n}"},{"id":"901bb668-c3bc-4e6f-b2d8-623ce120045a","name":"Archived","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks?type=ARCHIVED&page=0&size=10","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks"],"query":[{"key":"type","value":"ARCHIVED","type":"string","description":"Which list tab: `DRAFT` (default), `ACTIVE`, `ARCHIVED` or `ALL` (see the description)"},{"key":"page","value":"0","type":"number","description":"Zero-based page index. Default 0"},{"key":"size","value":"10","type":"number","description":"Page size. Omit it to get all matching rows in one page"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"content\": [\n        {\n            \"id\": \"c9366fed-0994-4b89-87fb-33f885a9b1f6\",\n            \"title\": \"Do you own a smartphone?\",\n            \"banner_image\": \"\",\n            \"sequence_id\": \"B-000001\",\n            \"question_type\": \"BINARY\",\n            \"status\": \"DRAFTED\",\n            \"type\": \"ARCHIVED\",\n            \"deleted_at\": \"2026-10-20 22:59:29\"\n        }\n    ],\n    \"pageable\": {\n        \"page_number\": 0,\n        \"page_size\": 10,\n        \"sort\": {\n            \"sorted\": true,\n            \"empty\": false,\n            \"unsorted\": false\n        },\n        \"offset\": 0,\n        \"paged\": true,\n        \"unpaged\": false\n    },\n    \"last\": true,\n    \"total_pages\": 1,\n    \"total_elements\": 1,\n    \"size\": 10,\n    \"number\": 0,\n    \"sort\": {\n        \"sorted\": true,\n        \"empty\": false,\n        \"unsorted\": false\n    },\n    \"first\": true,\n    \"number_of_elements\": 1,\n    \"empty\": false\n}"}],"_postman_id":"c68ed3dc-dcb2-4bbd-b301-d9caba63878a"},{"name":"Get Details","id":"ce215b9e-257c-43bb-bcad-3273155369b1","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/details/:id","description":"<p>Returns one question with all of its options, as shown on the question detail and edit screen.</p>\n<p>This works for questions in any status, including archived ones.</p>\n<h3 id=\"response-200\">Response: 200</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>Question UUID</td>\n</tr>\n<tr>\n<td>title</td>\n<td>Question text</td>\n</tr>\n<tr>\n<td>question_type</td>\n<td>Type name: BINARY, FREE_TEXT, SINGLE_SELECTION, MULTIPLE_SELECTION or INFORMATION</td>\n</tr>\n<tr>\n<td>question_category</td>\n<td><code>Drafted Question</code> (not approved), <code>Active Question</code> (APPROVED) or <code>Archived Question</code> (deleted)</td>\n</tr>\n<tr>\n<td>sequence_id</td>\n<td>Human-friendly ID, e.g. S-000012</td>\n</tr>\n<tr>\n<td>show_feedback</td>\n<td>Whether feedback is shown after answering</td>\n</tr>\n<tr>\n<td>information</td>\n<td>Information text (type 5), otherwise <code>\"\"</code></td>\n</tr>\n<tr>\n<td>free_text_feedback</td>\n<td>Feedback for free text questions, or <code>null</code></td>\n</tr>\n<tr>\n<td>rejection_reason</td>\n<td>The checker's reason, set by Submit Approval (<code>\"\"</code> or <code>null</code> if none)</td>\n</tr>\n<tr>\n<td>banner_image</td>\n<td>Image path, ready for <strong>Get Image</strong> (<code>\"\"</code> if none)</td>\n</tr>\n<tr>\n<td>status</td>\n<td>DRAFTED, UNCHECKED, APPROVED or REJECTED</td>\n</tr>\n<tr>\n<td>created_date / updated_date</td>\n<td>Epoch milliseconds</td>\n</tr>\n<tr>\n<td>options</td>\n<td>Array of <code>{{id, answer, image, answer_feedback, created_date, updated_date}}</code>, or <code>null</code> for types 2 and 5</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"errors\">Errors</h3>\n<ul>\n<li><strong>404</strong> <em>Resource Not Found</em>: there is no question with that ID.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","question-banks","details",":id"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"b897a0a4-aaf5-4e08-bff0-ae53b00a8108","description":{"content":"<p><strong>UUID</strong>. The question's ID, from Get List or the Create response. Example: <code>3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90</code></p>\n","type":"text/plain"},"type":"any","value":"3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90","key":"id"}]}},"response":[{"id":"7d7cea8c-89d7-4530-b0ae-8d0ef6e6a4e6","name":"Approved single selection question","originalRequest":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/details/002c6da4-5eb3-4883-b43a-7e4fe55f4792"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"002c6da4-5eb3-4883-b43a-7e4fe55f4792\",\n    \"title\": \"What do you drink in the morning?\",\n    \"question_type\": \"SINGLE_SELECTION\",\n    \"question_category\": \"Active Question\",\n    \"sequence_id\": \"S-000001\",\n    \"show_feedback\": true,\n    \"information\": \"\",\n    \"free_text_feedback\": null,\n    \"rejection_reason\": \"\",\n    \"banner_image\": \"/dashboard/question-banks/images/question_banner_20261013-093000.123.jpeg\",\n    \"status\": \"APPROVED\",\n    \"created_date\": 1792537160806,\n    \"updated_date\": 1792537160863,\n    \"options\": [\n        {\n            \"id\": \"b0a4bf33-dc8d-43a4-966f-577379d9e8ab\",\n            \"answer\": \"Coffee\",\n            \"image\": \"/dashboard/question-banks/images/question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\",\n            \"created_date\": 1792537160808,\n            \"updated_date\": 1792537160808\n        },\n        {\n            \"id\": \"c83a7ea4-6540-4a42-b633-823a583e92bf\",\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\",\n            \"created_date\": 1792537160808,\n            \"updated_date\": 1792537160808\n        },\n        {\n            \"id\": \"ca2e63c8-2a9a-4173-a9c6-f7c6efdbf4b4\",\n            \"answer\": \"Juice\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Fruity!\",\n            \"created_date\": 1792537160808,\n            \"updated_date\": 1792537160808\n        }\n    ]\n}"},{"id":"463c175b-759a-48bc-929f-51e3a2e11e90","name":"Rejected free text question","originalRequest":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/details/573e593c-38dc-4029-9876-ef2279e07b78"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"573e593c-38dc-4029-9876-ef2279e07b78\",\n    \"title\": \"How can we improve our app?\",\n    \"question_type\": \"FREE_TEXT\",\n    \"question_category\": \"Drafted Question\",\n    \"sequence_id\": \"F-000008\",\n    \"show_feedback\": true,\n    \"information\": \"\",\n    \"free_text_feedback\": \"Thanks, we read every suggestion.\",\n    \"rejection_reason\": \"Please make the wording friendlier.\",\n    \"banner_image\": \"\",\n    \"status\": \"REJECTED\",\n    \"created_date\": 1792537160887,\n    \"updated_date\": 1792537160920,\n    \"options\": null\n}"},{"id":"a9d9e2c5-aff0-463b-baa3-54264b277210","name":"404 - unknown id","originalRequest":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/details/00000000-0000-0000-0000-000000000000"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Resource Not Found\",\n    \"detail\": \"The requested resource was not found.\",\n    \"status\": 404,\n    \"instance\": \"\",\n    \"errorKey\": \"resource_not_found\"\n}"}],"_postman_id":"ce215b9e-257c-43bb-bcad-3273155369b1"},{"name":"Get Image","id":"967632bb-faf9-4664-88c5-0589f2cfd813","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/images/:name","description":"<p>Streams the raw bytes of a question banner or option image from S3.</p>\n<p>The paths returned in question responses already point at this endpoint, e.g. <code>banner_image: \"/dashboard/question-banks/images/question_banner_20261013-093000.123.jpeg\"</code>. Prefix them with <code>https://gateway.test.youtap.systems/survey/sso</code> to load the image.</p>\n<ul>\n<li><strong>200</strong>: the image bytes. No <code>Content-Type</code> is set, so infer it from the file extension.</li>\n<li><strong>404</strong> <em>Resource Not Found</em> / <em>Failed to retrieve S3 resource</em>: there is no file with that name.</li>\n</ul>\n<p>All three images endpoints (question bank, survey, mobile) read the same S3 folder, so any uploaded file name works on any of them.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","question-banks","images",":name"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"a7c672b9-6d3b-49bd-b499-ef01461eb7a3","description":{"content":"<p>Image file name: the last segment of <code>banner_image</code> or <code>options[].image</code>, or of the Upload File <code>file_name</code></p>\n","type":"text/plain"},"type":"any","value":"question_banner_20261013-093000.123.jpeg","key":"name"}]}},"response":[{"id":"a02e53c1-1c66-4c96-b6c3-fb27c29d6815","name":"200 - image bytes","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/images/:name","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","question-banks","images",":name"],"variable":[{"key":"name","value":"question_banner_20261013-093000.123.jpeg","description":"Image file name: the last segment of `banner_image` or `options[].image`, or of the Upload File `file_name`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[],"cookie":[],"responseTime":null,"body":""},{"id":"828faedf-5143-4011-b53e-badf01d75359","name":"404 - unknown file","originalRequest":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/images/does_not_exist.jpeg"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Resource Not Found\",\n    \"detail\": \"Failed to retrieve S3 resource\",\n    \"status\": 404,\n    \"instance\": \"\",\n    \"errorKey\": \"resource_not_found\"\n}"}],"_postman_id":"967632bb-faf9-4664-88c5-0589f2cfd813"},{"name":"Edit","id":"9037d2aa-e16c-42ff-a45c-a68c31db1eb0","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"What do you drink at breakfast?\",\n    \"question_type\": 3,\n    \"banner_image\": \"question_banner_20261013-093000.123.jpeg\",\n    \"information\": null,\n    \"show_feedback\": true,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Coffee\",\n            \"image\": \"question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\"\n        },\n        {\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"answer\": \"Water\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Staying hydrated!\"\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/update/:id","description":"<p>Updates a question. Despite the <code>PATCH</code> method this is a <strong>full replacement</strong>: send every field, exactly as in <strong>Create</strong>. The same validation rules and errors apply.</p>\n<h3 id=\"what-changes\">What changes</h3>\n<ul>\n<li>All fields are overwritten with the request values.</li>\n<li><strong>All existing options are removed and new options are created</strong>, so option IDs change. Send every option you want to keep.</li>\n<li><code>status</code> becomes <strong>UNCHECKED</strong> if <code>is_submitted</code> is true, otherwise <strong>DRAFTED</strong>. This applies whatever the current status is, so editing an <strong>APPROVED</strong> question takes it out of the ACTIVE list until it is approved again.</li>\n<li>An archived question is <strong>un-archived</strong>.</li>\n</ul>\n<p>Edit is refused with <strong>400</strong> <em>Action is unavailable</em> / <em>Question S-000012 is used in an active survey.</em> while the question is in an <strong>APPROVED</strong> survey. Draft, unchecked and rejected surveys that use the question show the new content, and approving such a survey fails until the edited question is approved again.</p>\n<h3 id=\"body\">Body</h3>\n<p>Same fields as <strong>Create</strong>. Note that the key is <code>banner_image</code>. A body with <code>image</code> instead is rejected because <code>banner_image</code> is required.</p>\n<h3 id=\"response-200\">Response: 200</h3>\n<p>This response differs slightly from Create:</p>\n<ul>\n<li>it includes <code>sequence_id</code>;</li>\n<li>the banner is returned in <strong><code>image</code></strong>, not <code>banner_image</code>;</li>\n<li>image values are returned <strong>as stored</strong> (file names), not as paths.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","question-banks","update",":id"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"efeca7d4-6b3e-488d-9f83-bb2fd6e4dc66","description":{"content":"<p><strong>UUID</strong>. The question's ID, from Get List or the Create response. Example: <code>3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90</code></p>\n","type":"text/plain"},"type":"any","value":"3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90","key":"id"}]}},"response":[{"id":"1618f846-391c-4805-856f-54591e6f401c","name":"Edit and resubmit","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"What do you drink at breakfast?\",\n    \"question_type\": 3,\n    \"banner_image\": \"question_banner_20261013-093000.123.jpeg\",\n    \"information\": null,\n    \"show_feedback\": true,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Coffee\",\n            \"image\": \"question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\"\n        },\n        {\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"answer\": \"Water\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Staying hydrated!\"\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/update/22b51528-7f73-4428-8ee3-40950c5ca4e8"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"22b51528-7f73-4428-8ee3-40950c5ca4e8\",\n    \"title\": \"What do you drink at breakfast?\",\n    \"sequence_id\": \"S-000001\",\n    \"question_type\": \"SINGLE_SELECTION\",\n    \"information\": \"\",\n    \"free_text_feedback\": null,\n    \"image\": \"question_banner_20261013-093000.123.jpeg\",\n    \"status\": \"UNCHECKED\",\n    \"created_date\": 1792537158938,\n    \"updated_date\": 1792537159219,\n    \"options\": [\n        {\n            \"id\": \"6c9c5cef-ba52-4298-9834-5ce08e25771a\",\n            \"answer\": \"Coffee\",\n            \"image\": \"question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\"\n        },\n        {\n            \"id\": \"6b6f0cfd-7ff3-418b-96f3-19d0a5d85c9b\",\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"id\": \"b0812350-47fb-4639-8b61-c7aa38e03b46\",\n            \"answer\": \"Water\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Staying hydrated!\"\n        }\n    ]\n}"},{"id":"e3c8d7d8-a3db-4911-848a-a7fba1778801","name":"404 - unknown id","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"What do you drink at breakfast?\",\n    \"question_type\": 3,\n    \"banner_image\": \"question_banner_20261013-093000.123.jpeg\",\n    \"information\": null,\n    \"show_feedback\": true,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Coffee\",\n            \"image\": \"question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\"\n        },\n        {\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"answer\": \"Water\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Staying hydrated!\"\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/update/00000000-0000-0000-0000-000000000000"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Resource Not Found\",\n    \"detail\": \"The requested resource was not found.\",\n    \"status\": 404,\n    \"instance\": \"\",\n    \"errorKey\": \"resource_not_found\"\n}"},{"id":"2f08bb6e-766c-4134-ae11-a9af2ebe0c0a","name":"400 - used in an active survey","originalRequest":{"method":"PATCH","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"title\": \"What do you drink at breakfast?\",\n    \"question_type\": 3,\n    \"banner_image\": \"question_banner_20261013-093000.123.jpeg\",\n    \"information\": null,\n    \"show_feedback\": true,\n    \"free_text_feedback\": null,\n    \"options\": [\n        {\n            \"answer\": \"Coffee\",\n            \"image\": \"question_option_image_20261013-093105.456.png\",\n            \"answer_feedback\": \"A classic way to start the day!\"\n        },\n        {\n            \"answer\": \"Tea\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Calm and refreshing.\"\n        },\n        {\n            \"answer\": \"Water\",\n            \"image\": \"\",\n            \"answer_feedback\": \"Staying hydrated!\"\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/update/af3995a7-3d84-4198-9425-acd0057fdae7"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Action is unavailable\",\n    \"detail\": \"Question S-000002 is used in an active survey.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"9037d2aa-e16c-42ff-a45c-a68c31db1eb0"},{"name":"Submit Approval","id":"2eb0f2b8-dc32-48c0-a01a-29b33b265880","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": true,\n    \"reason\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/submit-approval/:id","description":"<p>The <strong>checker's decision</strong> on a question that is waiting for review: approve or reject it.</p>\n<p>Despite the name, this does <strong>not</strong> submit a question for review. Makers do that by sending <code>is_submitted: true</code> to Create or Edit.</p>\n<h3 id=\"body\">Body</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>approval_status</td>\n<td>boolean</td>\n<td>Yes</td>\n<td><code>true</code> gives <strong>APPROVED</strong>, <code>false</code> gives <strong>REJECTED</strong></td>\n</tr>\n<tr>\n<td>reason</td>\n<td>string / null</td>\n<td>No</td>\n<td>Rejection reason shown to the maker (stored as <code>rejection_reason</code>). Normally only sent when rejecting</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"rules\">Rules</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Current state</th>\n<th>Result</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>UNCHECKED</td>\n<td>200, status updated</td>\n</tr>\n<tr>\n<td>DRAFTED</td>\n<td>400 <em>Could not submit question bank approval</em> / <em>The question bank item is still in draft.</em></td>\n</tr>\n<tr>\n<td>APPROVED or REJECTED</td>\n<td>400 <em>Could not submit question bank approval</em> / <em>The approval process for this question bank item has been finished.</em></td>\n</tr>\n<tr>\n<td>Archived</td>\n<td>404 <em>Resource Not Found</em> / <em>The survey is archived.</em> (the message says \"survey\" for questions too)</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"response-200\">Response: 200</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>question_id</td>\n<td>Question UUID</td>\n</tr>\n<tr>\n<td>title</td>\n<td>Question text</td>\n</tr>\n<tr>\n<td>sequence_id</td>\n<td>e.g. S-000012</td>\n</tr>\n<tr>\n<td>status</td>\n<td>APPROVED or REJECTED</td>\n</tr>\n<tr>\n<td>status_id</td>\n<td>3 (APPROVED) or 4 (REJECTED)</td>\n</tr>\n<tr>\n<td>rejection_reason</td>\n<td>The <code>reason</code> sent, or <code>\"\"</code></td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","question-banks","submit-approval",":id"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"93b230de-4391-441d-ba2b-b35b581cf5d4","description":{"content":"<p><strong>UUID</strong>. The question's ID, from Get List or the Create response. Example: <code>3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90</code></p>\n","type":"text/plain"},"type":"any","value":"3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90","key":"id"}]}},"response":[{"id":"e085cdcd-5ae5-4286-91fc-9d9d073bc1dd","name":"Approve","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": true,\n    \"reason\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/submit-approval/b333958a-41f6-4bf7-a317-9363efd83e14"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"question_id\": \"b333958a-41f6-4bf7-a317-9363efd83e14\",\n    \"title\": \"What do you drink in the morning?\",\n    \"sequence_id\": \"S-000001\",\n    \"status\": \"APPROVED\",\n    \"status_id\": 3,\n    \"rejection_reason\": \"\"\n}"},{"id":"d489ead4-a5cc-4f83-a5fa-15bfe5468d35","name":"Reject with reason","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": false,\n    \"reason\": \"Please make the wording friendlier.\"\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/submit-approval/95d8025b-76c5-40c0-ad9a-28e90be4cc44"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"question_id\": \"95d8025b-76c5-40c0-ad9a-28e90be4cc44\",\n    \"title\": \"How can we improve our app?\",\n    \"sequence_id\": \"F-000008\",\n    \"status\": \"REJECTED\",\n    \"status_id\": 4,\n    \"rejection_reason\": \"Please make the wording friendlier.\"\n}"},{"id":"e30a5a51-6711-4315-a984-ef34a329fa1a","name":"400 - still a draft","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": true,\n    \"reason\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/submit-approval/0eaeb4ea-e75d-4def-bd6f-0e953a843767"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Could not submit question bank approval\",\n    \"detail\": \"The question bank item is still in draft.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"2eb0f2b8-dc32-48c0-a01a-29b33b265880"},{"name":"Delete","id":"ce26549d-c5fb-49ef-94fa-732448502f34","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/delete/:id","description":"<p>Archives (soft-deletes) a question. It disappears from DRAFT and ACTIVE lists and appears under <code>type=ARCHIVED</code>.</p>\n<p>To restore it, use <strong>Edit</strong>: editing an archived question un-archives it.</p>\n<h3 id=\"rules\">Rules</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Question state</th>\n<th>Result</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>DRAFTED, REJECTED or APPROVED, and not used in an APPROVED survey</td>\n<td>204, archived (even if a draft or unchecked survey still lists it)</td>\n</tr>\n<tr>\n<td>UNCHECKED (waiting for a checker)</td>\n<td>400 <em>Could not perform this action</em> / <em>Question is under review.</em></td>\n</tr>\n<tr>\n<td>Used in at least one APPROVED survey</td>\n<td>400 <em>Question cannot be deleted</em> / <em>Question S-000012 is listed on one or multiple surveys.</em></td>\n</tr>\n<tr>\n<td>Unknown ID</td>\n<td>404 <em>Resource Not Found</em></td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"response-204-no-content\">Response: 204 No Content</h3>\n<p>The response has no body.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","question-banks","delete",":id"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"1fdd089c-c859-4a22-a639-6dbe80d8531d","description":{"content":"<p><strong>UUID</strong>. The question's ID, from Get List or the Create response. Example: <code>3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90</code></p>\n","type":"text/plain"},"type":"any","value":"3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90","key":"id"}]}},"response":[{"id":"40c53331-4ab1-4dfb-a922-90904ccc0385","name":"204 - archived","originalRequest":{"method":"DELETE","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/delete/b3cc3231-caaa-40b7-be04-e8aa4d2f015c"},"status":"No Content","code":204,"_postman_previewlanguage":"text","header":[],"cookie":[],"responseTime":null,"body":""},{"id":"0e055685-a3fe-41e2-aa85-aa9c69291629","name":"400 - waiting for approval","originalRequest":{"method":"DELETE","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/delete/87d1928a-0352-4769-acda-9a77a20a4d5d"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Could not perform this action\",\n    \"detail\": \"Question is under review.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"},{"id":"efe29848-9a23-414f-8e92-0fd3061060b1","name":"400 - used in a survey","originalRequest":{"method":"DELETE","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/question-banks/delete/808257f5-dd5a-4261-ab9a-e88ad89d2dce"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Question cannot be deleted\",\n    \"detail\": \"Question S-000001 is listed on one or multiple surveys.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"ce26549d-c5fb-49ef-94fa-732448502f34"}],"id":"bfee9263-77db-4227-bae7-0db04ca57a9e","description":"<p>Manage the reusable questions that surveys are built from.</p>\n<h2 id=\"question-types\">Question types</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>ID</th>\n<th>Name</th>\n<th>Seq. prefix</th>\n<th>Options</th>\n<th>Other required fields</th>\n<th>Answered on mobile with</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>1</td>\n<td>BINARY</td>\n<td>B</td>\n<td><strong>Exactly 2</strong></td>\n<td>-</td>\n<td><code>question_option_ids</code> (1 ID)</td>\n</tr>\n<tr>\n<td>2</td>\n<td>FREE_TEXT</td>\n<td>F</td>\n<td><strong>None</strong> (<code>null</code> or <code>[]</code>)</td>\n<td><code>free_text_feedback</code> if <code>show_feedback</code> is true (max 340 chars)</td>\n<td><code>answer_content</code> (max 340 chars)</td>\n</tr>\n<tr>\n<td>3</td>\n<td>SINGLE_SELECTION</td>\n<td>S</td>\n<td><strong>2-10</strong></td>\n<td>-</td>\n<td><code>question_option_ids</code> (1 ID)</td>\n</tr>\n<tr>\n<td>4</td>\n<td>MULTIPLE_SELECTION</td>\n<td>M</td>\n<td><strong>2-10</strong></td>\n<td>-</td>\n<td><code>question_option_ids</code> (1 or more IDs)</td>\n</tr>\n<tr>\n<td>5</td>\n<td>INFORMATION</td>\n<td>I</td>\n<td><strong>None</strong> (<code>null</code> or <code>[]</code>)</td>\n<td><code>information</code> (text to display)</td>\n<td>An empty answer, just to mark it as seen</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"field-limits\">Field limits</h2>\n<ul>\n<li><code>title</code>: max <strong>45</strong> characters.</li>\n<li><code>options[].answer</code>: max <strong>22</strong> characters.</li>\n<li><code>free_text_feedback</code>: max <strong>340</strong> characters.</li>\n<li>When <code>show_feedback</code> is <code>true</code>:<ul>\n<li>every option needs a non-empty <code>answer_feedback</code>;</li>\n<li>a FREE_TEXT question needs <code>free_text_feedback</code>.</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"feedback\">Feedback</h2>\n<p>When <code>show_feedback</code> is <code>true</code>, the app shows feedback after the customer answers:</p>\n<ul>\n<li>the <code>answer_feedback</code> of the option they chose, or</li>\n<li>the <code>free_text_feedback</code>, for a free text question.</li>\n</ul>\n<h2 id=\"rules\">Rules</h2>\n<ul>\n<li><strong>Delete</strong> is refused while the question is UNCHECKED, or while it is used in an <strong>APPROVED</strong> survey. Questions in draft, unchecked or rejected surveys can still be archived.</li>\n<li><strong>Edit</strong> is refused while the question is used in an <strong>APPROVED</strong> survey, because customers may be answering it. Otherwise it sets the status back to DRAFTED or UNCHECKED, so editing an APPROVED question takes it out of the ACTIVE list until it is re-approved.</li>\n<li><strong>Edit replaces all options</strong> with new ones, which have <strong>new option IDs</strong>.</li>\n</ul>\n","_postman_id":"bfee9263-77db-4227-bae7-0db04ca57a9e","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}}},{"name":"Survey","item":[{"name":"Upload File","id":"bc4649bd-f63e-4cb5-8b5f-bd0e06a6689b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PUT","header":[{"key":"Content-Type","value":"image/jpeg","description":"<p>Match the file, e.g. image/png</p>\n","type":"text"}],"body":{"mode":"file","file":{"src":""}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/upload-image?file_name=breakfast.jpeg","description":"<p>Uploads a survey banner image.</p>\n<p>Send the image as the <strong>raw binary body</strong> (Body &gt; binary in Postman).</p>\n<ul>\n<li>Checks: the body must be an image (PNG, JPEG or GIF) of at most <strong>150 KB</strong>.</li>\n<li>It is stored as <strong><code>survey_banner_&lt;yyyyMMdd-HHmmss.SSS&gt;&lt;extension&gt;</code></strong>.</li>\n<li>Then put the returned <strong>file name</strong> (the part after the last <code>/</code>) in the survey <code>image</code> field on Create or Edit.</li>\n</ul>\n<h3 id=\"response-200\">Response: 200</h3>\n<pre class=\"click-to-expand-wrapper is-snippet-wrapper\"><code class=\"language-json\">{ \"file_name\": \"/dashboard/surveys/images/survey_banner_20261013-094500.789.jpeg\" }\n</code></pre>\n<h3 id=\"errors\">Errors</h3>\n<ul>\n<li><strong>400</strong> <em>Invalid parameter</em>: <em>Image size cannot be larger than 150 KB.</em>, or <em>Image extension is not supported</em>.</li>\n<li><strong>400</strong> <em>Invalid parameter</em>: <em>Data is not an image.</em>, or <em>Invalid filename.</em> (<code>file_name</code> contains a path).</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","surveys","upload-image"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[{"description":{"content":"<p>Original file name. <strong>Only its extension is used</strong> (must be an image extension). Must not contain <code>/</code>, <code>\\</code> or <code>..</code></p>\n","type":"text/plain"},"key":"file_name","value":"breakfast.jpeg"}],"variable":[]}},"response":[{"id":"fafbf021-a11e-426d-92f3-f0219a3bb59c","name":"Banner image","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"image/jpeg","type":"text","description":"Match the file, e.g. image/png"}],"body":{"mode":"file","file":{}},"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/upload-image?file_name=breakfast.jpeg","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","surveys","upload-image"],"query":[{"key":"file_name","value":"breakfast.jpeg","type":"string","description":"Original file name. **Only its extension is used** (must be an image extension). Must not contain `/`, `\\` or `..`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"file_name\": \"/dashboard/surveys/images/survey_banner_20261020-225921.117.jpeg\"\n}"},{"id":"3ea14781-1c2b-4e57-a5b9-8d7a04039452","name":"400 - not an image extension","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"image/jpeg","type":"text","description":"Match the file, e.g. image/png"}],"body":{"mode":"file","file":{}},"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/upload-image?file_name=banner.pdf","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","surveys","upload-image"],"query":[{"key":"file_name","value":"banner.pdf","type":"string","description":"Original file name. **Only its extension is used** (must be an image extension). Must not contain `/`, `\\` or `..`"}]}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Invalid parameter\",\n    \"detail\": \"Image extension is not supported\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"bc4649bd-f63e-4cb5-8b5f-bd0e06a6689b"},{"name":"Create","event":[{"listen":"test","script":{"type":"text/javascript","exec":["// Stores the new ID so the other requests in this collection can use it","if (pm.response.code === 200) {","    pm.collectionVariables.set('survey_id', pm.response.json().id);","}"],"id":"664ea959-4476-49ad-993c-08d01c5a06bc"}}],"id":"51091b68-d97c-4de3-bf08-18d736ad4dea","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"name\": \"Morning habits survey\",\n    \"image\": \"survey_banner_20261013-094500.789.jpeg\",\n    \"questions\": [\n        {\n            \"question_id\": \"809b36dd-57c6-48a2-9d88-1f54cd09cfb6\",\n            \"position\": 1\n        },\n        {\n            \"question_id\": \"ba2f78a3-5175-4b47-a79b-075600c9827a\",\n            \"position\": 2\n        },\n        {\n            \"question_id\": \"205217c7-7184-43fc-88dd-82bf54e231f4\",\n            \"position\": 3\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/create","description":"<p>Creates a survey from approved questions.</p>\n<p>The test script saves the new <code>id</code> into the <code>survey_id</code> collection variable.</p>\n<h3 id=\"body\">Body</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>string</td>\n<td>Yes</td>\n<td>Survey name shown to customers. Max 70 characters</td>\n</tr>\n<tr>\n<td>image</td>\n<td>string</td>\n<td>Yes</td>\n<td>Banner file name from <strong>Survey &gt; Upload File</strong>, or <code>\"\"</code> for none</td>\n</tr>\n<tr>\n<td>questions</td>\n<td>array</td>\n<td>Yes</td>\n<td>At least 1. The order customers see is set by <code>position</code>, not by array order</td>\n</tr>\n<tr>\n<td>questions[].question_id</td>\n<td>string</td>\n<td>Yes</td>\n<td>UUID of an <strong>APPROVED</strong> question (from Question Bank &gt; Get List with <code>type=ACTIVE</code>). No duplicates</td>\n</tr>\n<tr>\n<td>questions[].position</td>\n<td>number</td>\n<td>Yes</td>\n<td>1-based display order, from 1 to the number of questions</td>\n</tr>\n<tr>\n<td>is_submitted</td>\n<td>boolean</td>\n<td>Yes</td>\n<td><code>true</code> gives UNCHECKED (sent to a checker), <code>false</code> gives DRAFTED</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"linking-an-uploaded-image\">Linking an uploaded image</h3>\n<p>Upload File returns a <strong>path</strong> such as <code>/dashboard/surveys/images/survey_banner_20261013-093000.123.jpeg</code>.</p>\n<p>In create and edit requests, put <strong>only the file name</strong>, the part after the last <code>/</code> (e.g. <code>survey_banner_20261013-093000.123.jpeg</code>). The API prefixes the correct images path when it returns the record. A full path or URL is also accepted: only the part after the last <code>/</code> is used when the path is returned. Use <code>\"\"</code> for \"no image\".</p>\n<h3 id=\"response-200\">Response: 200</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>Survey UUID. This is the value that goes into the promotion-service-api campaign <code>url</code></td>\n</tr>\n<tr>\n<td>name</td>\n<td>Survey name</td>\n</tr>\n<tr>\n<td>status / status_id</td>\n<td><code>UNCHECKED</code>/2 or <code>DRAFTED</code>/1</td>\n</tr>\n<tr>\n<td>questions</td>\n<td><code>[{{question_id, position}}]</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>The sequence ID (e.g. <code>007</code>) is generated but not returned here. See <strong>Get Detail</strong>.</p>\n<h3 id=\"errors\">Errors</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>title / detail</th>\n<th>Cause</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>400</td>\n<td>Missing required body field / Survey name should not be longer than 70 characters.</td>\n<td>Name too long</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field / Survey should have at least one question.</td>\n<td>Empty <code>questions</code></td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field / Survey question position cannot be higher than question count.</td>\n<td>A <code>position</code> is &lt; 1 or &gt; the question count</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field / Duplicate question (Edit: <em>There are duplicate question IDs provided.</em>)</td>\n<td>Same <code>question_id</code> twice</td>\n</tr>\n<tr>\n<td>404</td>\n<td>Resource Not Found</td>\n<td>Unknown <code>question_id</code></td>\n</tr>\n<tr>\n<td>400</td>\n<td>Invalid survey question / Question # is not approved.</td>\n<td>A question is not APPROVED</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","surveys","create"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[]}},"response":[{"id":"2f5a8b1e-5ad7-4a59-a2ad-eaf9521dc343","name":"Create and submit","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"name\": \"Morning habits survey\",\n    \"image\": \"survey_banner_20261013-094500.789.jpeg\",\n    \"questions\": [\n        {\n            \"question_id\": \"809b36dd-57c6-48a2-9d88-1f54cd09cfb6\",\n            \"position\": 1\n        },\n        {\n            \"question_id\": \"ba2f78a3-5175-4b47-a79b-075600c9827a\",\n            \"position\": 2\n        },\n        {\n            \"question_id\": \"205217c7-7184-43fc-88dd-82bf54e231f4\",\n            \"position\": 3\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/create"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"bac13833-defc-4a2e-b53f-3f79283df38c\",\n    \"name\": \"Morning habits survey\",\n    \"status\": \"UNCHECKED\",\n    \"status_id\": 2,\n    \"questions\": [\n        {\n            \"question_id\": \"809b36dd-57c6-48a2-9d88-1f54cd09cfb6\",\n            \"position\": 1\n        },\n        {\n            \"question_id\": \"ba2f78a3-5175-4b47-a79b-075600c9827a\",\n            \"position\": 2\n        },\n        {\n            \"question_id\": \"205217c7-7184-43fc-88dd-82bf54e231f4\",\n            \"position\": 3\n        }\n    ]\n}"},{"id":"c01a2d1c-918e-42c4-9793-4490aca1dff9","name":"Save as draft","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"name\": \"Smartphone survey\",\n    \"image\": \"\",\n    \"questions\": [\n        {\n            \"question_id\": \"554d5e9b-9d21-4542-9bc3-ed9b95f1f641\",\n            \"position\": 1\n        }\n    ],\n    \"is_submitted\": false\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/create"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"bfbe6991-ed79-4a96-958d-2000c7695b8a\",\n    \"name\": \"Smartphone survey\",\n    \"status\": \"DRAFTED\",\n    \"status_id\": 1,\n    \"questions\": [\n        {\n            \"question_id\": \"554d5e9b-9d21-4542-9bc3-ed9b95f1f641\",\n            \"position\": 1\n        }\n    ]\n}"},{"id":"9fa85384-5c44-4ec0-bf63-e36c2da5a7a0","name":"400 - position out of range","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"name\": \"Morning habits survey\",\n    \"image\": \"survey_banner_20261013-094500.789.jpeg\",\n    \"questions\": [\n        {\n            \"question_id\": \"ba2f78a3-5175-4b47-a79b-075600c9827a\",\n            \"position\": 2\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/create"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Missing required body field\",\n    \"detail\": \"Survey question position cannot be higher than question count.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"},{"id":"828eb6c3-f4a6-4137-96db-3610deabb263","name":"400 - question not approved","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"name\": \"Morning habits survey\",\n    \"image\": \"survey_banner_20261013-094500.789.jpeg\",\n    \"questions\": [\n        {\n            \"question_id\": \"8e1f32b3-1e17-4287-9c34-57ed9be8a6a1\",\n            \"position\": 1\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/create"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Invalid survey question\",\n    \"detail\": \"Question #8e1f32b3-1e17-4287-9c34-57ed9be8a6a1 is not approved.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"51091b68-d97c-4de3-bf08-18d736ad4dea"},{"name":"Get List","id":"e4b1ab22-a291-4850-8854-3fe22253a56f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys?title=&status=&type=DRAFT&role_names=&page=0&size=10","description":"<p>Lists surveys for the dashboard tables, with filtering, paging and sorting.</p>\n<p>All query parameters are optional. To pick a survey for a campaign, use <code>type=ACTIVE</code>.</p>\n<h3 id=\"list-types\">List types</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>type</th>\n<th>Returns</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>DRAFT</code> (default, or <code>1</code>)</td>\n<td>Not archived and status is not APPROVED, so DRAFTED, UNCHECKED and REJECTED</td>\n<td>With a Checker-only <code>role_names</code>, DRAFTED items are hidden</td>\n</tr>\n<tr>\n<td><code>ACTIVE</code> (or <code>2</code>)</td>\n<td>Not archived and status is APPROVED</td>\n<td>Only these can go into a survey or campaign</td>\n</tr>\n<tr>\n<td><code>ARCHIVED</code> (or <code>3</code>)</td>\n<td>Archived (deleted) items in any status</td>\n<td></td>\n</tr>\n<tr>\n<td><code>ALL</code> (or <code>4</code>)</td>\n<td>Everything, archived items included</td>\n<td>With a Checker-only <code>role_names</code>, DRAFTED items are hidden</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"pagination-and-sorting\">Pagination and sorting</h3>\n<p>This uses standard Spring Data paging. Note that the parameter is <strong><code>size</code></strong>, not <code>limit</code>.</p>\n<ul>\n<li><code>page</code> is <strong>zero-based</strong>, so the first page is <code>page=0</code>. The default is <code>0</code>.</li>\n<li><code>size</code> is the page size. If you omit it, <strong>every matching row comes back in one page</strong> (capped at 1,000,000). A <code>size</code> of 10 is typical for a table.</li>\n<li><code>sort</code> takes database column names, as <code>sort=&lt;column&gt;,&lt;asc|desc&gt;</code>. The default is <code>created_date,desc</code>. Examples: <code>sort=sequence_id,asc</code>, <code>sort=updated_date,desc</code>.</li>\n</ul>\n<p>Example: <code>page=0&amp;size=10</code> returns rows 1-10, and <code>page=1&amp;size=10</code> returns rows 11-20. Use <code>total_elements</code> and <code>total_pages</code> in the response to build the pager.</p>\n<h3 id=\"response\">Response</h3>\n<p>The response is a Spring <code>Page</code> object. The rows are in <strong><code>content</code></strong>; there is no <code>data</code> field.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>content</td>\n<td>The rows for this page (fields below)</td>\n</tr>\n<tr>\n<td>number</td>\n<td>The current page index (zero-based)</td>\n</tr>\n<tr>\n<td>size</td>\n<td>The requested page size</td>\n</tr>\n<tr>\n<td>number_of_elements</td>\n<td>How many rows are in this page</td>\n</tr>\n<tr>\n<td>total_elements</td>\n<td>Total matching rows across all pages</td>\n</tr>\n<tr>\n<td>total_pages</td>\n<td>Total number of pages</td>\n</tr>\n<tr>\n<td>first / last</td>\n<td>Whether this is the first or last page</td>\n</tr>\n<tr>\n<td>empty</td>\n<td><code>true</code> if <code>content</code> is empty</td>\n</tr>\n<tr>\n<td>pageable, sort</td>\n<td>Echo of the paging and sort that were applied</td>\n</tr>\n</tbody>\n</table>\n</div><p>Each row in <code>content</code>:</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>Survey UUID</td>\n</tr>\n<tr>\n<td>name</td>\n<td>Survey name</td>\n</tr>\n<tr>\n<td>banner_image</td>\n<td>Banner path (<code>\"\"</code> if none)</td>\n</tr>\n<tr>\n<td>sequence_id</td>\n<td>e.g. 007</td>\n</tr>\n<tr>\n<td>status</td>\n<td>DRAFTED, UNCHECKED, APPROVED or REJECTED</td>\n</tr>\n<tr>\n<td>type</td>\n<td><code>DRAFT</code>, <code>ACTIVE</code> or <code>ARCHIVED</code></td>\n</tr>\n<tr>\n<td>deleted_at</td>\n<td>Archive time (<code>yyyy-MM-dd HH:mm:ss</code>), or <code>null</code></td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","surveys"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[{"description":{"content":"<p>Case-insensitive partial match on the survey <strong>name</strong>. Example: <code>morning</code></p>\n","type":"text/plain"},"key":"title","value":""},{"description":{"content":"<p>Filter by status name or ID: <code>DRAFTED</code>/<code>1</code>, <code>UNCHECKED</code>/<code>2</code>, <code>APPROVED</code>/<code>3</code>, <code>REJECTED</code>/<code>4</code>. Applied within <code>type</code></p>\n","type":"text/plain"},"key":"status","value":""},{"description":{"content":"<p>Which list tab: <code>DRAFT</code> (default), <code>ACTIVE</code>, <code>ARCHIVED</code> or <code>ALL</code></p>\n","type":"text/plain"},"key":"type","value":"DRAFT"},{"description":{"content":"<p>Comma-separated roles of the logged-in dashboard user, e.g. <code>Survey.Maker,Survey.Checker</code>. This is <strong>not a filter on data</strong>. It only controls whether DRAFTED items are visible: if <code>Survey.Checker</code> is present <strong>without</strong> <code>Survey.Maker</code>, DRAFTED items are hidden from <code>type=DRAFT</code> and <code>type=ALL</code> (a checker has nothing to review until the maker submits). Leave it empty to show everything.</p>\n","type":"text/plain"},"key":"role_names","value":""},{"description":{"content":"<p>Zero-based page index. Default 0</p>\n","type":"text/plain"},"key":"page","value":"0"},{"description":{"content":"<p>Page size. Omit it to get all matching rows in one page</p>\n","type":"text/plain"},"key":"size","value":"10"},{"disabled":true,"description":{"content":"<p>Sort column and direction. Default <code>created_date,desc</code></p>\n","type":"text/plain"},"key":"sort","value":"created_date,desc"}],"variable":[]}},"response":[{"id":"755395c3-5595-4e9f-8699-ac9f09739679","name":"Active surveys (for campaign set-up)","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys?type=ACTIVE&page=0&size=10","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","surveys"],"query":[{"key":"type","value":"ACTIVE","type":"string","description":"Which list tab: `DRAFT` (default), `ACTIVE`, `ARCHIVED` or `ALL`"},{"key":"page","value":"0","type":"number","description":"Zero-based page index. Default 0"},{"key":"size","value":"10","type":"number","description":"Page size. Omit it to get all matching rows in one page"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"content\": [\n        {\n            \"id\": \"84b7dc11-fc79-4d87-a09a-31095334eb52\",\n            \"name\": \"Morning habits survey\",\n            \"banner_image\": \"/dashboard/surveys/images/survey_banner_20261013-094500.789.jpeg\",\n            \"sequence_id\": \"001\",\n            \"status\": \"APPROVED\",\n            \"type\": \"ACTIVE\",\n            \"deleted_at\": null\n        }\n    ],\n    \"pageable\": {\n        \"page_number\": 0,\n        \"page_size\": 10,\n        \"sort\": {\n            \"sorted\": true,\n            \"empty\": false,\n            \"unsorted\": false\n        },\n        \"offset\": 0,\n        \"paged\": true,\n        \"unpaged\": false\n    },\n    \"last\": true,\n    \"total_pages\": 1,\n    \"total_elements\": 1,\n    \"size\": 10,\n    \"number\": 0,\n    \"sort\": {\n        \"sorted\": true,\n        \"empty\": false,\n        \"unsorted\": false\n    },\n    \"first\": true,\n    \"number_of_elements\": 1,\n    \"empty\": false\n}"},{"id":"066e5bab-005f-4552-b138-056794450a36","name":"Draft tab, searched by name","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys?title=smart&type=DRAFT&role_names=Survey.Maker&page=0&size=10","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","surveys"],"query":[{"key":"title","value":"smart","type":"string","description":"Case-insensitive partial match on the survey **name**. Example: `morning`"},{"key":"type","value":"DRAFT","type":"string","description":"Which list tab: `DRAFT` (default), `ACTIVE`, `ARCHIVED` or `ALL`"},{"key":"role_names","value":"Survey.Maker","type":"string","description":"Comma-separated roles of the logged-in dashboard user, e.g. `Survey.Maker,Survey.Checker`. This is **not a filter on data**. It only controls whether DRAFTED items are visible: if `Survey.Checker` is present **without** `Survey.Maker`, DRAFTED items are hidden from `type=DRAFT` and `type=ALL` (a checker has nothing to review until the maker submits). Leave it empty to show everything."},{"key":"page","value":"0","type":"number","description":"Zero-based page index. Default 0"},{"key":"size","value":"10","type":"number","description":"Page size. Omit it to get all matching rows in one page"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"content\": [\n        {\n            \"id\": \"f6ba82a8-e33f-4d40-aeaa-49dcd6adf6ed\",\n            \"name\": \"Smartphone survey\",\n            \"banner_image\": \"/dashboard/surveys/images/survey_banner_20261013-094500.789.jpeg\",\n            \"sequence_id\": \"002\",\n            \"status\": \"DRAFTED\",\n            \"type\": \"DRAFT\",\n            \"deleted_at\": null\n        }\n    ],\n    \"pageable\": {\n        \"page_number\": 0,\n        \"page_size\": 10,\n        \"sort\": {\n            \"sorted\": true,\n            \"empty\": false,\n            \"unsorted\": false\n        },\n        \"offset\": 0,\n        \"paged\": true,\n        \"unpaged\": false\n    },\n    \"last\": true,\n    \"total_pages\": 1,\n    \"total_elements\": 1,\n    \"size\": 10,\n    \"number\": 0,\n    \"sort\": {\n        \"sorted\": true,\n        \"empty\": false,\n        \"unsorted\": false\n    },\n    \"first\": true,\n    \"number_of_elements\": 1,\n    \"empty\": false\n}"}],"_postman_id":"e4b1ab22-a291-4850-8854-3fe22253a56f"},{"name":"Get Detail","id":"b7fc1ab2-594b-4cca-84a4-452bc8cbf462","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/details/:id","description":"<p>Returns one survey with its questions, for the dashboard detail and edit screen.</p>\n<p>This works for any status, including archived surveys.</p>\n<h3 id=\"response-200\">Response: 200</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>Survey UUID</td>\n</tr>\n<tr>\n<td>name</td>\n<td>Survey name</td>\n</tr>\n<tr>\n<td>image</td>\n<td>Banner path for <strong>Get Image</strong>, or <code>\"\"</code> if none</td>\n</tr>\n<tr>\n<td>status</td>\n<td>DRAFTED, UNCHECKED, APPROVED or REJECTED</td>\n</tr>\n<tr>\n<td>rejection_reason</td>\n<td>The checker's reason, or <code>\"\"</code>/<code>null</code></td>\n</tr>\n<tr>\n<td>sequence_id</td>\n<td>e.g. 007</td>\n</tr>\n<tr>\n<td>survey_category</td>\n<td><code>Drafted Survey</code>, <code>Active Survey</code> (APPROVED) or <code>Archived Survey</code></td>\n</tr>\n<tr>\n<td>questions[]</td>\n<td><code>question_id</code>, <code>question_sequence_id</code>, <code>question_type</code> (name), <code>question_title</code>, <code>question_image</code> (path or <code>\"\"</code>), <code>position</code>. Sorted by <code>position</code></td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"errors\">Errors</h3>\n<ul>\n<li><strong>404</strong> <em>Resource Not Found</em>: unknown survey ID.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","surveys","details",":id"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"0ee3fa21-d783-433b-b858-0a38b728b26b","description":{"content":"<p><strong>UUID</strong>. The survey's ID, from Get List or the Create response. Example: <code>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</code></p>\n","type":"text/plain"},"type":"any","value":"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37","key":"id"}]}},"response":[{"id":"cb7d9a41-d44d-41b2-af1c-2794280ecb71","name":"Approved survey","originalRequest":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/details/9c825713-b0e4-4291-b992-c99bddb69fde"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"9c825713-b0e4-4291-b992-c99bddb69fde\",\n    \"name\": \"Morning habits survey\",\n    \"image\": \"/dashboard/surveys/images/survey_banner_20261013-094500.789.jpeg\",\n    \"status\": \"APPROVED\",\n    \"rejection_reason\": \"\",\n    \"sequence_id\": \"001\",\n    \"survey_category\": \"Active Survey\",\n    \"questions\": [\n        {\n            \"question_id\": \"1d834123-e696-47d5-9316-c5b02d7abfc1\",\n            \"question_sequence_id\": \"I-000001\",\n            \"question_type\": \"INFORMATION\",\n            \"question_title\": \"Before you start\",\n            \"question_image\": \"\",\n            \"position\": 1\n        },\n        {\n            \"question_id\": \"849dfb6a-f856-42b5-8f5b-c1963eb69cbf\",\n            \"question_sequence_id\": \"S-000001\",\n            \"question_type\": \"SINGLE_SELECTION\",\n            \"question_title\": \"What do you drink in the morning?\",\n            \"question_image\": \"/dashboard/question-banks/images/question_banner_20261013-093000.123.jpeg\",\n            \"position\": 2\n        },\n        {\n            \"question_id\": \"8468d097-f2f8-4426-8f59-5b6d35b06b37\",\n            \"question_sequence_id\": \"F-000008\",\n            \"question_type\": \"FREE_TEXT\",\n            \"question_title\": \"How can we improve our app?\",\n            \"question_image\": \"\",\n            \"position\": 3\n        }\n    ]\n}"},{"id":"8591530f-039b-44d9-85b1-a92fb72d7492","name":"404 - unknown id","originalRequest":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/details/00000000-0000-0000-0000-000000000000"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Resource Not Found\",\n    \"detail\": \"The requested resource was not found.\",\n    \"status\": 404,\n    \"instance\": \"\",\n    \"errorKey\": \"resource_not_found\"\n}"}],"_postman_id":"b7fc1ab2-594b-4cca-84a4-452bc8cbf462"},{"name":"Get Image","id":"eaf0d91b-178f-4d67-921b-5a88e099528b","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/images/:name","description":"<p>Streams the raw bytes of a survey banner image from S3.</p>\n<p>The survey <code>image</code> path returned by Get Detail points here, e.g. <code>/dashboard/surveys/images/survey_banner_20261013-094500.789.jpeg</code>.</p>\n<ul>\n<li><strong>200</strong>: image bytes, with no <code>Content-Type</code> set.</li>\n<li><strong>404</strong> <em>Resource Not Found</em> / <em>Failed to retrieve S3 resource</em>: unknown file.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","surveys","images",":name"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"ac1074eb-8f10-4384-859d-4379163e971a","description":{"content":"<p>Image file name: the last segment of the survey <code>image</code>/<code>banner_image</code>, or of the Upload File <code>file_name</code></p>\n","type":"text/plain"},"type":"any","value":"survey_banner_20261013-094500.789.jpeg","key":"name"}]}},"response":[{"id":"e2f9dd95-8b46-44e0-ae7a-ddb9b91b9665","name":"200 - image bytes","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/images/:name","host":["https://gateway.test.youtap.systems/survey/sso"],"path":["dashboard","surveys","images",":name"],"variable":[{"key":"name","value":"survey_banner_20261013-094500.789.jpeg","description":"Image file name: the last segment of the survey `image`/`banner_image`, or of the Upload File `file_name`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[],"cookie":[],"responseTime":null,"body":""},{"id":"64a616cc-befe-465f-9083-6e4549aaa97e","name":"404 - unknown file","originalRequest":{"method":"GET","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/images/does_not_exist.jpeg"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Resource Not Found\",\n    \"detail\": \"Failed to retrieve S3 resource\",\n    \"status\": 404,\n    \"instance\": \"\",\n    \"errorKey\": \"resource_not_found\"\n}"}],"_postman_id":"eaf0d91b-178f-4d67-921b-5a88e099528b"},{"name":"Edit","id":"07eba551-aa29-4301-a627-f757c0806619","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"name\": \"Morning habits survey v2\",\n    \"image\": \"survey_banner_20261013-094500.789.jpeg\",\n    \"questions\": [\n        {\n            \"question_id\": \"1eb3355f-eee1-4920-8122-d7767522ae6e\",\n            \"position\": 1\n        },\n        {\n            \"question_id\": \"53478d75-b8c1-4e3b-8abc-850e4ee37568\",\n            \"position\": 2\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/edit/:id","description":"<p>Replaces a survey's name, image and question list. Send the complete survey, with the same body and validation as <strong>Create</strong>.</p>\n<h3 id=\"rules\">Rules</h3>\n<ul>\n<li><strong>Blocked while UNCHECKED</strong>: 400 <em>Unable to edit survey</em> / <em>Survey is on check.</em></li>\n<li>DRAFTED, REJECTED and APPROVED surveys can be edited. The status becomes <strong>UNCHECKED</strong> (<code>is_submitted: true</code>) or <strong>DRAFTED</strong> (<code>false</code>).<ul>\n<li>Editing an <strong>APPROVED</strong> survey therefore takes it offline for customers until it is re-approved.</li>\n</ul>\n</li>\n<li>Archived surveys are un-archived by an edit.</li>\n<li>The old question list is replaced entirely.</li>\n</ul>\n<h3 id=\"body\">Body</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>name</td>\n<td>string</td>\n<td>Yes</td>\n<td>Survey name shown to customers. Max 70 characters</td>\n</tr>\n<tr>\n<td>image</td>\n<td>string</td>\n<td>Yes</td>\n<td>Banner file name from <strong>Survey &gt; Upload File</strong>, or <code>\"\"</code> for none</td>\n</tr>\n<tr>\n<td>questions</td>\n<td>array</td>\n<td>Yes</td>\n<td>At least 1. The order customers see is set by <code>position</code>, not by array order</td>\n</tr>\n<tr>\n<td>questions[].question_id</td>\n<td>string</td>\n<td>Yes</td>\n<td>UUID of an <strong>APPROVED</strong> question (from Question Bank &gt; Get List with <code>type=ACTIVE</code>). No duplicates</td>\n</tr>\n<tr>\n<td>questions[].position</td>\n<td>number</td>\n<td>Yes</td>\n<td>1-based display order, from 1 to the number of questions</td>\n</tr>\n<tr>\n<td>is_submitted</td>\n<td>boolean</td>\n<td>Yes</td>\n<td><code>true</code> gives UNCHECKED (sent to a checker), <code>false</code> gives DRAFTED</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"response-200\">Response: 200</h3>\n<p><code>id</code>, <code>name</code>, <code>image</code> (stored file name), <code>status</code>, <code>status_id</code>, and <code>questions[]</code>, each with <code>question_id</code>, <code>question_sequence_id</code>, <code>question_title</code> and <code>position</code>.</p>\n<h3 id=\"errors\">Errors</h3>\n<p>The same as <strong>Create</strong>, plus the UNCHECKED rule above.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","surveys","edit",":id"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"068b9b6b-fe39-46fe-8981-5dc2d562071f","description":{"content":"<p><strong>UUID</strong>. The survey's ID, from Get List or the Create response. Example: <code>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</code></p>\n","type":"text/plain"},"type":"any","value":"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37","key":"id"}]}},"response":[{"id":"8fd735b8-e333-48a2-9133-851e63820f82","name":"Edit and resubmit","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"name\": \"Morning habits survey v2\",\n    \"image\": \"survey_banner_20261013-094500.789.jpeg\",\n    \"questions\": [\n        {\n            \"question_id\": \"1eb3355f-eee1-4920-8122-d7767522ae6e\",\n            \"position\": 1\n        },\n        {\n            \"question_id\": \"53478d75-b8c1-4e3b-8abc-850e4ee37568\",\n            \"position\": 2\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/edit/2ca4ceca-37f8-4b0b-99f8-98f6d433cb26"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"id\": \"2ca4ceca-37f8-4b0b-99f8-98f6d433cb26\",\n    \"name\": \"Morning habits survey v2\",\n    \"image\": \"survey_banner_20261013-094500.789.jpeg\",\n    \"status\": \"UNCHECKED\",\n    \"status_id\": 2,\n    \"questions\": [\n        {\n            \"question_id\": \"1eb3355f-eee1-4920-8122-d7767522ae6e\",\n            \"question_sequence_id\": \"S-000001\",\n            \"question_title\": \"What do you drink in the morning?\",\n            \"position\": 1\n        },\n        {\n            \"question_id\": \"53478d75-b8c1-4e3b-8abc-850e4ee37568\",\n            \"question_sequence_id\": \"F-000008\",\n            \"question_title\": \"How can we improve our app?\",\n            \"position\": 2\n        }\n    ]\n}"},{"id":"e87a9e46-4384-4d94-8a69-79e925e7f093","name":"400 - waiting for approval","originalRequest":{"method":"PUT","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"name\": \"Morning habits survey v2\",\n    \"image\": \"survey_banner_20261013-094500.789.jpeg\",\n    \"questions\": [\n        {\n            \"question_id\": \"1eb3355f-eee1-4920-8122-d7767522ae6e\",\n            \"position\": 1\n        },\n        {\n            \"question_id\": \"53478d75-b8c1-4e3b-8abc-850e4ee37568\",\n            \"position\": 2\n        }\n    ],\n    \"is_submitted\": true\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/edit/2ca4ceca-37f8-4b0b-99f8-98f6d433cb26"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Unable to edit survey\",\n    \"detail\": \"Survey is on check.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"07eba551-aa29-4301-a627-f757c0806619"},{"name":"Submit Approval","id":"bbea9736-1a31-400b-ae90-3ff11753a381","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": true,\n    \"reason\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/submit-approval/:id","description":"<p>The <strong>checker's decision</strong> on a survey that is waiting for review (UNCHECKED). Makers submit surveys with <code>is_submitted: true</code> on Create or Edit.</p>\n<p>Approving a survey also creates the answer statistics counters used by the mobile percentages. After approval, the survey ID can be used in a promotion-service-api Survey campaign.</p>\n<h3 id=\"body\">Body</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>approval_status</td>\n<td>boolean</td>\n<td>Yes</td>\n<td><code>true</code> gives <strong>APPROVED</strong>, <code>false</code> gives <strong>REJECTED</strong></td>\n</tr>\n<tr>\n<td>reason</td>\n<td>string / null</td>\n<td>When rejecting</td>\n<td>Rejection reason (<code>rejection_reason</code>). Ignored when approving</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"rules\">Rules</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Current state</th>\n<th>Result</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>UNCHECKED, and every question APPROVED</td>\n<td>200</td>\n</tr>\n<tr>\n<td>UNCHECKED, but a question is no longer APPROVED (it was edited after being added)</td>\n<td>400 <em>Invalid survey question</em> / <em>Question # is not approved.</em> (only when approving)</td>\n</tr>\n<tr>\n<td>DRAFTED</td>\n<td>400 <em>Could not submit survey approval</em> / <em>The survey is still in draft.</em></td>\n</tr>\n<tr>\n<td>APPROVED or REJECTED</td>\n<td>400 <em>Could not submit survey approval</em> / <em>The approval process for this survey has been finished.</em></td>\n</tr>\n<tr>\n<td>Archived</td>\n<td>404 <em>Resource Not Found</em> / <em>The survey is archived.</em></td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"response-200\">Response: 200</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>survey_id</td>\n<td>Survey UUID</td>\n</tr>\n<tr>\n<td>name</td>\n<td>Survey name</td>\n</tr>\n<tr>\n<td>sequence_id</td>\n<td>e.g. 007</td>\n</tr>\n<tr>\n<td>status</td>\n<td>APPROVED or REJECTED</td>\n</tr>\n<tr>\n<td>status_id</td>\n<td>3 (APPROVED) or 4 (REJECTED)</td>\n</tr>\n<tr>\n<td>rejection_reason</td>\n<td>The <code>reason</code> sent, or <code>\"\"</code></td>\n</tr>\n<tr>\n<td>question_id</td>\n<td><strong>Deprecated</strong>: the survey ID again, under its original name. Use <code>survey_id</code></td>\n</tr>\n<tr>\n<td>title</td>\n<td><strong>Deprecated</strong>: the survey name again, under its original name. Use <code>name</code></td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","surveys","submit-approval",":id"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"d3a199ad-ca92-440e-8bd6-b6b75b6f8fa0","description":{"content":"<p><strong>UUID</strong>. The survey's ID, from Get List or the Create response. Example: <code>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</code></p>\n","type":"text/plain"},"type":"any","value":"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37","key":"id"}]}},"response":[{"id":"46a53449-b66c-40dc-80d1-8893c3ca7448","name":"Approve","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": true,\n    \"reason\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/submit-approval/2909b387-38ab-4aa4-9ce0-7cd1fa45b87e"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"survey_id\": \"2909b387-38ab-4aa4-9ce0-7cd1fa45b87e\",\n    \"name\": \"Morning habits survey\",\n    \"question_id\": \"2909b387-38ab-4aa4-9ce0-7cd1fa45b87e\",\n    \"title\": \"Morning habits survey\",\n    \"sequence_id\": \"001\",\n    \"status\": \"APPROVED\",\n    \"status_id\": 3,\n    \"rejection_reason\": \"\"\n}"},{"id":"431efae0-3eaf-47de-990c-aa74220e48bf","name":"Reject with reason","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": false,\n    \"reason\": \"Banner image is blurry.\"\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/submit-approval/0844d696-77d6-44d8-b3e2-2265e6dc6da2"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"survey_id\": \"0844d696-77d6-44d8-b3e2-2265e6dc6da2\",\n    \"name\": \"Morning habits survey\",\n    \"question_id\": \"0844d696-77d6-44d8-b3e2-2265e6dc6da2\",\n    \"title\": \"Morning habits survey\",\n    \"sequence_id\": \"002\",\n    \"status\": \"REJECTED\",\n    \"status_id\": 4,\n    \"rejection_reason\": \"Banner image is blurry.\"\n}"},{"id":"cda35350-9f7e-4324-89af-3d4a99e811e9","name":"400 - already decided","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": true,\n    \"reason\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/submit-approval/2909b387-38ab-4aa4-9ce0-7cd1fa45b87e"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Could not submit survey approval\",\n    \"detail\": \"The approval process for this survey has been finished.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"},{"id":"7f39fc01-9292-4ff2-b4c7-0d73239d2da2","name":"400 - question not approved","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"approval_status\": true,\n    \"reason\": null\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/submit-approval/4a2fdf24-52c8-443c-8e1d-91da777a6f3a"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Invalid survey question\",\n    \"detail\": \"Question #d6957fd0-452c-4e2f-8c7c-6845a8a46531 is not approved.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"bbea9736-1a31-400b-ae90-3ff11753a381"},{"name":"Delete","id":"608ccdb0-5d7d-46ca-97eb-768a76d1ee9f","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"DELETE","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/delete/:id","description":"<p>Archives (soft-deletes) a survey. It then appears under <code>type=ARCHIVED</code>. <strong>Edit</strong> restores it.</p>\n<h3 id=\"rules\">Rules</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Survey state</th>\n<th>Result</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>DRAFTED or REJECTED</td>\n<td>200 <code>{\"is_success\": true}</code></td>\n</tr>\n<tr>\n<td>UNCHECKED</td>\n<td>400 <em>Unable to edit survey</em> / <em>Survey is on check.</em></td>\n</tr>\n<tr>\n<td>APPROVED (active)</td>\n<td>400 <em>Action is unavailable</em> / <em>Survey 007 is currently active.</em></td>\n</tr>\n<tr>\n<td>Unknown ID</td>\n<td>404 <em>Resource Not Found</em></td>\n</tr>\n</tbody>\n</table>\n</div><p>Approved surveys cannot be archived, because a campaign may be using them.</p>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}},"urlObject":{"path":["dashboard","surveys","delete",":id"],"host":["https://gateway.test.youtap.systems/survey/sso"],"query":[],"variable":[{"id":"6c8eb55f-6bc3-44ba-a74e-c050da78e5d5","description":{"content":"<p><strong>UUID</strong>. The survey's ID, from Get List or the Create response. Example: <code>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</code></p>\n","type":"text/plain"},"type":"any","value":"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37","key":"id"}]}},"response":[{"id":"ae24c3b5-a3e7-4035-86ef-0484a40bdea7","name":"Archived","originalRequest":{"method":"DELETE","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/delete/beb28380-d608-408c-949d-8bbbc3fcee82"},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"is_success\": true\n}"},{"id":"b647bc64-b5fb-4ad3-8239-4fb17eed43d3","name":"400 - survey is active","originalRequest":{"method":"DELETE","header":[],"url":"https://gateway.test.youtap.systems/survey/sso/dashboard/surveys/delete/84d1095e-5488-4574-bd77-2c86297027ec"},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Action is unavailable\",\n    \"detail\": \"Survey 002 is currently active.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"608ccdb0-5d7d-46ca-97eb-768a76d1ee9f"}],"id":"2b8c2a64-f14a-408e-98cf-6a30368cff37","description":"<p>Assemble <strong>approved</strong> questions into surveys and run them through approval.</p>\n<p>An APPROVED survey can be linked to a promotion-service-api <strong>Survey campaign</strong>: the campaign's <code>url</code> is set to the survey <code>id</code>. Customers holding a coupon for that campaign can then take the survey in the app. See <em>Survey coupons</em> in the collection description.</p>\n<h2 id=\"rules\">Rules</h2>\n<ul>\n<li>A survey needs at least <strong>1</strong> question, and every question must be <strong>APPROVED</strong> when the survey is created or edited.</li>\n<li>Question <code>position</code>s are 1-based and must lie between 1 and the number of questions. The same question cannot be added twice.</li>\n<li>Name: max <strong>70</strong> characters.</li>\n<li><strong>Edit</strong> is blocked while the survey is UNCHECKED. On any other status it resets the status to DRAFTED or UNCHECKED.<ul>\n<li>Warning: editing an <strong>APPROVED</strong> survey that a live campaign uses makes it unavailable on mobile (<em>Survey is not available.</em>) until it is re-approved.</li>\n</ul>\n</li>\n<li><strong>Delete</strong> (archive) is only allowed for DRAFTED and REJECTED surveys.</li>\n<li><strong>Approving</strong> a survey creates the per-option answer counters behind <code>statistic_percentage</code> on mobile. A survey must be approved before customers can answer it.</li>\n</ul>\n","_postman_id":"2b8c2a64-f14a-408e-98cf-6a30368cff37","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","name":"Dashboard","type":"folder"}}}],"id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54","description":"<p>Endpoints for the <strong>Builder Portal / dashboard</strong>: managing the Question Bank and Surveys and approving them.</p>\n<p>The dashboard calls these endpoints through the gateway's <code>/survey/sso</code> route, with the signed-in user's Azure AD token (see <em>Authentication</em> in the collection description). This folder sends <code></code> as the bearer token. The current user's roles are passed as the <code>role_names</code> query parameter on the list endpoints.</p>\n<h2 id=\"statuses\">Statuses</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>ID</th>\n<th>Meaning</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>DRAFTED</td>\n<td>1</td>\n<td>Created or edited with <code>is_submitted: false</code>. Only the maker sees it</td>\n</tr>\n<tr>\n<td>UNCHECKED</td>\n<td>2</td>\n<td>Submitted (<code>is_submitted: true</code>) and waiting for a checker. It <strong>cannot be edited or deleted</strong> while in this state (surveys) or deleted (questions)</td>\n</tr>\n<tr>\n<td>APPROVED</td>\n<td>3</td>\n<td>Approved by a checker. Questions can be used in surveys, and surveys can be used in campaigns</td>\n</tr>\n<tr>\n<td>REJECTED</td>\n<td>4</td>\n<td>Rejected by a checker. Fix it with Edit and resubmit</td>\n</tr>\n</tbody>\n</table>\n</div><h2 id=\"list-types-type-query-parameter\">List types (<code>type</code> query parameter)</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>type</th>\n<th>Returns</th>\n<th>Notes</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code>DRAFT</code> (default, or <code>1</code>)</td>\n<td>Not archived and status is not APPROVED, so DRAFTED, UNCHECKED and REJECTED</td>\n<td>With a Checker-only <code>role_names</code>, DRAFTED items are hidden</td>\n</tr>\n<tr>\n<td><code>ACTIVE</code> (or <code>2</code>)</td>\n<td>Not archived and status is APPROVED</td>\n<td>Only these can go into a survey or campaign</td>\n</tr>\n<tr>\n<td><code>ARCHIVED</code> (or <code>3</code>)</td>\n<td>Archived (deleted) items in any status</td>\n<td></td>\n</tr>\n<tr>\n<td><code>ALL</code> (or <code>4</code>)</td>\n<td>Everything, archived items included</td>\n<td>With a Checker-only <code>role_names</code>, DRAFTED items are hidden</td>\n</tr>\n</tbody>\n</table>\n</div><p>The <code>status</code> filter is applied <strong>inside</strong> the chosen type. For example, <code>type=DRAFT&amp;status=REJECTED</code> lists rejected items, while <code>type=ACTIVE&amp;status=REJECTED</code> is always empty.</p>\n<p><code>question_type</code>, <code>status</code> and <code>type</code> all accept the enum name (case-insensitive) or its numeric ID. Unknown values are ignored, and an unknown <code>type</code> falls back to <code>DRAFT</code>.</p>\n<h2 id=\"categories\">Categories</h2>\n<p>Detail responses include a display category derived from status and archive state:</p>\n<ul>\n<li>Questions: <code>Drafted Question</code>, <code>Active Question</code> or <code>Archived Question</code>.</li>\n<li>Surveys: <code>Drafted Survey</code>, <code>Active Survey</code> or <code>Archived Survey</code>.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"_postman_id":"5ba7e5f2-ad5f-4cd4-8576-e96d9915ca54"},{"name":"Mobile","item":[{"name":"Survey Detail","id":"3d26399c-1e60-473e-a4f0-ca32c3ebb282","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.youtap-test.net/survey/api/v1/surveys/details/:id?customer_id=64211234567&campaign_id=5001","description":"<p>Loads a survey for a customer, after checking they are allowed to take it. This is the entry point when a customer opens a survey Activity.</p>\n<h3 id=\"what-it-checks-in-order\">What it checks (in order)</h3>\n<ol>\n<li>The survey exists (otherwise <strong>404</strong> <em>Resource Not Found</em>) and is <strong>APPROVED</strong> (otherwise <strong>404</strong> <em>Survey is not available.</em>).</li>\n<li>Unless <code>customer_id</code> is a whitelisted test customer:<ul>\n<li><strong>Coupon check.</strong> It calls promotion-service-api <code>GET /integration/customers/{customer_id}/campaign/{campaign_id}</code>:<ul>\n<li>a 404 there (no ACTIVE customer with that wallet ID, or no coupon in the campaign) gives <strong>400</strong> <em>Survey is not accessible</em> here, with promotion-service-api's message, e.g. <em>customer is not enrolled in this campaign</em>;</li>\n<li>a campaign ID mismatch gives <strong>400</strong> <em>Survey is not accessible</em> / <em>The survey is ineligible for customer.</em></li>\n<li>a campaign that is not ACTIVE gives <strong>400</strong> <em>Survey is not accessible</em> / <em>The campaign is not active.</em></li>\n<li>a coupon that is not ELIGIBLE (already ASSIGNED or DELETED after completion, or EXPIRED) gives <strong>400</strong> <em>Survey is not accessible</em> / <em>The customer's coupon for this campaign is ASSIGNED.</em></li>\n</ul>\n</li>\n<li><strong>Already-finished check.</strong> As a backstop, if the customer has a SKIP_REWARD answer, or every question already has a final answer, the response is <strong>400</strong> <em>Survey detail cannot be shown</em> / <em>You have already filled this survey.</em></li>\n</ul>\n</li>\n<li>Partially completed surveys <strong>are</strong> returned, so the app can resume. Use <strong>Get Customer Answer List</strong> to see which questions are done.</li>\n</ol>\n<h3 id=\"response-200\">Response: 200</h3>\n<p>The survey is wrapped in <strong><code>data</code></strong>. Questions are sorted by <code>position</code>.</p>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>data.id / data.name</td>\n<td>Survey UUID and name</td>\n</tr>\n<tr>\n<td>data.image_url</td>\n<td>Banner path for <strong>Survey Image</strong>, e.g. <code>/v1/surveys/images/survey_banner_...jpeg</code></td>\n</tr>\n<tr>\n<td>data.questions[].id</td>\n<td>Question UUID: send it as <code>question_id</code> in Fill Answer</td>\n</tr>\n<tr>\n<td>data.questions[].title</td>\n<td>Question text</td>\n</tr>\n<tr>\n<td>data.questions[].image_url</td>\n<td>Question banner path, or <code>\"\"</code></td>\n</tr>\n<tr>\n<td>data.questions[].question_type</td>\n<td><strong>Number</strong>: 1 BINARY, 2 FREE_TEXT, 3 SINGLE_SELECTION, 4 MULTIPLE_SELECTION, 5 INFORMATION</td>\n</tr>\n<tr>\n<td>data.questions[].question_type_name</td>\n<td>Type name</td>\n</tr>\n<tr>\n<td>data.questions[].is_selection</td>\n<td><code>true</code> for types 1, 3 and 4 (answer with option IDs)</td>\n</tr>\n<tr>\n<td>data.questions[].is_free_text</td>\n<td><code>true</code> for type 2 (answer with <code>answer_content</code>)</td>\n</tr>\n<tr>\n<td>data.questions[].show_feedback</td>\n<td>Show <code>answer_feedback</code> / <code>free_text_feedback</code> after answering</td>\n</tr>\n<tr>\n<td>data.questions[].position</td>\n<td>Display order (1-based)</td>\n</tr>\n<tr>\n<td>data.questions[].information</td>\n<td>Text for INFORMATION screens</td>\n</tr>\n<tr>\n<td>data.questions[].free_text_feedback</td>\n<td>Feedback after a free text answer</td>\n</tr>\n<tr>\n<td>data.questions[].answers</td>\n<td>Options <code>[{{id, answer, answer_feedback, image_url}}]</code>, or <code>null</code> for types 2 and 5. Send <code>id</code> in <code>question_option_ids</code></td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"other-errors\">Other errors</h3>\n<ul>\n<li><strong>400</strong> <em>Invalid parameter</em>: <code>campaign_id</code> is missing (<em>Required parameter campaign_id is missing.</em>) or not a number (<em>Parameter campaign_id has an invalid value.</em>), or <code>customer_id</code> contains <code>/</code>, <code>\\</code> or <code>..</code> (<em>Invalid customer ID.</em>).</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","name":"Mobile","type":"folder"}},"urlObject":{"path":["v1","surveys","details",":id"],"host":["https://gateway.youtap-test.net/survey/api"],"query":[{"description":{"content":"<p>Customer wallet ID / MSISDN, the same as promotion-service-api <code>walletId</code>. Example: <code>64211234567</code></p>\n","type":"text/plain"},"key":"customer_id","value":"64211234567"},{"description":{"content":"<p><strong>Required.</strong> promotion-service-api Survey campaign ID (coupon <code>campaignId</code>). Example: <code>5001</code></p>\n","type":"text/plain"},"key":"campaign_id","value":"5001"}],"variable":[{"id":"a2b4e3e0-a09a-4c2f-b491-7cdf406eb49b","description":{"content":"<p><strong>UUID</strong>. The survey's ID, taken from the coupon's <code>launchUrl</code> / <code>couponOfferMessage[].surveyId</code>. Example: <code>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</code></p>\n","type":"text/plain"},"type":"any","value":"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37","key":"id"}]}},"response":[{"id":"7bd80566-4493-4657-8b2e-7614df25b114","name":"Survey for an eligible customer","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/details/20fce7bf-e560-4eca-a3c8-b8389e3e4d0d?customer_id=64211234567&campaign_id=5001","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","details","20fce7bf-e560-4eca-a3c8-b8389e3e4d0d"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"},{"key":"campaign_id","value":"5001","type":"number","description":"**Required.** promotion-service-api Survey campaign ID (coupon `campaignId`). Example: `5001`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"{\n    \"data\": {\n        \"id\": \"20fce7bf-e560-4eca-a3c8-b8389e3e4d0d\",\n        \"name\": \"Morning habits survey\",\n        \"image_url\": \"/v1/surveys/images/survey_banner_20261013-094500.789.jpeg\",\n        \"questions\": [\n            {\n                \"id\": \"a1038d21-962f-4e7e-a074-2b07a8b804e2\",\n                \"title\": \"Before you start\",\n                \"image_url\": \"\",\n                \"question_type\": 5,\n                \"show_feedback\": false,\n                \"position\": 1,\n                \"information\": \"This survey takes about 2 minutes. Answer every question to earn your reward.\",\n                \"free_text_feedback\": null,\n                \"question_type_name\": \"INFORMATION\",\n                \"answers\": null,\n                \"is_free_text\": false,\n                \"is_selection\": false\n            },\n            {\n                \"id\": \"574c1cfc-a846-4482-a619-bfd3048e8c26\",\n                \"title\": \"What do you drink in the morning?\",\n                \"image_url\": \"/v1/surveys/images/question_banner_20261013-093000.123.jpeg\",\n                \"question_type\": 3,\n                \"show_feedback\": true,\n                \"position\": 2,\n                \"information\": \"\",\n                \"free_text_feedback\": null,\n                \"question_type_name\": \"SINGLE_SELECTION\",\n                \"answers\": [\n                    {\n                        \"id\": \"b418094c-551a-4845-ac71-746292c7ad75\",\n                        \"answer\": \"Coffee\",\n                        \"answer_feedback\": \"A classic way to start the day!\",\n                        \"image_url\": \"/v1/surveys/images/question_option_image_20261013-093105.456.png\"\n                    },\n                    {\n                        \"id\": \"45d8ac64-22a7-4b0a-8f87-714e09b2d0b3\",\n                        \"answer\": \"Tea\",\n                        \"answer_feedback\": \"Calm and refreshing.\",\n                        \"image_url\": \"\"\n                    },\n                    {\n                        \"id\": \"0b2024f9-3f62-4d9b-bf28-23fe85224592\",\n                        \"answer\": \"Juice\",\n                        \"answer_feedback\": \"Fruity!\",\n                        \"image_url\": \"\"\n                    }\n                ],\n                \"is_free_text\": false,\n                \"is_selection\": true\n            },\n            {\n                \"id\": \"462acca4-7c72-463e-bbdf-7a5b242a0163\",\n                \"title\": \"Which services do you use?\",\n                \"image_url\": \"\",\n                \"question_type\": 4,\n                \"show_feedback\": false,\n                \"position\": 3,\n                \"information\": \"\",\n                \"free_text_feedback\": null,\n                \"question_type_name\": \"MULTIPLE_SELECTION\",\n                \"answers\": [\n                    {\n                        \"id\": \"ef5ec421-deb2-4926-86b1-c2809d26e250\",\n                        \"answer\": \"Mobile data\",\n                        \"answer_feedback\": \"\",\n                        \"image_url\": \"\"\n                    },\n                    {\n                        \"id\": \"91bdc2fc-1557-4705-80af-30bf8086ef88\",\n                        \"answer\": \"Home broadband\",\n                        \"answer_feedback\": \"\",\n                        \"image_url\": \"\"\n                    },\n                    {\n                        \"id\": \"4fa1b722-a0bf-45b3-9234-9954c79ccce6\",\n                        \"answer\": \"TV streaming\",\n                        \"answer_feedback\": \"\",\n                        \"image_url\": \"\"\n                    }\n                ],\n                \"is_free_text\": false,\n                \"is_selection\": true\n            },\n            {\n                \"id\": \"5a10cb05-706d-4de2-9514-01211bb12473\",\n                \"title\": \"How can we improve our app?\",\n                \"image_url\": \"\",\n                \"question_type\": 2,\n                \"show_feedback\": true,\n                \"position\": 4,\n                \"information\": \"\",\n                \"free_text_feedback\": \"Thanks, we read every suggestion.\",\n                \"question_type_name\": \"FREE_TEXT\",\n                \"answers\": null,\n                \"is_free_text\": true,\n                \"is_selection\": false\n            }\n        ]\n    }\n}"},{"id":"ff54a561-6372-43d0-9ccc-e9fc16747a87","name":"400 - no coupon in this campaign","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/details/20fce7bf-e560-4eca-a3c8-b8389e3e4d0d?customer_id=64299999999&campaign_id=5001","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","details","20fce7bf-e560-4eca-a3c8-b8389e3e4d0d"],"query":[{"key":"customer_id","value":"64299999999","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"},{"key":"campaign_id","value":"5001","type":"number","description":"**Required.** promotion-service-api Survey campaign ID (coupon `campaignId`). Example: `5001`"}]}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Survey is not accessible\",\n    \"detail\": \"customer is not enrolled in this campaign\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"},{"id":"23662b5f-3c20-4d6f-a3d9-62a390a77ccf","name":"400 - already completed","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/details/20fce7bf-e560-4eca-a3c8-b8389e3e4d0d?customer_id=64211234567&campaign_id=5001","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","details","20fce7bf-e560-4eca-a3c8-b8389e3e4d0d"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"},{"key":"campaign_id","value":"5001","type":"number","description":"**Required.** promotion-service-api Survey campaign ID (coupon `campaignId`). Example: `5001`"}]}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Survey is not accessible\",\n    \"detail\": \"The customer's coupon for this campaign is ASSIGNED.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"},{"id":"28b37e40-24fa-48e0-a724-f67fa95e90b5","name":"404 - survey not approved","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/details/f16c43a6-bcc3-45d3-adcd-ae12f2b8be85?customer_id=64211234567&campaign_id=5001","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","details","f16c43a6-bcc3-45d3-adcd-ae12f2b8be85"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"},{"key":"campaign_id","value":"5001","type":"number","description":"**Required.** promotion-service-api Survey campaign ID (coupon `campaignId`). Example: `5001`"}]}},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Resource Not Found\",\n    \"detail\": \"Survey is not available.\",\n    \"status\": 404,\n    \"instance\": \"\",\n    \"errorKey\": \"resource_not_found\"\n}"},{"id":"e911517b-ee1d-4b05-a4c3-19a421202efe","name":"400 - missing campaign_id","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/details/20fce7bf-e560-4eca-a3c8-b8389e3e4d0d?customer_id=64211234567","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","details","20fce7bf-e560-4eca-a3c8-b8389e3e4d0d"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Invalid parameter\",\n    \"detail\": \"Required parameter campaign_id is missing.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"3d26399c-1e60-473e-a4f0-ca32c3ebb282"},{"name":"Survey Image","id":"4cf2c78e-ba26-4a23-b53d-e33e0b3d0303","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.youtap-test.net/survey/api/v1/surveys/images/:name","description":"<p>Streams a survey, question or option image. Survey Detail returns <code>image_url</code> values such as <code>/v1/surveys/images/survey_banner_20261013-094500.789.jpeg</code>. Prefix them with <code>https://gateway.youtap-test.net/survey/api</code>.</p>\n<ul>\n<li><strong>200</strong>: image bytes, with no <code>Content-Type</code> set (use the file extension).</li>\n<li><strong>404</strong> <em>Resource Not Found</em> / <em>Failed to retrieve S3 resource</em>: unknown file.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","name":"Mobile","type":"folder"}},"urlObject":{"path":["v1","surveys","images",":name"],"host":["https://gateway.youtap-test.net/survey/api"],"query":[],"variable":[{"id":"dc914672-3196-49f6-9f8a-c4efc27cc2cd","description":{"content":"<p>Image file name: the last segment of any <code>image_url</code> in the Survey Detail response</p>\n","type":"text/plain"},"type":"any","value":"survey_banner_20261013-094500.789.jpeg","key":"name"}]}},"response":[{"id":"3d17d2dd-abd3-4503-b5c2-f20128d6d860","name":"200 - image bytes","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/images/:name","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","images",":name"],"variable":[{"key":"name","value":"survey_banner_20261013-094500.789.jpeg","description":"Image file name: the last segment of any `image_url` in the Survey Detail response"}]}},"status":"OK","code":200,"_postman_previewlanguage":"text","header":[],"cookie":[],"responseTime":null,"body":""},{"id":"1f2f263c-e44f-49b3-8887-6f017a5a7e3c","name":"404 - unknown file","originalRequest":{"method":"GET","header":[],"url":"https://gateway.youtap-test.net/survey/api/v1/surveys/images/does_not_exist.jpeg"},"status":"Not Found","code":404,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Resource Not Found\",\n    \"detail\": \"Failed to retrieve S3 resource\",\n    \"status\": 404,\n    \"instance\": \"\",\n    \"errorKey\": \"resource_not_found\"\n}"}],"_postman_id":"4cf2c78e-ba26-4a23-b53d-e33e0b3d0303"},{"name":"Fill Answer","id":"4f8cefb5-fbc5-40bc-8377-a8ae0029c64c","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"0d2192e2-a3ca-477a-86cb-35602e8ac0f6\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [],\n    \"is_select\": false,\n    \"answer_content\": \"\",\n    \"reward_status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234567","description":"<p>Saves a customer's answer to <strong>one</strong> question.</p>\n<p>Call it once per question, including INFORMATION questions. When the call completes the survey, it also settles the survey coupon in promotion-service-api.</p>\n<h3 id=\"body\">Body</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Type</th>\n<th>Required</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>survey_id</td>\n<td>string</td>\n<td>Yes</td>\n<td>Survey UUID</td>\n</tr>\n<tr>\n<td>question_id</td>\n<td>string</td>\n<td>Yes</td>\n<td>Question UUID (<code>data.questions[].id</code>)</td>\n</tr>\n<tr>\n<td>campaign_id</td>\n<td>number</td>\n<td>Yes</td>\n<td>promotion-service-api campaign ID. Must match the Survey Detail <code>campaign_id</code></td>\n</tr>\n<tr>\n<td>question_option_ids</td>\n<td>string[]</td>\n<td>Yes</td>\n<td>Selected option IDs (<code>answers[].id</code>): 1 for BINARY or SINGLE_SELECTION, 1+ for MULTIPLE_SELECTION. Use <strong><code>[]</code></strong> for FREE_TEXT and INFORMATION</td>\n</tr>\n<tr>\n<td>is_select</td>\n<td>boolean</td>\n<td>Yes</td>\n<td><code>true</code> when options are selected (counts towards statistics), <code>false</code> for free text, information or skip</td>\n</tr>\n<tr>\n<td>answer_content</td>\n<td>string</td>\n<td>Yes</td>\n<td>Free text answer, max <strong>340</strong> characters. Use <strong><code>\"\"</code></strong> for other types (not <code>null</code>)</td>\n</tr>\n<tr>\n<td>reward_status</td>\n<td>string</td>\n<td>Yes</td>\n<td><code>COMPLETED</code>, <code>SKIP_REWARD</code> or <code>INCOMPLETE</code> (uppercase). See the Mobile folder</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"what-happens\">What happens</h3>\n<ol>\n<li>If the question already has a final answer (COMPLETED or SKIP_REWARD) for this customer and campaign, the response is <strong>400</strong> <em>Data exist</em> / <em>Customer already fill the answer.</em> INCOMPLETE answers are overwritten.</li>\n<li>The answer is saved:<ul>\n<li><strong>With option IDs:</strong> one answer row per selected option; previous INCOMPLETE rows are replaced; option statistics are incremented when <code>is_select</code> is true and the answer is final (not INCOMPLETE).</li>\n<li><strong>Without option IDs:</strong> one answer row holding <code>answer_content</code>.</li>\n</ul>\n</li>\n<li><strong>Completion check.</strong> If every question in the survey now has a final answer, promotion-service-api is called: <code>POST /integration/customers/{customer_id}/campaign/{campaign_id}</code> with <code>{\"status\": \"ASSIGNED\" | \"DELETED\", \"initiator\": \"survey-builder\"}</code>.<ul>\n<li><strong>ASSIGNED</strong> if all answers are COMPLETED: the coupon's <code>offerValue</code> is credited to the customer.</li>\n<li><strong>DELETED</strong> if any answer is SKIP_REWARD: no reward, and the coupon is removed from the app.</li>\n<li>If that call fails but the coupon already has the requested status (e.g. a retry after a lost response), the answer is saved as normal.</li>\n<li>If it fails otherwise (e.g. the coupon is no longer ELIGIBLE, the campaign is not ACTIVE, or the service is unreachable), this request returns <strong>502</strong> <em>Survey could not be completed</em> (with promotion-service-api's message as <code>detail</code>) and <strong>the answer is not saved</strong> (the transaction rolls back), so it can be retried.</li>\n</ul>\n</li>\n<li>For COMPLETED and SKIP_REWARD answers, a <code>survey</code> business event is published to EventBridge. A failure here is logged and does not affect the answer.</li>\n</ol>\n<h3 id=\"response-200-always-an-array\">Response: 200 (always an array)</h3>\n<ul>\n<li><strong>Selection questions:</strong> <strong>one entry per option of the question</strong>, not only the selected ones. Use it to show the result straight after answering.</li>\n<li><strong>Free text and information questions:</strong> a single entry.</li>\n</ul>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>Answer row UUID, or <code>\"\"</code> for options that were not selected</td>\n</tr>\n<tr>\n<td>customer_id / survey_id / question_id</td>\n<td>Echo of the request</td>\n</tr>\n<tr>\n<td>question_option_id</td>\n<td>The option this entry describes (<code>\"\"</code> for free text and information)</td>\n</tr>\n<tr>\n<td>is_select</td>\n<td><code>true</code> if the customer chose this option</td>\n</tr>\n<tr>\n<td>answer_content</td>\n<td>Free text answer (<code>\"\"</code> for selections)</td>\n</tr>\n<tr>\n<td>statistic_percentage</td>\n<td>Rounded percentage of all customers' selections for this question that chose this option (0 for free text)</td>\n</tr>\n<tr>\n<td>reward_status</td>\n<td>The <code>reward_status</code> that was saved</td>\n</tr>\n</tbody>\n</table>\n</div><h3 id=\"errors\">Errors</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Status</th>\n<th>title / detail</th>\n<th>Cause</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>400</td>\n<td>Data exist / Customer already fill the answer.</td>\n<td>Question already has a final answer</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Survey answer content max limit reach / Max content length is 340 characters.</td>\n<td><code>answer_content</code> too long</td>\n</tr>\n<tr>\n<td>404</td>\n<td>Resource Not Found</td>\n<td>Unknown <code>question_id</code>, or survey not approved (no statistics)</td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field / Required field: ...</td>\n<td>A body field is missing or <code>null</code></td>\n</tr>\n<tr>\n<td>400</td>\n<td>Missing required body field / Invalid reward status type.</td>\n<td><code>reward_status</code> is not COMPLETED, SKIP_REWARD or INCOMPLETE</td>\n</tr>\n<tr>\n<td>502</td>\n<td>Survey could not be completed</td>\n<td>The promotion-service-api completion call failed. The answer is not saved</td>\n</tr>\n</tbody>\n</table>\n</div>","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","name":"Mobile","type":"folder"}},"urlObject":{"path":["v1","surveys","fill"],"host":["https://gateway.youtap-test.net/survey/api"],"query":[{"description":{"content":"<p>Customer wallet ID / MSISDN, the same as promotion-service-api <code>walletId</code>. Example: <code>64211234567</code></p>\n","type":"text/plain"},"key":"customer_id","value":"64211234567"}],"variable":[]}},"response":[{"id":"e5f4cf8e-fe91-4e42-a48b-084562ae59cc","name":"Single selection","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"dfe69aaa-db64-47ed-85d6-562e2e2e005b\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [\n        \"8851c19b-d72e-43a9-a6bb-2939a4f9a8ad\"\n    ],\n    \"is_select\": true,\n    \"answer_content\": \"\",\n    \"reward_status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234567","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"d4ae529e-502b-4854-8221-90f8d8cb4854\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"dfe69aaa-db64-47ed-85d6-562e2e2e005b\",\n        \"question_option_id\": \"8851c19b-d72e-43a9-a6bb-2939a4f9a8ad\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": true\n    },\n    {\n        \"id\": \"\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"dfe69aaa-db64-47ed-85d6-562e2e2e005b\",\n        \"question_option_id\": \"4f366d20-830f-4fa4-b568-e9e1f183e17d\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": false\n    },\n    {\n        \"id\": \"\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"dfe69aaa-db64-47ed-85d6-562e2e2e005b\",\n        \"question_option_id\": \"dea5fd65-075a-446e-b98b-181af9dbd108\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": false\n    }\n]"},{"id":"86897cf3-0ea8-4fa8-90d5-e5b16ad73a87","name":"Multiple selection","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"2c46d74e-76b8-4421-a257-5a2acb71f9e4\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [\n        \"70d164ab-6294-45c6-9c70-f96af3a10af1\",\n        \"9f3fa017-64ef-4528-8440-1dd34c6679d2\"\n    ],\n    \"is_select\": true,\n    \"answer_content\": \"\",\n    \"reward_status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234567","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"02d453a7-6b9b-4796-9275-8e52b75b9a6c\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"2c46d74e-76b8-4421-a257-5a2acb71f9e4\",\n        \"question_option_id\": \"70d164ab-6294-45c6-9c70-f96af3a10af1\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": true\n    },\n    {\n        \"id\": \"\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"2c46d74e-76b8-4421-a257-5a2acb71f9e4\",\n        \"question_option_id\": \"c8658c68-eef2-4f04-956b-04015bd1ed8a\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": false\n    },\n    {\n        \"id\": \"77f0135c-2c89-4050-9001-15f494a49c66\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"2c46d74e-76b8-4421-a257-5a2acb71f9e4\",\n        \"question_option_id\": \"9f3fa017-64ef-4528-8440-1dd34c6679d2\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": true\n    }\n]"},{"id":"ae813ba7-eea4-44b0-b9f9-372e7ae31f59","name":"Information screen (mark as seen)","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"0d2192e2-a3ca-477a-86cb-35602e8ac0f6\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [],\n    \"is_select\": false,\n    \"answer_content\": \"\",\n    \"reward_status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234567","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"d9e7564d-9187-450d-b57e-462b11759b05\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"0d2192e2-a3ca-477a-86cb-35602e8ac0f6\",\n        \"question_option_id\": \"\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": false\n    }\n]"},{"id":"08290232-cc81-4573-8db8-0a1469a7527c","name":"Free text - last question, coupon ASSIGNED","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"0017c134-abde-4dff-9f4a-646d2e1fe9df\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [],\n    \"is_select\": false,\n    \"answer_content\": \"Add a dark mode please!\",\n    \"reward_status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234567","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"a5aa8562-ec46-4b8c-b9a7-617891adbbf1\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"0017c134-abde-4dff-9f4a-646d2e1fe9df\",\n        \"question_option_id\": \"\",\n        \"answer_content\": \"Add a dark mode please!\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": false\n    }\n]"},{"id":"b4ee1dfb-223a-403b-8ede-15c03cc56e0e","name":"Free text - skipped, coupon DELETED","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"0017c134-abde-4dff-9f4a-646d2e1fe9df\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [],\n    \"is_select\": false,\n    \"answer_content\": \"\",\n    \"reward_status\": \"SKIP_REWARD\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234568","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234568","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"fe7049b9-ce5b-4638-817c-a2cca0b61ee1\",\n        \"customer_id\": \"64211234568\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"0017c134-abde-4dff-9f4a-646d2e1fe9df\",\n        \"question_option_id\": \"\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"SKIP_REWARD\",\n        \"is_select\": false\n    }\n]"},{"id":"8073ee00-048f-4431-98a8-a0ca4956025f","name":"Free text - save draft (INCOMPLETE)","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"0017c134-abde-4dff-9f4a-646d2e1fe9df\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [],\n    \"is_select\": false,\n    \"answer_content\": \"Add a dark\",\n    \"reward_status\": \"INCOMPLETE\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234567","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"a5aa8562-ec46-4b8c-b9a7-617891adbbf1\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n        \"question_id\": \"0017c134-abde-4dff-9f4a-646d2e1fe9df\",\n        \"question_option_id\": \"\",\n        \"answer_content\": \"Add a dark\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"INCOMPLETE\",\n        \"is_select\": false\n    }\n]"},{"id":"e5d8c26d-a76b-49c7-8cde-23037ff97aa2","name":"400 - already answered","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"dfe69aaa-db64-47ed-85d6-562e2e2e005b\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [\n        \"4f366d20-830f-4fa4-b568-e9e1f183e17d\"\n    ],\n    \"is_select\": true,\n    \"answer_content\": \"\",\n    \"reward_status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234567","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234567","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Data exist\",\n    \"detail\": \"Customer already fill the answer.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"},{"id":"b237c54d-0aa9-4c6d-aa8c-7a71f041d7fc","name":"502 - coupon could not be settled","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"0017c134-abde-4dff-9f4a-646d2e1fe9df\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [],\n    \"is_select\": false,\n    \"answer_content\": \"Add a dark mode please!\",\n    \"reward_status\": \"COMPLETED\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234570","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234570","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"Bad Gateway","code":502,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Survey could not be completed\",\n    \"detail\": \"coupon status is not eligible\",\n    \"status\": 502,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_gateway\"\n}"},{"id":"1016cdac-8c67-4580-a7b9-7cccb795a94f","name":"400 - invalid reward status","originalRequest":{"method":"POST","header":[{"key":"Content-Type","value":"application/json","type":"text"}],"body":{"mode":"raw","raw":"{\n    \"survey_id\": \"31d637d4-11a9-4d49-b5b4-ddfbc0af81f9\",\n    \"question_id\": \"0017c134-abde-4dff-9f4a-646d2e1fe9df\",\n    \"campaign_id\": 5001,\n    \"question_option_ids\": [],\n    \"is_select\": false,\n    \"answer_content\": \"Add a dark mode please!\",\n    \"reward_status\": \"DONE\"\n}","options":{"raw":{"language":"json"}}},"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/fill?customer_id=64211234569","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","fill"],"query":[{"key":"customer_id","value":"64211234569","type":"string","description":"Customer wallet ID / MSISDN, the same as promotion-service-api `walletId`. Example: `64211234567`"}]}},"status":"Bad Request","code":400,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/problem+json"}],"cookie":[],"responseTime":null,"body":"{\n    \"type\": \"\",\n    \"title\": \"Missing required body field\",\n    \"detail\": \"Invalid reward status type.\",\n    \"status\": 400,\n    \"instance\": \"\",\n    \"errorKey\": \"bad_request\"\n}"}],"_postman_id":"4f8cefb5-fbc5-40bc-8377-a8ae0029c64c"},{"name":"Get Customer Answer List","id":"18ac83c5-14ba-4308-bf0a-fc4702ec87d7","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.youtap-test.net/survey/api/v1/surveys/:surveyId/:customerId?campaign_id=5001","description":"<p>Returns the customer's progress through a survey: <strong>one entry per question in the survey</strong>, answered or not.</p>\n<p>Use it to resume a partly completed survey (skip to the first entry with <code>is_answer: false</code>) or to show a summary.</p>\n<p><code>campaign_id</code> is <strong>required</strong>. Answers are scoped to the campaign.</p>\n<h3 id=\"response-200-array\">Response: 200 (array)</h3>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Field</th>\n<th>Description</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>id</td>\n<td>Answer row UUID, or <code>\"\"</code> if unanswered</td>\n</tr>\n<tr>\n<td>customer_id / survey_id / question_id</td>\n<td>Identifiers</td>\n</tr>\n<tr>\n<td>answer_content</td>\n<td>Free text answer (<code>\"\"</code> for selection questions)</td>\n</tr>\n<tr>\n<td>is_answer</td>\n<td><code>true</code> if the question has been answered. For free text and information questions it is only <code>true</code> once the answer is final (not INCOMPLETE)</td>\n</tr>\n<tr>\n<td>question_options</td>\n<td>For selection questions, one entry per option: <code>question_option_id</code>, <code>is_select</code> (chosen by this customer), <code>statistic_percentage</code> (all customers), <code>is_answer</code> (same as <code>is_select</code>). <code>[]</code> for free text and information</td>\n</tr>\n<tr>\n<td>reward_status</td>\n<td><code>COMPLETED</code>, <code>SKIP_REWARD</code> or <code>INCOMPLETE</code> (also INCOMPLETE when unanswered)</td>\n</tr>\n</tbody>\n</table>\n</div><p>Entries are in question <code>position</code> order, the same order as Survey Detail.</p>\n<h3 id=\"errors\">Errors</h3>\n<ul>\n<li><strong>404</strong> <em>Resource Not Found</em>: unknown survey, or the survey was never approved.</li>\n<li><strong>400</strong> <em>Invalid parameter</em>: <code>campaign_id</code> is missing or not a number.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","name":"Mobile","type":"folder"}},"urlObject":{"path":["v1","surveys",":surveyId",":customerId"],"host":["https://gateway.youtap-test.net/survey/api"],"query":[{"description":{"content":"<p><strong>Required.</strong> promotion-service-api Survey campaign ID (coupon <code>campaignId</code>). Example: <code>5001</code></p>\n","type":"text/plain"},"key":"campaign_id","value":"5001"}],"variable":[{"id":"f8a82124-c547-430e-bef9-29844ea6139d","description":{"content":"<p><strong>UUID</strong>. The survey's ID. Example: <code>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</code></p>\n","type":"text/plain"},"type":"any","value":"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37","key":"surveyId"},{"id":"ab20b7c6-be53-4a66-ae4a-55560e8cedf4","description":{"content":"<p>Customer wallet ID / MSISDN. Example: <code>64211234567</code></p>\n","type":"text/plain"},"type":"any","value":"64211234567","key":"customerId"}]}},"response":[{"id":"16ba70aa-626a-433b-a71d-dcaceee267f4","name":"Partly completed survey","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/91b25424-a8cd-4be5-8779-2d2671ad5360/64211234569?campaign_id=5001","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","91b25424-a8cd-4be5-8779-2d2671ad5360","64211234569"],"query":[{"key":"campaign_id","value":"5001","type":"number","description":"**Required.** promotion-service-api Survey campaign ID (coupon `campaignId`). Example: `5001`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"497b19b1-0220-4152-afb5-bf34009a9574\",\n        \"customer_id\": \"64211234569\",\n        \"survey_id\": \"91b25424-a8cd-4be5-8779-2d2671ad5360\",\n        \"question_id\": \"55d691a2-3fe2-4a50-9204-b38c5b3fa918\",\n        \"answer_content\": \"\",\n        \"question_options\": [],\n        \"reward_status\": \"COMPLETED\",\n        \"is_answer\": true\n    },\n    {\n        \"id\": \"e12ce53c-f0e2-4326-8f4b-9a8b724263bb\",\n        \"customer_id\": \"64211234569\",\n        \"survey_id\": \"91b25424-a8cd-4be5-8779-2d2671ad5360\",\n        \"question_id\": \"914f9ed5-cc3d-40fc-ae1c-a5ffcdcd32ec\",\n        \"answer_content\": \"\",\n        \"question_options\": [\n            {\n                \"question_option_id\": \"6acb500a-afa3-480d-941d-a10f225f1e9b\",\n                \"statistic_percentage\": 100,\n                \"is_select\": true,\n                \"is_answer\": true\n            },\n            {\n                \"question_option_id\": \"0494dd0d-6334-4b27-942d-2d83eac794f5\",\n                \"statistic_percentage\": 0,\n                \"is_select\": false,\n                \"is_answer\": false\n            },\n            {\n                \"question_option_id\": \"6346c9bb-0e2c-48a4-8678-bd32c0933282\",\n                \"statistic_percentage\": 0,\n                \"is_select\": false,\n                \"is_answer\": false\n            }\n        ],\n        \"reward_status\": \"COMPLETED\",\n        \"is_answer\": true\n    },\n    {\n        \"id\": \"\",\n        \"customer_id\": \"64211234569\",\n        \"survey_id\": \"91b25424-a8cd-4be5-8779-2d2671ad5360\",\n        \"question_id\": \"f3a327ee-41ca-45f5-a86a-1e679ee33ca9\",\n        \"answer_content\": \"\",\n        \"question_options\": [\n            {\n                \"question_option_id\": \"df19c7ad-f9ed-4dc1-b384-231da180bcbf\",\n                \"statistic_percentage\": 0,\n                \"is_select\": false,\n                \"is_answer\": false\n            },\n            {\n                \"question_option_id\": \"6e517a95-0581-42fc-8da0-8dc055c0983b\",\n                \"statistic_percentage\": 0,\n                \"is_select\": false,\n                \"is_answer\": false\n            },\n            {\n                \"question_option_id\": \"cd96f1fd-6de2-4b26-bca3-52cb9ff737b3\",\n                \"statistic_percentage\": 0,\n                \"is_select\": false,\n                \"is_answer\": false\n            }\n        ],\n        \"reward_status\": \"INCOMPLETE\",\n        \"is_answer\": false\n    },\n    {\n        \"id\": \"\",\n        \"customer_id\": \"64211234569\",\n        \"survey_id\": \"91b25424-a8cd-4be5-8779-2d2671ad5360\",\n        \"question_id\": \"dfaedf2a-2c61-4856-97b1-e1b5ae7c397e\",\n        \"answer_content\": \"\",\n        \"question_options\": [],\n        \"reward_status\": \"INCOMPLETE\",\n        \"is_answer\": false\n    }\n]"}],"_postman_id":"18ac83c5-14ba-4308-bf0a-fc4702ec87d7"},{"name":"Answer Results","id":"23b9422b-15c6-4c40-8530-158d0ee02c31","protocolProfileBehavior":{"disableBodyPruning":true},"request":{"method":"GET","header":[],"url":"https://gateway.youtap-test.net/survey/api/v1/surveys/result/:customerId/:surveyId/:questionId?campaign_id=5001","description":"<p>Returns the result for <strong>one question</strong>: what the customer chose, plus how all customers answered. Use it for a per-question results or feedback screen.</p>\n<p><code>campaign_id</code> is <strong>required</strong>.</p>\n<h3 id=\"response-200-array\">Response: 200 (array)</h3>\n<p>The response has the same fields as <strong>Fill Answer</strong>:</p>\n<ul>\n<li><strong>Selection questions:</strong> one entry per option.<ul>\n<li><code>is_select</code> marks the options this customer chose.</li>\n<li><code>statistic_percentage</code> is the share of all customers' selections.</li>\n<li>For options this customer did not choose, <code>id</code>, <code>customer_id</code> and <code>reward_status</code> are <code>\"\"</code>.</li>\n</ul>\n</li>\n<li><strong>Free text and information questions:</strong> one entry with the customer's <code>answer_content</code>.<ul>\n<li>If the customer has not answered yet, every value is <code>\"\"</code>.</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"errors\">Errors</h3>\n<ul>\n<li><strong>404</strong> <em>Resource Not Found</em>: unknown question, or the survey was never approved.</li>\n<li><strong>400</strong> <em>Invalid parameter</em>: <code>campaign_id</code> is missing or not a number.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":true,"source":{"_postman_id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","name":"Mobile","type":"folder"}},"urlObject":{"path":["v1","surveys","result",":customerId",":surveyId",":questionId"],"host":["https://gateway.youtap-test.net/survey/api"],"query":[{"description":{"content":"<p><strong>Required.</strong> promotion-service-api Survey campaign ID (coupon <code>campaignId</code>). Example: <code>5001</code></p>\n","type":"text/plain"},"key":"campaign_id","value":"5001"}],"variable":[{"id":"c88e24c1-9aee-43c5-b176-93c0bd789f7c","description":{"content":"<p>Customer wallet ID / MSISDN. Example: <code>64211234567</code></p>\n","type":"text/plain"},"type":"any","value":"64211234567","key":"customerId"},{"id":"da5282db-3ae1-4c45-82c9-751eb1d374b8","description":{"content":"<p><strong>UUID</strong>. The survey's ID. Example: <code>7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37</code></p>\n","type":"text/plain"},"type":"any","value":"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37","key":"surveyId"},{"id":"4477ca65-2844-479d-8d60-89b0f1ba1cfa","description":{"content":"<p><strong>UUID</strong>. The question's ID, from Survey Detail <code>data.questions[].id</code>. Example: <code>3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90</code></p>\n","type":"text/plain"},"type":"any","value":"3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90","key":"questionId"}]}},"response":[{"id":"c1e81ef3-dc78-4ea2-8b05-b1d01e8fa2c6","name":"Selection question","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/result/64211234567/b9a0a649-0859-4602-9746-f6ac905c15d1/76079476-febe-46a1-abf9-2a4276582dfc?campaign_id=5001","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","result","64211234567","b9a0a649-0859-4602-9746-f6ac905c15d1","76079476-febe-46a1-abf9-2a4276582dfc"],"query":[{"key":"campaign_id","value":"5001","type":"number","description":"**Required.** promotion-service-api Survey campaign ID (coupon `campaignId`). Example: `5001`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"ae273c96-de10-4eb4-97ba-c9301882e0cc\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"b9a0a649-0859-4602-9746-f6ac905c15d1\",\n        \"question_id\": \"76079476-febe-46a1-abf9-2a4276582dfc\",\n        \"question_option_id\": \"a3139894-4149-400d-bb0d-3389ed2a8b9e\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 100,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": true\n    },\n    {\n        \"id\": \"\",\n        \"customer_id\": \"\",\n        \"survey_id\": \"b9a0a649-0859-4602-9746-f6ac905c15d1\",\n        \"question_id\": \"76079476-febe-46a1-abf9-2a4276582dfc\",\n        \"question_option_id\": \"7e3b6831-93b8-4e8d-935c-a0c8a2936940\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"\",\n        \"is_select\": false\n    },\n    {\n        \"id\": \"\",\n        \"customer_id\": \"\",\n        \"survey_id\": \"b9a0a649-0859-4602-9746-f6ac905c15d1\",\n        \"question_id\": \"76079476-febe-46a1-abf9-2a4276582dfc\",\n        \"question_option_id\": \"f9f0cf7f-b171-4f58-b4d9-119bd14f2868\",\n        \"answer_content\": \"\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"\",\n        \"is_select\": false\n    }\n]"},{"id":"9a693fca-9716-4686-86a6-31e164f605ef","name":"Free text question","originalRequest":{"method":"GET","header":[],"url":{"raw":"https://gateway.youtap-test.net/survey/api/v1/surveys/result/64211234567/b9a0a649-0859-4602-9746-f6ac905c15d1/b7aa037f-6e7f-4529-a16f-e4698def6756?campaign_id=5001","host":["https://gateway.youtap-test.net/survey/api"],"path":["v1","surveys","result","64211234567","b9a0a649-0859-4602-9746-f6ac905c15d1","b7aa037f-6e7f-4529-a16f-e4698def6756"],"query":[{"key":"campaign_id","value":"5001","type":"number","description":"**Required.** promotion-service-api Survey campaign ID (coupon `campaignId`). Example: `5001`"}]}},"status":"OK","code":200,"_postman_previewlanguage":"json","header":[{"key":"Content-Type","value":"application/json"}],"cookie":[],"responseTime":null,"body":"[\n    {\n        \"id\": \"e7c41d16-6537-4022-b121-bc8d9ce36bf3\",\n        \"customer_id\": \"64211234567\",\n        \"survey_id\": \"b9a0a649-0859-4602-9746-f6ac905c15d1\",\n        \"question_id\": \"b7aa037f-6e7f-4529-a16f-e4698def6756\",\n        \"question_option_id\": \"\",\n        \"answer_content\": \"Add a dark mode please!\",\n        \"statistic_percentage\": 0,\n        \"reward_status\": \"COMPLETED\",\n        \"is_select\": false\n    }\n]"}],"_postman_id":"23b9422b-15c6-4c40-8530-158d0ee02c31"}],"id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede","description":"<p>Endpoints the <strong>mobile app</strong> uses to run a survey for a customer.</p>\n<p>Together with promotion-service-api, these implement one <strong>Activity</strong>: a survey that earns a reward. Read <em>Survey coupons</em> in the collection description first.</p>\n<p>Requests in this folder send <code></code> as the bearer token. Get one with <strong>Authorization &gt; Get Customer Token</strong>, using the same customer as <code>customer_id</code> (see <em>Authentication</em> in the collection description).</p>\n<h2 id=\"where-the-ids-come-from\">Where the IDs come from</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Parameter</th>\n<th>Source</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>survey id (<code>:id</code>, <code>survey_id</code>)</td>\n<td>promotion-service-api coupon: <code>launchUrl</code> (or <code>couponOfferMessage[].surveyId</code>)</td>\n</tr>\n<tr>\n<td><code>campaign_id</code></td>\n<td>promotion-service-api coupon: <code>campaignId</code></td>\n</tr>\n<tr>\n<td><code>customer_id</code></td>\n<td>The logged-in customer's wallet ID / MSISDN (promotion-service-api <code>walletId</code>)</td>\n</tr>\n<tr>\n<td>question ids</td>\n<td>Survey Detail: <code>data.questions[].id</code></td>\n</tr>\n<tr>\n<td>option ids (<code>question_option_ids</code>)</td>\n<td>Survey Detail: <code>data.questions[].answers[].id</code></td>\n</tr>\n</tbody>\n</table>\n</div><p>Answers are stored per <strong>customer + survey + campaign</strong>, so the same survey used in two campaigns is tracked separately.</p>\n<h2 id=\"customer-flow\">Customer flow</h2>\n<ol>\n<li><strong>Survey Detail.</strong> Load the survey. This fails if the customer has no coupon in the campaign, or has already finished.</li>\n<li><strong>Survey Image.</strong> Load the images in <code>image_url</code> fields.</li>\n<li><strong>Fill Answer.</strong> Call it once per question, in <code>position</code> order, <strong>including INFORMATION questions</strong>. Every question must have a final answer (<code>COMPLETED</code> or <code>SKIP_REWARD</code>) before the reward is processed.</li>\n<li>When the last question is answered, Fill Answer calls promotion-service-api:<ul>\n<li>every answer <code>COMPLETED</code>: the coupon becomes <strong>ASSIGNED</strong> and the reward is credited;</li>\n<li>any answer <code>SKIP_REWARD</code>: the coupon becomes <strong>DELETED</strong>, with no reward, and the Activity disappears.</li>\n</ul>\n</li>\n<li><strong>Get Customer Answer List</strong> (optional) gives per-question progress, so the app can resume an unfinished survey.</li>\n<li><strong>Answer Results</strong> (optional) gives one question's result with percentages, for a results screen.</li>\n</ol>\n<h2 id=\"reward-status-reward_status\">Reward status (<code>reward_status</code>)</h2>\n<div class=\"click-to-expand-wrapper is-table-wrapper\"><table>\n<thead>\n<tr>\n<th>Value</th>\n<th>Meaning</th>\n<th>Effect</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>INCOMPLETE</td>\n<td>Draft or partial answer</td>\n<td>Saved, but the question still counts as unanswered. It can be overwritten later. No business event</td>\n</tr>\n<tr>\n<td>COMPLETED</td>\n<td>Final answer</td>\n<td>Locks the answer. When all questions are final and none are skipped, the coupon is <strong>ASSIGNED</strong></td>\n</tr>\n<tr>\n<td>SKIP_REWARD</td>\n<td>Final answer, but the customer forfeits the reward (e.g. declined a required question or consent)</td>\n<td>Locks the answer. When all questions are final, the coupon is <strong>DELETED</strong>. Survey Detail is refused from then on</td>\n</tr>\n</tbody>\n</table>\n</div><p>Once a question has a COMPLETED or SKIP_REWARD answer, it cannot be answered again (400 <em>Customer already fill the answer.</em>).</p>\n<h2 id=\"statistics\">Statistics</h2>\n<p><code>statistic_percentage</code> is the share (0-100, rounded) of <strong>all customers'</strong> selections for a question that chose this option. The app can use it to show \"62% of people chose Coffee\".</p>\n<ul>\n<li>It only counts final answers (COMPLETED or SKIP_REWARD) with <code>is_select: true</code>. INCOMPLETE drafts are not counted.</li>\n<li>It is always 0 for free text and information questions.</li>\n</ul>\n","auth":{"type":"bearer","bearer":{"basicConfig":[{"key":"token","value":""}]},"isInherited":false},"_postman_id":"42a0aec1-7d89-454c-8a6f-a5dc66b37ede"}],"variable":[{"key":"base_url","value":"https://gateway.youtap-test.net/survey/api","description":"Base URL for the Mobile endpoints: the gateway's /survey/api route. Currently set to the test environment gateway. To point at another environment (e.g. local dev - http://localhost:19422, matching server.port in application-dev.yml - or production), either edit this collection variable's current value, or define base_url in a Postman Environment and select that environment - an active Environment variable takes precedence over this collection variable."},{"key":"dashboard_base_url","value":"https://gateway.test.youtap.systems/survey/sso","description":"Base URL for the Dashboard endpoints: the gateway's /survey/sso route, which takes Azure AD tokens (the same route the Campaign Manager portal uses). Override it the same way as base_url; for local dev use http://localhost:19422."},{"key":"question_id","value":"3f2c9a7e-8b1d-4c55-9e0a-6d4b2f1a7c90","description":"**UUID**. The ID of a question. Set automatically when Question Bank > Create succeeds."},{"key":"survey_id","value":"7a1e5c2d-4f3b-4e8a-9c6d-2b0f8e4a1d37","description":"**UUID**. The ID of a survey. Set automatically when Survey > Create succeeds."},{"key":"customer_id","value":"64211234567","description":"Customer wallet ID (MSISDN), the same value promotion-service-api uses as walletId."},{"key":"campaign_id","value":"5001","description":"promotion-service-api Survey campaign ID whose url/externalUrl is the survey ID."},{"key":"customer_password","value":"","description":"The code the customer logs in with. Used by Authorization > Get Customer Token. Keep it as a current value or in an Environment so it isn't shared."},{"key":"customer_token","value":"","description":"Bearer token for the Mobile requests. Set automatically by Authorization > Get Customer Token."},{"key":"dashboard_token","value":"","description":"Bearer token for the Dashboard requests: an Azure AD access token copied from the Campaign Manager portal (see Authentication in the collection description)."},{"key":"auth_url","value":"https://auth.youtap-test.net","description":"Youtap auth server used by Authorization > Get Customer Token."},{"key":"consumer_client_id","value":"","description":"Consumer app OAuth client ID, sent as HTTP Basic by Get Customer Token. Ask the platform team."},{"key":"consumer_client_secret","value":"","description":"Consumer app OAuth client secret, sent as HTTP Basic by Get Customer Token. Ask the platform team, and keep it as a current value or in an Environment so it isn't shared."}]}