{"openapi":"3.1.0","info":{"title":"PickFu API","version":"1.0.0","description":"The PickFu API enables programmatic access to create surveys, retrieve results, and integrate PickFu into your workflows.\n\n## Overview\n\nPickFu helps you get instant consumer feedback through surveys. With the API, you can:\n\n- Create surveys programmatically\n- Retrieve survey results and respondent data\n- Target specific audiences with demographic traits\n- Integrate PickFu into your product development workflow\n\n## Rate Limits\n\nSelected endpoints (currently the CSV export endpoints) enforce per-caller rate limits and return `429 Too Many Requests` when exceeded. See each endpoint description for its specific budget.\n\n## Authentication\n\nAll API requests require a Bearer token — either an API key or an OAuth 2.0 access token. See the [Authentication guide](https://www.pickfu.com/docs/developers/authentication) for details.","contact":{"name":"PickFu Support","email":"support@pickfu.com","url":"https://www.pickfu.com"}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"OAuth2 access token obtained via the authorization flow. Include in the Authorization header as: `Bearer {access_token}`"}},"schemas":{}},"paths":{"/users/me":{"get":{"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/traits/targeting":{"get":{"operationId":"getTargetingTraits","summary":"Get targeting traits","tags":["Traits"],"description":"Returns all available audience targeting traits that can be used when creating or updating surveys. Traits allow you to reach specific demographics such as age groups, gender, income levels, shopping habits, and more.\n\nOptionally filter by country code to see traits available in a specific market.","parameters":[{"schema":{"type":"string"},"in":"query","name":"country","required":false,"description":"Two-letter country code to filter available traits (e.g. US, GB). Defaults to US traits when omitted."}],"responses":{"200":{"description":"List of available targeting traits","content":{"application/json":{"schema":{"type":"array","description":"List of available targeting traits","items":{"type":"object","required":["trait_name","permalink"],"properties":{"trait_name":{"type":"string","description":"Human-readable trait name with category prefix (e.g. \"Age: 25-34\")"},"permalink":{"type":"string","description":"Trait permalink to use in the targeting array when creating or updating surveys"}}}}}}}}}},"/traits/reporting":{"get":{"operationId":"getReportingTraits","summary":"Get reporting traits","tags":["Traits"],"description":"Returns all available reporting/demographic breakdown traits that can be applied to surveys. These traits allow you to segment survey results by demographics such as age, gender, income, and more.\n\nOptionally filter by country code to see traits available in a specific market.","parameters":[{"schema":{"type":"string"},"in":"query","name":"country","required":false,"description":"Two-letter country code to filter available traits (e.g. US, GB). Defaults to US traits when omitted."}],"responses":{"200":{"description":"List of available reporting traits","content":{"application/json":{"schema":{"type":"array","description":"List of available reporting traits","items":{"type":"object","required":["trait_name","permalink"],"properties":{"trait_name":{"type":"string","description":"Human-readable trait name (e.g. \"Age: 25-34\")"},"permalink":{"type":"string","description":"Trait permalink to use in the reporting array when creating or updating surveys"}}}}}}}}}},"/help/search":{"get":{"operationId":"searchHelpArticles","summary":"Search help articles and PickFu examples","tags":["Help"],"description":"Searches PickFu content matching the query. Use the `types` parameter to select help, example, case_study, and solution results. Results include titles, descriptions, body text, URLs, and response metadata.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":500},"in":"query","name":"query","required":true,"description":"Search query for help articles (maximum 500 characters)"},{"schema":{"type":"integer","minimum":1},"in":"query","name":"page","required":false,"description":"Page number for pagination (positive integer, default: 1)"},{"schema":{"type":"integer","minimum":1,"maximum":100},"in":"query","name":"per_page","required":false,"description":"Number of results per page (1-100, default: 20)"},{"schema":{"type":"string","enum":["en","es","ru","zh","ja"],"default":"en"},"in":"query","name":"locale","required":false,"description":"Requested article locale"},{"schema":{"type":"string","pattern":"^(help|example|case_study|solution)(,(help|example|case_study|solution))*$"},"in":"query","name":"types","required":false,"description":"Comma-separated result types: help, example, case_study, solution"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"totalCount":{"type":"number"},"pages":{"type":"object","additionalProperties":true,"properties":{"page":{"type":"number"},"perPage":{"type":"number"},"totalPages":{"type":"number"}}},"data":{"type":"object","additionalProperties":true,"properties":{"articles":{"type":"array","items":{"type":"object","additionalProperties":true,"required":["id","type"],"properties":{"id":{"type":"string"},"type":{"type":"string","enum":["help","example","case_study","solution"]},"title":{"type":"string"},"description":{"type":"string"},"body":{"type":"string","description":"Result content. Help articles up to 8,000 characters return in full. Longer help articles return only the sections that best match the query, in article order, prefixed with a line starting \"Excerpt:\" that gives the full article URL; \"…\" marks skipped sections. Example, case study and solution results return their best-matching section."},"snippet":{"type":"string"},"url":{"type":"string"},"industries":{"type":"array","items":{"type":"string"}},"useCases":{"type":"array","items":{"type":"string"}},"pollType":{"type":["null","string"]},"pollUrl":{"type":["null","string"]},"company":{"type":["null","string"]}}}}}},"meta":{"type":"object","required":["backend","locale","generationSha"],"properties":{"backend":{"type":"string","enum":["intercom","turbopuffer","none"]},"locale":{"type":"string","enum":["en","es","ru","zh","ja"]},"generationSha":{"type":["null","string"]},"degraded":{"type":"boolean","enum":[true]}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys":{"get":{"operationId":"listSurveys","summary":"List surveys","tags":["Surveys"],"description":"Returns a paginated list of surveys with filtering and sorting options. Use query parameters to filter by status, type, country, tags, projects, and more.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":20},"in":"query","name":"limit","required":false,"description":"Results per page (1-100)"},{"schema":{"type":"string"},"in":"query","name":"status","required":false,"description":"Filter by survey status. Comma-separated values: completed, in-progress, unpublished, archived"},{"schema":{"type":"string"},"in":"query","name":"type","required":false,"description":"Filter by question type. Comma-separated values: head_to_head, ranked, open_ended, click_test, etc."},{"schema":{"type":"string"},"in":"query","name":"option_type","required":false,"description":"Filter by option type (e.g. text, image). Comma-separated."},{"schema":{"type":"string"},"in":"query","name":"countries","required":false,"description":"Filter by country codes. Comma-separated (e.g. US,GB,CA)."},{"schema":{"type":"string"},"in":"query","name":"tags","required":false,"description":"Filter by tag IDs — opaque identifiers (tag_<32-hex>) and/or legacy integers, mixed freely. Comma-separated."},{"schema":{"type":"string"},"in":"query","name":"audiences","required":false,"description":"Filter by audience IDs. Comma-separated."},{"schema":{"type":"string","maxLength":255},"in":"query","name":"text","required":false,"description":"Full-text search across survey names and questions"},{"schema":{"type":"string","minLength":1,"maxLength":255},"in":"query","name":"externalId","required":false,"description":"Exact match on the optional opaque correlation key. Account-scoped. Not a text search."},{"schema":{"type":"string"},"in":"query","name":"member_id","required":false,"description":"Filter by team member ID(s) — opaque identifiers (usr_<32-hex>, as returned by GET /users) and/or legacy integers, mixed freely. Comma-separated."},{"schema":{"type":"string"},"in":"query","name":"project_ids","required":false,"description":"Filter by project GUIDs or numeric IDs. Comma-separated."},{"schema":{"type":"string","format":"date-time"},"in":"query","name":"published_after","required":false,"description":"Only include surveys published after this ISO 8601 datetime"},{"schema":{"type":"string","enum":["createdAt","name","creator","status"],"default":"createdAt"},"in":"query","name":"sort_by","required":false,"description":"Field to sort by"},{"schema":{"type":"string","enum":["asc","desc"],"default":"desc"},"in":"query","name":"dir","required":false,"description":"Sort direction"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","description":"List of surveys","items":{"type":"object","properties":{"id":{"type":"string","description":"Survey GUID"},"name":{"type":"string","description":"Survey name"},"url":{"type":"string","description":"URL to view survey results"},"status":{"type":"string","description":"Survey status: completed, in-progress, unpublished, or archived"},"type":{"type":"string","description":"Primary question type"},"countryCode":{"type":["string","null"],"description":"Two-letter country code"},"sampleSize":{"type":["number","null"],"description":"Number of respondents requested"},"numResponses":{"type":"number","description":"Number of responses collected"},"createdAt":{"type":["string","null"],"description":"Creation timestamp (ISO 8601)"},"publishedAt":{"type":["string","null"],"description":"Publication timestamp (ISO 8601)"},"completedAt":{"type":["string","null"],"description":"Completion timestamp (ISO 8601)"},"creatorName":{"type":["string","null"],"description":"Name of the team member who created the survey"},"targeting":{"type":"array","items":{"type":"string"},"description":"Targeting trait permalinks"},"tags":{"type":"array","description":"Tags associated with the survey","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string","description":"Tag name"}}}},"projects":{"type":"array","description":"Projects the survey belongs to","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":"string","description":"Project name"}}}},"externalId":{"type":"string","description":"Optional opaque correlation key. Omitted when unset. Case-sensitive and byte-exact."},"template":{"type":["object","null"],"description":"The template the survey was made from, or null. GET the survey for its constraints.","properties":{"id":{"type":["string","null"],"description":"Template id (cmb_...), or null when the template can no longer be addressed"},"name":{"type":"string"}}},"elements":{"type":"array","description":"Questions in this survey (summary view)","items":{"type":"object","properties":{"id":{"type":"string","description":"Question GUID"},"question":{"type":["string","null"],"description":"Question text"},"subtype":{"type":"string","description":"Question subtype"},"variant":{"type":["string","null"],"description":"Question variant"},"position":{"type":"number","description":"Display position"}}}}}}},"pagination":{"type":"object","description":"Pagination metadata","properties":{"page":{"type":"number","description":"Current page number"},"limit":{"type":"number","description":"Results per page"},"total":{"type":"number","description":"Total number of results"},"totalPages":{"type":"number","description":"Total number of pages"}}}}}}}}}},"post":{"operationId":"createSurvey","summary":"Create survey","tags":["Surveys"],"description":"Creates a new survey in draft status. The survey must be published separately using the publish endpoint.\n\nEach survey contains one or more questions, each with a type (head_to_head, ranked, open_ended, etc.) and optional answer options. You can also specify targeting traits, reporting breakdowns, country, and sample size.\n\nTo start from a template instead, send `template` (an id from GET /v1/templates, plus any blanks and options) in place of `questions`. The draft is checked against the template limits before anything is written; a request outside them is a 422 listing every violation with its allowed values.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Send exactly one of `questions` (write your own poll) or `template` (build it from a template id returned by GET /v1/templates).","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Survey name (1-255 characters, trimmed)"},"projectId":{"type":["string","number","null"],"description":"Project GUID (string) or numeric ID to associate with the survey, or null to leave unassigned. Mutually exclusive with `projects`."},"projects":{"type":"array","maxItems":50,"description":"Project GUIDs (or numeric IDs) to associate the survey with. Mutually exclusive with `projectId`.","items":{"type":["string","number"]}},"tags":{"type":"array","maxItems":10,"description":"Tags to attach. Each item has either id (existing tag) or name (find-or-create).","items":{"type":"object","oneOf":[{"required":["id"],"properties":{"id":{"type":"number","description":"Existing tag ID"}},"additionalProperties":false},{"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Tag name (will find or create)"}},"additionalProperties":false}]}},"targeting":{"type":"array","items":{"type":"string"},"description":"Demographic targeting traits"},"reporting":{"type":"array","items":{"type":"string"},"description":"Reporting breakdown traits"},"country":{"type":"string","description":"Two-letter country code (e.g. US)"},"sampleSize":{"type":"string","description":"Number of respondents. Standard surveys: \"15\", \"30\", \"50\", \"75\", \"100\", \"200\", \"300\", \"500\". Screen recording surveys: \"5\", \"10\", \"15\", \"20\", \"25\", \"30\", \"50\", \"75\" (max 75)."},"surveyIntent":{"type":"string","description":"Original intent of the survey as interpreted by AI (max 255 characters)","maxLength":255},"isMiniPoll":{"type":"boolean","description":"Whether to create this survey as a daily mini-poll"},"externalId":{"type":"string","minLength":1,"maxLength":255,"description":"Optional opaque correlation key for your own records. Omit when unset. Case-sensitive and byte-exact — send the identical string every time. Many surveys may share the same id. We do not interpret this value."},"template":{"type":"object","required":["id"],"additionalProperties":false,"description":"Create the survey from a template instead of writing `questions`. A template is one ready-made question with a fixed price per response and fixed limits (question type, option count and kinds, sample sizes, countries, audience). Call GET /v1/templates/{id} first to read its question, blanks, option slots and constraints. The server picks the question type from the template (head_to_head for 2 options or fewer and ranked for 3 or more, where a template offers both). Omitted survey fields come from the template: `sampleSize` its default size, `country` its default country, `name` its title, and `targeting` its preset audience (send the full list to change it, keeping the preset). Its reporting traits always apply, so `reporting` cannot be sent. A request outside the limits is rejected with a 422 listing every violation; nothing is written. Create only: edit the draft afterwards with `questions`.","properties":{"id":{"type":"string","minLength":1,"description":"Template id (cmb_...) from GET /v1/templates."},"prompt":{"type":"string","maxLength":255,"description":"Replaces the question of a template without blanks, and is required when the template has no question. A template whose question has {{name}} blanks takes `blanks` instead; `prompt` is rejected there."},"blanks":{"type":"object","additionalProperties":{"type":"string"},"description":"One value per {{name}} blank in the template's question, keyed by the blank's name. Every blank must be filled."},"context":{"type":"object","additionalProperties":false,"description":"Context shown with the question, as text or as a media URL (one, not both). Only for templates that take context.","properties":{"text":{"type":"string"},"mediaUrl":{"type":"string"}}},"options":{"type":"array","description":"The question's options, in the same shape as a question's options. Omit to use the template's preset option values when it has one for every slot.","maxItems":8,"items":{"type":"object","additionalProperties":false,"properties":{"value":{"type":"string","maxLength":5000},"mediaUrl":{"type":"string"},"asin":{"type":"string","pattern":"^[A-Z0-9]{10}$","maxLength":10},"imageSet":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","required":["source","id"],"additionalProperties":false,"properties":{"source":{"type":"string","enum":["amazon","walmart","google_play","apple"]},"id":{"type":"string","minLength":1}}}]},"minItems":1},"imageSetDirection":{"type":"string","enum":["vertical","horizontal","a-plus"]},"mockup":{"type":"object","description":"Either an Amazon product mockup (`type`, `image`, `title`, `price`, …) or a first-party mockup template (`template` with `values`, `import` or both), never both. A template keeps the option a text option: send `value` as well, which is the option's text and fills the template's display field. Every option of a question names the same template, or none does. List the templates and the values each takes with GET /v1/mockup-templates.","properties":{"type":{"type":"string","enum":["serp","listing"]},"image":{"type":"string"},"title":{"type":"string"},"numRatings":{"type":"number"},"reviewScore":{"type":"number"},"rating":{"type":"number"},"reviews":{"type":"number"},"price":{"type":"number"},"currency":{"type":"string"},"template":{"type":"string","minLength":1,"description":"Lookup key of a mockup template from GET /v1/mockup-templates, such as `app-store-page`."},"values":{"type":"object","description":"The template's field values, keyed by field name, as its `valuesSchema` describes. Leave out the display field: it is the option's `value`."},"import":{"type":"object","description":"A store listing that fills the template's values before the survey is saved, for templates whose `importSources` list the store. `values` sent beside it win, so send the fields a store does not provide, such as an App Store subtitle, there. The option's `value` stays its text. Images are copied to PickFu's media CDN as when sent in `values`.","required":["source","id"],"additionalProperties":false,"properties":{"source":{"type":"string","enum":["apple"]},"id":{"type":"string","minLength":1,"maxLength":500,"description":"The app: an App Store link such as https://apps.apple.com/us/app/name/id123456789, or the number after \"id\"."},"country":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"Two-letter storefront to read the listing from when the link names none. Defaults to the survey's country."}}}}}}}}}},"questions":{"type":"array","minItems":1,"description":"List of questions for the survey. Required unless `template` is sent.","items":{"type":"object","required":["type","prompt"],"properties":{"type":{"type":"string","enum":["head_to_head","ranked","open_ended","click_test","emoji_rating","star_rating","five_second_test","screen_recording","single_select","multi_select","likert","van_westendorp"],"description":"Question type. Every type except screen_recording automatically collects a required written explanation from each respondent, returned as the response's `explanation` field. Do NOT add a separate open_ended question to capture 'why' — it duplicates the built-in explanation and wastes a question slot (multi-question surveys are priced per question)."},"prompt":{"type":"string","description":"Question text prompt (max 255 chars). Every response automatically includes a required written explanation from the respondent for all types except screen_recording — phrase the real question here and PickFu collects the 'why' automatically.","maxLength":255},"variant":{"type":["string","null"],"description":"Persisted question variant. For likert questions, accepts canonical variant slugs returned by GET."},"context":{"type":"object","description":"Context provided with the question: text, a mediaUrl, or both. With both, text is the caption shown with the image and mediaUrl must be an image URL.","properties":{"text":{"type":"string"},"mediaUrl":{"type":"string"}}},"likertScale":{"type":"string","enum":["agreement5","agreement7","frequency","satisfaction"],"description":"Likert scale preset. Only honored when type=likert. Defaults to agreement5 (5-point Agreement) if omitted. DEV-3128."},"options":{"type":"array","description":"Options for the question","items":{"type":"object","additionalProperties":false,"properties":{"value":{"type":"string","maxLength":5000},"mediaUrl":{"type":"string"},"asin":{"type":"string","pattern":"^[A-Z0-9]{10}$","maxLength":10},"imageSet":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","required":["source","id"],"additionalProperties":false,"properties":{"source":{"type":"string","enum":["amazon","walmart","google_play","apple"]},"id":{"type":"string","minLength":1}}}]},"minItems":1},"imageSetDirection":{"type":"string","enum":["vertical","horizontal","a-plus"]},"mockup":{"type":"object","description":"Either an Amazon product mockup (`type`, `image`, `title`, `price`, …) or a first-party mockup template (`template` with `values`, `import` or both), never both. A template keeps the option a text option: send `value` as well, which is the option's text and fills the template's display field. Every option of a question names the same template, or none does. List the templates and the values each takes with GET /v1/mockup-templates.","properties":{"type":{"type":"string","enum":["serp","listing"]},"image":{"type":"string"},"title":{"type":"string"},"numRatings":{"type":"number"},"reviewScore":{"type":"number"},"rating":{"type":"number"},"reviews":{"type":"number"},"price":{"type":"number"},"currency":{"type":"string"},"template":{"type":"string","minLength":1,"description":"Lookup key of a mockup template from GET /v1/mockup-templates, such as `app-store-page`."},"values":{"type":"object","description":"The template's field values, keyed by field name, as its `valuesSchema` describes. Leave out the display field: it is the option's `value`."},"import":{"type":"object","description":"A store listing that fills the template's values before the survey is saved, for templates whose `importSources` list the store. `values` sent beside it win, so send the fields a store does not provide, such as an App Store subtitle, there. The option's `value` stays its text. Images are copied to PickFu's media CDN as when sent in `values`.","required":["source","id"],"additionalProperties":false,"properties":{"source":{"type":"string","enum":["apple"]},"id":{"type":"string","minLength":1,"maxLength":500,"description":"The app: an App Store link such as https://apps.apple.com/us/app/name/id123456789, or the number after \"id\"."},"country":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"Two-letter storefront to read the listing from when the link names none. Defaults to the survey's country."}}}}}}}}}}}},"additionalProperties":false}}},"description":"Send exactly one of `questions` (write your own poll) or `template` (build it from a template id returned by GET /v1/templates)."},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","description":"Full survey data including questions, options, and metadata","properties":{"id":{"type":"string","description":"Unique survey GUID"},"name":{"type":["string","null"],"description":"Survey name/title"},"country":{"type":"string","description":"Two-letter country code (e.g. US, GB)"},"currency":{"type":"string","description":"ISO 4217 currency derived from the survey target country"},"sampleSize":{"type":"number","description":"Number of respondents requested"},"numResponses":{"type":["number","null"],"description":"Number of responses collected so far"},"status":{"type":"string","description":"Survey status: unpublished, in-progress, completed, or archived (deleted is also possible here for soft-deleted surveys, which the list endpoint excludes). Same vocabulary as the list endpoint — a survey always has the identical status string on both."},"targeting":{"type":"array","items":{"type":"string"},"description":"Array of targeting trait permalinks applied to this survey"},"reporting":{"type":"array","items":{"type":"string"},"description":"Array of reporting trait permalinks for demographic breakdowns"},"reportingDefaultsApplied":{"type":"array","items":{"type":"string"},"description":"Reporting trait permalinks that were auto-injected as free defaults (based on plan level and country), not explicitly requested by the caller"},"tags":{"type":"array","description":"Tags associated with the survey","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string","description":"Tag name"}}}},"projects":{"type":"array","description":"Projects the survey belongs to","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":"string","description":"Project name"}}}},"surveyUrl":{"type":"string","description":"Public URL to view the survey results"},"surveyIntent":{"type":"string","description":"AI-interpreted intent of the survey"},"externalId":{"type":"string","description":"Optional opaque correlation key for your own records. Omitted when unset. Case-sensitive and byte-exact. Many surveys may share the same id. We do not interpret this value."},"template":{"type":["object","null"],"description":"The template the survey was made from and the limits it must meet to publish, or null. Edits that break a limit are rejected.","properties":{"id":{"type":["string","null"],"description":"Template id (cmb_...), or null when the template can no longer be addressed"},"name":{"type":"string"},"constraints":{"type":"object","additionalProperties":false,"required":["questionTypes","optionTypes","optionCount","sampleSizes","defaultSampleSize","countries","defaultCountry"],"properties":{"questionTypes":{"type":"array","items":{"type":"string","enum":["head_to_head","ranked","open_ended","star_rating","click_test"]}},"optionTypes":{"type":"array","items":{"type":"string","enum":["text","image","video","url","product","image-set","audio"]}},"optionCount":{"type":"object","additionalProperties":false,"required":["min","max"],"properties":{"min":{"type":"integer"},"max":{"type":"integer"}}},"sampleSizes":{"type":"array","items":{"type":"string"}},"defaultSampleSize":{"type":"string"},"countries":{"type":"array","items":{"type":"string"}},"defaultCountry":{"type":"string"}}}}},"questions":{"type":"array","description":"Questions in the survey with options, responses, and AI metadata","items":{"type":"object","properties":{"id":{"type":"string","description":"Question ID (GUID)"},"type":{"type":"string","description":"Question type (head_to_head, ranked, open_ended, click_test, emoji_rating, star_rating, five_second_test, screen_recording, single_select, multi_select, likert, van_westendorp)"},"variant":{"type":["string","null"],"description":"Question variant for specialized display modes"},"value":{"type":"string","description":"Question text"},"translation":{"type":["string","null"],"description":"Translated question text"},"likertScale":{"type":["string","null"],"enum":["agreement5","agreement7","frequency","satisfaction",null],"description":"Likert scale preset, returned for likert questions whose variant matches one of the canonical presets. Null for non-likert questions or legacy likert questions with no recognized variant."},"options":{"type":["array","null"],"items":{"type":"object","properties":{"id":{"type":"string","description":"Option GUID for round-trip updates"},"label":{"type":"string","description":"Option identifier label (e.g. \"Option A\")"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Option content: text string, Cloudinary URL, or array of URLs (image-set)"},"type":{"type":"string","description":"Option data type: text, image, video, product, or image-set"},"translation":{"type":["string","null"],"description":"Translated option text"},"product":{"type":["object","null"],"description":"Product data for product-type options (ASIN or custom mockups)","properties":{"asin":{"type":["string","null"],"description":"Amazon ASIN (null for custom mockups)"},"title":{"type":"string","description":"Product title"},"price":{"type":"number","description":"Product price"},"salePrice":{"type":["number","null"],"description":"Discounted/sale price. null when the product is not on sale."},"currency":{"type":["string","null"],"description":"Currency code for the price"},"rating":{"type":"number","description":"Star rating (0-5)"},"reviews":{"type":"number","description":"Number of reviews"},"reviewScore":{"type":["number","null"],"description":"Alias of rating for public API round-trip"},"numRatings":{"type":["number","null"],"description":"Alias of reviews for public API round-trip"},"image":{"type":"string","description":"Product image URL"}}},"imageSetDirection":{"type":"string","description":"Image stack layout direction: horizontal or vertical (image-set options only)"},"mockupType":{"type":"string","description":"Product mockup rendering style: serp or listing (product options only)"},"mockup":{"type":"object","description":"The mockup template a text option shows: `template` is its lookup key and `values` its stored field values, images at their PickFu media CDN copies. `values` leaves out the display field, which is the option's `value`. On update, leaving `mockup` out or sending it back unchanged keeps the page, and `mockup: null` removes the question's template.","properties":{"template":{"type":"string"},"values":{"type":"object","additionalProperties":true}}}}},"description":"Answer options for this question"},"context":{"type":["object","null"],"description":"Additional context provided with the question (e.g. a product description or image)","properties":{"type":{"type":"string","description":"Context type (text or media)"},"value":{"type":"string","description":"Context content: the text, or for media the hosted media URL"},"text":{"type":"string","description":"Caption shown with the image. Present only on a media context that has one; send it back with the media URL to keep both."},"translation":{"type":["string","null"],"description":"Translated context text"}}},"results":{"type":["object","null"],"description":"Aggregated, page-faithful summary of the outcome for this question — the same percentages and ranking shown on the results page. Null for question types without a simple per-option aggregate (open_ended, click_test, likert, five_second_test, screen_recording, round_robin) or before any responses arrive. For ranked questions, `votes` is the final instant-runoff tally the percentage is computed from, and differs from the first-choice count shown beside each option on the page; the winner exceeds 50%.","properties":{"totalResponses":{"type":"number","description":"Number of valid responses the percentages are computed against"},"winningOptionId":{"type":["string","null"],"description":"GUID of the winning option, or null on a tie / before a winner is decided"},"averageScore":{"type":"number","description":"Average rating, returned for rating questions only (emoji_rating, star_rating)"},"options":{"type":"array","description":"Per-option results, ordered by rank (winner first)","items":{"type":"object","properties":{"id":{"type":"string","description":"Option GUID"},"label":{"type":["string","null"],"description":"Option label (e.g. \"A\")"},"votes":{"type":"number","description":"Vote count; the final instant-runoff tally for ranked questions"},"percentage":{"type":"number","description":"round(votes / totalResponses * 100), matching the results page"},"rank":{"type":["number","null"],"description":"Final placement (1 = winner)"},"isWinner":{"type":"boolean","description":"Whether this option is the winner"}}}}}},"responses":{"type":"array","description":"Respondent answers for this question","items":{"type":"object","properties":{"id":{"type":"string","description":"Response ID"},"pinned":{"type":"boolean","description":"Whether the response is pinned"},"explanation":{"type":["string","null"],"description":"Written explanation from the respondent"},"translation":{"type":["string","null"],"description":"Translated explanation text"},"chosenOption":{"type":["string","null"],"description":"Label of the option chosen by the respondent"},"selectedOptions":{"type":["array","null"],"description":"Labels of options selected by the respondent for multi-select questions","items":{"type":"string"}},"score":{"type":["number","null"],"description":"Rating score (for emoji_rating, star_rating question types)"},"clicks":{"type":["array","null"],"description":"Click coordinates for click_test questions","items":{"type":"object","properties":{"number":{"type":"number","description":"Click sequence number"},"xCoord":{"type":"number","description":"X coordinate of the click"},"yCoord":{"type":"number","description":"Y coordinate of the click"}}}},"ranking":{"type":["array","null"],"description":"Respondent's ranking of options for ranked question types. Each entry pairs a rank (1 = top pick) with the option label.","items":{"type":"object","properties":{"rank":{"type":"number","description":"Rank position (1 = respondent's top pick)"},"option":{"type":["string","null"],"description":"Option label at this rank"}}}},"media":{"type":["string","null"],"description":"Media URL (for screen_recording question types)"},"mediaTranscription":{"type":["string","null"],"description":"Transcription of the recorded media"},"matchup":{"type":["object","null"],"description":"Head-to-head matchup pairing shown to the respondent","properties":{"option1":{"type":"string","description":"First option in the matchup"},"option2":{"type":"string","description":"Second option in the matchup"}}},"statements":{"type":["array","null"],"description":"Per-statement responses for likert question types. Each entry pairs a statement with the numeric value the respondent picked on the configured scale. DEV-3149.","items":{"type":"object","properties":{"id":{"type":"string","description":"GUID of the statement (the question option)"},"statement":{"type":["string","null"],"description":"Statement text"},"value":{"type":"number","description":"Numeric value the respondent picked on the Likert scale (1..N for the configured scale)"}}}},"prices":{"type":["object","null"],"description":"Van Westendorp price-sensitivity responses. Four numeric prices the respondent provided for the four standardized PSM questions.","properties":{"tooCheap":{"type":"number","description":"Price at which the product would be so cheap that quality is questionable"},"bargain":{"type":"number","description":"Price at which the product would be a bargain"},"expensive":{"type":"number","description":"Price at which the product starts to feel expensive but is still worth considering"},"tooExpensive":{"type":"number","description":"Price at which the product would be too expensive to consider"}}},"respondent":{"type":"array","description":"Demographic traits of the respondent","items":{"type":"object","properties":{"trait":{"type":"string","description":"Trait category name"},"value":{"type":"string","description":"Trait value"}}}}}}},"ai":{"type":"object","description":"AI-generated metadata such as summaries and key themes for this question","additionalProperties":{"type":"string"}}}}}}},"cost":{"type":"object","description":"Cost information for the survey","properties":{"amount":{"type":"number","description":"Survey cost in dollars"},"balance":{"type":"number","description":"Credit balance in dollars"},"currency":{"type":"string","description":"Currency code (USD)"},"canPayWithBalance":{"type":"boolean","description":"Whether balance covers the cost"},"quotedCreditsCost":{"type":"number","description":"Post-discount cost in credits, after free credits applied (1 credit = $2 USD)"},"creditsCostSubtotal":{"type":"number","description":"Pre-discount cost in credits (1 credit = $2 USD)"},"discounts":{"type":"array","description":"Credit-side discount line items, each entry is [label, amountInCredits]. Amounts are denominated in credits so they subtract directly from creditsCostSubtotal","items":{"type":"array","items":{"type":"string"}}},"discountsMoney":{"type":"array","description":"Dollar-side discount line items, each entry is [label, formattedDollarAmount] (e.g. \"$20.08\")","items":{"type":"array","items":{"type":"string"}}},"planRequired":{"type":["null","string"],"description":"Plan tier required for current survey configuration, or null if the current plan is sufficient"},"priceLines":{"type":"array","description":"The survey builder's price summary, each entry is [label, formattedDollarAmount] (e.g. [\"Head-to-Head: Text Length (+1.2x)\", \"$10.00\"]). Each amount is that line's cost for the whole sample: base price, extra options, text or video length, targeting and reporting. A $0.00 line is included free. The lines come before discounts: they add up to `creditsCostSubtotal` in dollars, and `discountsMoney` takes that down to `amount`","items":{"type":"array","items":{"type":"string"}}}}},"completionEstimate":{"type":"object","description":"Estimated completion-time bucket for the current audience","properties":{"bucket":{"type":"string","description":"Completion-time bucket: SUPER_EASY (<2h), EASY (1-2 days), MEDIUM (up to 2 weeks), HARD (may take longer), MAY_NOT_COMPLETE"},"estimatedMinutes":{"type":["null","number"],"description":"Estimated completion time in minutes, or null when unavailable"},"status":{"type":"string","description":"ready when an estimate exists, pending while computing"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"code":{"type":"string"},"param":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string"}}}}}},"422":{"description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","content":{"application/json":{"schema":{"type":"object","description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"code":{"type":"string"},"param":{"type":"string","description":"The request field to change."},"message":{"type":"string"},"violations":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"param":{"type":"string"},"message":{"type":"string"},"allowed":{},"received":{}}}},"blanks":{"type":"array","description":"Blanks still to fill, for TEMPLATE_BLANKS_UNFILLED.","items":{"type":"object","properties":{"name":{"type":"string"},"placeholder":{"type":["null","string"]}}}}}}}}},"429":{"description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","content":{"application/json":{"schema":{"type":"object","description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"code":{"type":"string"},"param":{"type":"string","description":"The request field to change."},"message":{"type":"string"},"violations":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"param":{"type":"string"},"message":{"type":"string"},"allowed":{},"received":{}}}},"blanks":{"type":"array","description":"Blanks still to fill, for TEMPLATE_BLANKS_UNFILLED.","items":{"type":"object","properties":{"name":{"type":"string"},"placeholder":{"type":["null","string"]}}}}}}}}},"503":{"description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","content":{"application/json":{"schema":{"type":"object","description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"code":{"type":"string"},"param":{"type":"string","description":"The request field to change."},"message":{"type":"string"},"violations":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"param":{"type":"string"},"message":{"type":"string"},"allowed":{},"received":{}}}},"blanks":{"type":"array","description":"Blanks still to fill, for TEMPLATE_BLANKS_UNFILLED.","items":{"type":"object","properties":{"name":{"type":"string"},"placeholder":{"type":["null","string"]}}}}}}}}}}}},"/semantic-search/search":{"post":{"operationId":"semanticSearchSurveys","summary":"Search completed surveys","tags":["Semantic Search"],"description":"Searches completed surveys in your enrolled team account using vector semantic retrieval. The team is resolved from the Bearer token.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["query"],"properties":{"query":{"type":"string","minLength":1,"maxLength":500,"description":"Natural-language search query"},"limit":{"type":"integer","minimum":1,"maximum":50,"default":20,"description":"Maximum number of survey results to return"},"target":{"type":"string","enum":["all","surveys","answers"],"default":"all","description":"Which semantic namespace to query. Defaults to all; MCP survey and answer tools pin this server-side."},"filters":{"type":"object","additionalProperties":false,"properties":{"includeEvidence":{"type":"boolean","default":true,"description":"Whether to include matching snippets for each result"}}}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"surveyGuid":{"type":"string"},"title":{"type":"string"},"question":{"type":"string"},"score":{"type":"number"},"matchedTypes":{"type":"array","items":{"type":"string","enum":["survey","answer"]}},"evidence":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["survey","answer"]},"id":{"type":"string"},"snippet":{"type":"string"}}}},"metadata":{"type":"object","properties":{"completedAt":{"type":"string"},"createdAt":{"type":"string"},"publishedAt":{"type":"string"},"updatedAt":{"type":"string"},"countryCode":{"type":"string"},"questionTypes":{"type":"array","items":{"type":"string"}},"tags":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}}},"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"}}}}}}}}},"meta":{"type":"object","properties":{"limit":{"type":"integer"},"total":{"type":"integer"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"502":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"503":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys/{id}":{"get":{"operationId":"getSurvey","summary":"Get survey","tags":["Surveys"],"description":"Retrieves a survey by its unique GUID, including all questions, answer options, respondent answers (if complete), and AI-generated summaries.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"},{"schema":{"type":["string","null"]},"in":"path","name":"questionId","required":true,"description":"Filter to a specific question by its GUID"},{"schema":{"type":["string","null"]},"in":"path","name":"language","required":true,"description":"Language code for response translations (e.g. ES, FR, DE)"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","description":"Full survey data including questions, options, and metadata","properties":{"id":{"type":"string","description":"Unique survey GUID"},"name":{"type":["string","null"],"description":"Survey name/title"},"country":{"type":"string","description":"Two-letter country code (e.g. US, GB)"},"currency":{"type":"string","description":"ISO 4217 currency derived from the survey target country"},"sampleSize":{"type":"number","description":"Number of respondents requested"},"numResponses":{"type":["number","null"],"description":"Number of responses collected so far"},"status":{"type":"string","description":"Survey status: unpublished, in-progress, completed, or archived (deleted is also possible here for soft-deleted surveys, which the list endpoint excludes). Same vocabulary as the list endpoint — a survey always has the identical status string on both."},"targeting":{"type":"array","items":{"type":"string"},"description":"Array of targeting trait permalinks applied to this survey"},"reporting":{"type":"array","items":{"type":"string"},"description":"Array of reporting trait permalinks for demographic breakdowns"},"reportingDefaultsApplied":{"type":"array","items":{"type":"string"},"description":"Reporting trait permalinks that were auto-injected as free defaults (based on plan level and country), not explicitly requested by the caller"},"tags":{"type":"array","description":"Tags associated with the survey","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string","description":"Tag name"}}}},"projects":{"type":"array","description":"Projects the survey belongs to","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":"string","description":"Project name"}}}},"surveyUrl":{"type":"string","description":"Public URL to view the survey results"},"surveyIntent":{"type":"string","description":"AI-interpreted intent of the survey"},"externalId":{"type":"string","description":"Optional opaque correlation key for your own records. Omitted when unset. Case-sensitive and byte-exact. Many surveys may share the same id. We do not interpret this value."},"template":{"type":["object","null"],"description":"The template the survey was made from and the limits it must meet to publish, or null. Edits that break a limit are rejected.","properties":{"id":{"type":["string","null"],"description":"Template id (cmb_...), or null when the template can no longer be addressed"},"name":{"type":"string"},"constraints":{"type":"object","additionalProperties":false,"required":["questionTypes","optionTypes","optionCount","sampleSizes","defaultSampleSize","countries","defaultCountry"],"properties":{"questionTypes":{"type":"array","items":{"type":"string","enum":["head_to_head","ranked","open_ended","star_rating","click_test"]}},"optionTypes":{"type":"array","items":{"type":"string","enum":["text","image","video","url","product","image-set","audio"]}},"optionCount":{"type":"object","additionalProperties":false,"required":["min","max"],"properties":{"min":{"type":"integer"},"max":{"type":"integer"}}},"sampleSizes":{"type":"array","items":{"type":"string"}},"defaultSampleSize":{"type":"string"},"countries":{"type":"array","items":{"type":"string"}},"defaultCountry":{"type":"string"}}}}},"questions":{"type":"array","description":"Questions in the survey with options, responses, and AI metadata","items":{"type":"object","properties":{"id":{"type":"string","description":"Question ID (GUID)"},"type":{"type":"string","description":"Question type (head_to_head, ranked, open_ended, click_test, emoji_rating, star_rating, five_second_test, screen_recording, single_select, multi_select, likert, van_westendorp)"},"variant":{"type":["string","null"],"description":"Question variant for specialized display modes"},"value":{"type":"string","description":"Question text"},"translation":{"type":["string","null"],"description":"Translated question text"},"likertScale":{"type":["string","null"],"enum":["agreement5","agreement7","frequency","satisfaction",null],"description":"Likert scale preset, returned for likert questions whose variant matches one of the canonical presets. Null for non-likert questions or legacy likert questions with no recognized variant."},"options":{"type":["array","null"],"items":{"type":"object","properties":{"id":{"type":"string","description":"Option GUID for round-trip updates"},"label":{"type":"string","description":"Option identifier label (e.g. \"Option A\")"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Option content: text string, Cloudinary URL, or array of URLs (image-set)"},"type":{"type":"string","description":"Option data type: text, image, video, product, or image-set"},"translation":{"type":["string","null"],"description":"Translated option text"},"product":{"type":["object","null"],"description":"Product data for product-type options (ASIN or custom mockups)","properties":{"asin":{"type":["string","null"],"description":"Amazon ASIN (null for custom mockups)"},"title":{"type":"string","description":"Product title"},"price":{"type":"number","description":"Product price"},"salePrice":{"type":["number","null"],"description":"Discounted/sale price. null when the product is not on sale."},"currency":{"type":["string","null"],"description":"Currency code for the price"},"rating":{"type":"number","description":"Star rating (0-5)"},"reviews":{"type":"number","description":"Number of reviews"},"reviewScore":{"type":["number","null"],"description":"Alias of rating for public API round-trip"},"numRatings":{"type":["number","null"],"description":"Alias of reviews for public API round-trip"},"image":{"type":"string","description":"Product image URL"}}},"imageSetDirection":{"type":"string","description":"Image stack layout direction: horizontal or vertical (image-set options only)"},"mockupType":{"type":"string","description":"Product mockup rendering style: serp or listing (product options only)"},"mockup":{"type":"object","description":"The mockup template a text option shows: `template` is its lookup key and `values` its stored field values, images at their PickFu media CDN copies. `values` leaves out the display field, which is the option's `value`. On update, leaving `mockup` out or sending it back unchanged keeps the page, and `mockup: null` removes the question's template.","properties":{"template":{"type":"string"},"values":{"type":"object","additionalProperties":true}}}}},"description":"Answer options for this question"},"context":{"type":["object","null"],"description":"Additional context provided with the question (e.g. a product description or image)","properties":{"type":{"type":"string","description":"Context type (text or media)"},"value":{"type":"string","description":"Context content: the text, or for media the hosted media URL"},"text":{"type":"string","description":"Caption shown with the image. Present only on a media context that has one; send it back with the media URL to keep both."},"translation":{"type":["string","null"],"description":"Translated context text"}}},"results":{"type":["object","null"],"description":"Aggregated, page-faithful summary of the outcome for this question — the same percentages and ranking shown on the results page. Null for question types without a simple per-option aggregate (open_ended, click_test, likert, five_second_test, screen_recording, round_robin) or before any responses arrive. For ranked questions, `votes` is the final instant-runoff tally the percentage is computed from, and differs from the first-choice count shown beside each option on the page; the winner exceeds 50%.","properties":{"totalResponses":{"type":"number","description":"Number of valid responses the percentages are computed against"},"winningOptionId":{"type":["string","null"],"description":"GUID of the winning option, or null on a tie / before a winner is decided"},"averageScore":{"type":"number","description":"Average rating, returned for rating questions only (emoji_rating, star_rating)"},"options":{"type":"array","description":"Per-option results, ordered by rank (winner first)","items":{"type":"object","properties":{"id":{"type":"string","description":"Option GUID"},"label":{"type":["string","null"],"description":"Option label (e.g. \"A\")"},"votes":{"type":"number","description":"Vote count; the final instant-runoff tally for ranked questions"},"percentage":{"type":"number","description":"round(votes / totalResponses * 100), matching the results page"},"rank":{"type":["number","null"],"description":"Final placement (1 = winner)"},"isWinner":{"type":"boolean","description":"Whether this option is the winner"}}}}}},"responses":{"type":"array","description":"Respondent answers for this question","items":{"type":"object","properties":{"id":{"type":"string","description":"Response ID"},"pinned":{"type":"boolean","description":"Whether the response is pinned"},"explanation":{"type":["string","null"],"description":"Written explanation from the respondent"},"translation":{"type":["string","null"],"description":"Translated explanation text"},"chosenOption":{"type":["string","null"],"description":"Label of the option chosen by the respondent"},"selectedOptions":{"type":["array","null"],"description":"Labels of options selected by the respondent for multi-select questions","items":{"type":"string"}},"score":{"type":["number","null"],"description":"Rating score (for emoji_rating, star_rating question types)"},"clicks":{"type":["array","null"],"description":"Click coordinates for click_test questions","items":{"type":"object","properties":{"number":{"type":"number","description":"Click sequence number"},"xCoord":{"type":"number","description":"X coordinate of the click"},"yCoord":{"type":"number","description":"Y coordinate of the click"}}}},"ranking":{"type":["array","null"],"description":"Respondent's ranking of options for ranked question types. Each entry pairs a rank (1 = top pick) with the option label.","items":{"type":"object","properties":{"rank":{"type":"number","description":"Rank position (1 = respondent's top pick)"},"option":{"type":["string","null"],"description":"Option label at this rank"}}}},"media":{"type":["string","null"],"description":"Media URL (for screen_recording question types)"},"mediaTranscription":{"type":["string","null"],"description":"Transcription of the recorded media"},"matchup":{"type":["object","null"],"description":"Head-to-head matchup pairing shown to the respondent","properties":{"option1":{"type":"string","description":"First option in the matchup"},"option2":{"type":"string","description":"Second option in the matchup"}}},"statements":{"type":["array","null"],"description":"Per-statement responses for likert question types. Each entry pairs a statement with the numeric value the respondent picked on the configured scale. DEV-3149.","items":{"type":"object","properties":{"id":{"type":"string","description":"GUID of the statement (the question option)"},"statement":{"type":["string","null"],"description":"Statement text"},"value":{"type":"number","description":"Numeric value the respondent picked on the Likert scale (1..N for the configured scale)"}}}},"prices":{"type":["object","null"],"description":"Van Westendorp price-sensitivity responses. Four numeric prices the respondent provided for the four standardized PSM questions.","properties":{"tooCheap":{"type":"number","description":"Price at which the product would be so cheap that quality is questionable"},"bargain":{"type":"number","description":"Price at which the product would be a bargain"},"expensive":{"type":"number","description":"Price at which the product starts to feel expensive but is still worth considering"},"tooExpensive":{"type":"number","description":"Price at which the product would be too expensive to consider"}}},"respondent":{"type":"array","description":"Demographic traits of the respondent","items":{"type":"object","properties":{"trait":{"type":"string","description":"Trait category name"},"value":{"type":"string","description":"Trait value"}}}}}}},"ai":{"type":"object","description":"AI-generated metadata such as summaries and key themes for this question","additionalProperties":{"type":"string"}}}}},"pace":{"type":"object","additionalProperties":false,"description":"Live pace of a poll that is still collecting responses. Present only while the poll is in progress and only for users who can edit it.","properties":{"publishedAt":{"type":"string","description":"When the poll went live (ISO 8601)"},"elapsedMinutes":{"type":"number","description":"Whole minutes since the poll went live"},"typical":{"type":["object","null"],"additionalProperties":false,"description":"How long recent polls like this took to fill, or null when there are too few to compare","properties":{"minutesToQuarter":{"type":"number","description":"Median minutes from launch until recent polls like this were a quarter full"},"minutesToHalf":{"type":"number","description":"Median minutes from launch until recent polls like this were half full"},"minutesToThreeQuarters":{"type":"number","description":"Median minutes from launch until recent polls like this were three-quarters full"},"minutesToFinish":{"type":"number","description":"Median minutes from launch until recent polls like this were finished"},"basis":{"type":"string","enum":["same_audience","similar_audience"],"description":"same_audience: recent polls with the same targeting, country and size; similar_audience: recent polls with the same country and size that were also targeted"}}},"yourHistory":{"type":["object","null"],"additionalProperties":false,"description":"The poll owner's own recent polls like this one. Null for anyone but the owner, and when there are too few","properties":{"medianMinutesToFinish":{"type":"number","description":"Median minutes from launch until they finished"}}}}}}}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"code":{"type":"string"},"availableLanguages":{"type":"array","items":{"type":"string"}}}}}}}}},"delete":{"operationId":"deleteSurvey","summary":"Delete survey","tags":["Surveys"],"description":"Deletes or archives a survey depending on its state:\n\n- **Draft surveys** (unpublished) are soft-deleted and will no longer appear in listings\n- **Published surveys** (with or without responses) are archived — their data is preserved but they are hidden from default listings\n\nThis operation is idempotent: deleting an already-archived survey returns 200 with `action: \"archived\"`.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey ID (GUID)"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"action":{"type":"string","enum":["deleted","archived"]}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}}}},"patch":{"operationId":"updateSurvey","summary":"Update survey","tags":["Surveys"],"description":"Updates a draft survey. All fields use replace-all semantics — for example, sending `tags` replaces all existing tags, and sending `questions` replaces all existing questions.\n\nOnly surveys in `unpublished` (draft) status can be updated. You can update the name, tags, project, questions, targeting, reporting, country, sample size, and survey intent.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255,"description":"Survey name (1-255 characters, trimmed)"},"tags":{"type":"array","maxItems":10,"description":"Tags to replace all existing tags. Each item has either id or name.","items":{"type":"object","oneOf":[{"required":["id"],"properties":{"id":{"type":["string","number"],"description":"Existing tag ID — opaque identifier (tag_<32-hex>) or legacy integer"}},"additionalProperties":false},{"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Tag name (will find or create)"}},"additionalProperties":false}]}},"projectId":{"type":["string","number","null"],"description":"Project GUID (string) or numeric ID to associate, or null to remove project. Mutually exclusive with `projects`."},"projects":{"type":"array","maxItems":50,"description":"Project GUIDs (or numeric IDs) to associate the survey with. Replace-all semantics. Mutually exclusive with `projectId`.","items":{"type":["string","number"]}},"questions":{"type":"array","minItems":1,"maxItems":24,"description":"Questions to replace all existing questions (replace-all semantics)","items":{"type":"object","required":["type","prompt"],"properties":{"id":{"type":"string","description":"Question GUID from GET response. Include to update in-place (preserving response data). Omit to create as new."},"type":{"type":"string","enum":["head_to_head","ranked","open_ended","click_test","emoji_rating","star_rating","five_second_test","screen_recording","single_select","multi_select","likert","van_westendorp"],"description":"Question type. Every type except screen_recording automatically collects a required written explanation from each respondent, returned as the response's `explanation` field. Do NOT add a separate open_ended question to capture 'why' — it duplicates the built-in explanation and wastes a question slot (multi-question surveys are priced per question)."},"prompt":{"type":"string","description":"Question text prompt (max 255 chars). Every response automatically includes a required written explanation from the respondent for all types except screen_recording — phrase the real question here and PickFu collects the 'why' automatically.","maxLength":255},"variant":{"type":["string","null"],"description":"Persisted question variant. For likert questions, accepts canonical variant slugs returned by GET."},"likertScale":{"type":"string","enum":["agreement5","agreement7","frequency","satisfaction"],"description":"Likert scale preset. Only honored when type=likert. On PATCH, omitting this field leaves the existing scale unchanged. DEV-3128."},"context":{"type":"object","description":"Context provided with the question: text, a mediaUrl, or both (text is then the caption shown with the image, and mediaUrl must be an image URL). Also accepts the {type, value, text?} format from GET responses.","properties":{"text":{"type":"string"},"mediaUrl":{"type":"string"},"type":{"type":"string"},"value":{"type":"string"}}},"options":{"type":"array","description":"Options for the question","items":{"type":"object","additionalProperties":false,"properties":{"id":{"type":"string","description":"Option GUID from GET response. Include to update in-place. Omit to create as new."},"value":{"type":"string","maxLength":5000},"mediaUrl":{"type":"string"},"asin":{"type":"string","pattern":"^[A-Z0-9]{10}$","maxLength":10},"imageSet":{"type":"array","items":{"anyOf":[{"type":"string"},{"type":"object","required":["source","id"],"additionalProperties":false,"properties":{"source":{"type":"string","enum":["amazon","walmart","google_play","apple"]},"id":{"type":"string","minLength":1}}}]},"minItems":1},"imageSetDirection":{"type":"string","enum":["vertical","horizontal","a-plus"]},"mockup":{"type":["object","null"],"description":"Either an Amazon product mockup (`type`, `image`, `title`, `price`, …) or a first-party mockup template (`template` with `values`, `import` or both), never both. A template keeps the option a text option: send `value` as well, which is the option's text and fills the template's display field. Every option of a question names the same template, or none does. List the templates and the values each takes with GET /v1/mockup-templates. On update, leaving `mockup` out keeps the option's page, and `null` removes the question's mockup template from every option.","properties":{"type":{"type":"string","enum":["serp","listing"]},"image":{"type":"string"},"title":{"type":"string"},"numRatings":{"type":"number"},"reviewScore":{"type":"number"},"rating":{"type":"number"},"reviews":{"type":"number"},"price":{"type":"number"},"currency":{"type":"string"},"template":{"type":"string","minLength":1,"description":"Lookup key of a mockup template from GET /v1/mockup-templates, such as `app-store-page`."},"values":{"type":"object","description":"The template's field values, keyed by field name, as its `valuesSchema` describes. Leave out the display field: it is the option's `value`."},"import":{"type":"object","description":"A store listing that fills the template's values before the survey is saved, for templates whose `importSources` list the store. `values` sent beside it win, so send the fields a store does not provide, such as an App Store subtitle, there. The option's `value` stays its text. Images are copied to PickFu's media CDN as when sent in `values`.","required":["source","id"],"additionalProperties":false,"properties":{"source":{"type":"string","enum":["apple"]},"id":{"type":"string","minLength":1,"maxLength":500,"description":"The app: an App Store link such as https://apps.apple.com/us/app/name/id123456789, or the number after \"id\"."},"country":{"type":"string","pattern":"^[A-Za-z]{2}$","description":"Two-letter storefront to read the listing from when the link names none. Defaults to the survey's country."}}}}}}}}}}},"targeting":{"type":"array","items":{"type":"string"},"description":"Targeting trait permalinks (replace-all semantics)"},"reporting":{"type":"array","items":{"type":"string"},"description":"Reporting trait permalinks (replace-all semantics)"},"country":{"type":"string","description":"Two-letter country code (e.g. US)"},"sampleSize":{"type":"string","description":"Number of respondents. Standard surveys: \"15\", \"30\", \"50\", \"75\", \"100\", \"200\", \"300\", \"500\". Screen recording surveys: \"5\", \"10\", \"15\", \"20\", \"25\", \"30\", \"50\", \"75\" (max 75)."},"surveyIntent":{"type":"string","maxLength":255,"description":"Original intent of the survey as interpreted by AI (max 255 characters)"},"externalId":{"type":"string","minLength":1,"maxLength":255,"description":"Optional opaque correlation key for your own records. Omit when unset. Case-sensitive and byte-exact — send the identical string every time. Many surveys may share the same id. We do not interpret this value."},"template":{"type":"object","description":"Create only: sending it here is a 400. Edit a draft made from a template with `questions`, using the ids from GET /v1/surveys/{id}; its edits must stay within the template limits shown in `template.constraints`."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","description":"Full survey data including questions, options, and metadata","properties":{"id":{"type":"string","description":"Unique survey GUID"},"name":{"type":["string","null"],"description":"Survey name/title"},"country":{"type":"string","description":"Two-letter country code (e.g. US, GB)"},"currency":{"type":"string","description":"ISO 4217 currency derived from the survey target country"},"sampleSize":{"type":"number","description":"Number of respondents requested"},"numResponses":{"type":["number","null"],"description":"Number of responses collected so far"},"status":{"type":"string","description":"Survey status: unpublished, in-progress, completed, or archived (deleted is also possible here for soft-deleted surveys, which the list endpoint excludes). Same vocabulary as the list endpoint — a survey always has the identical status string on both."},"targeting":{"type":"array","items":{"type":"string"},"description":"Array of targeting trait permalinks applied to this survey"},"reporting":{"type":"array","items":{"type":"string"},"description":"Array of reporting trait permalinks for demographic breakdowns"},"reportingDefaultsApplied":{"type":"array","items":{"type":"string"},"description":"Reporting trait permalinks that were auto-injected as free defaults (based on plan level and country), not explicitly requested by the caller"},"tags":{"type":"array","description":"Tags associated with the survey","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string","description":"Tag name"}}}},"projects":{"type":"array","description":"Projects the survey belongs to","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":"string","description":"Project name"}}}},"surveyUrl":{"type":"string","description":"Public URL to view the survey results"},"surveyIntent":{"type":"string","description":"AI-interpreted intent of the survey"},"externalId":{"type":"string","description":"Optional opaque correlation key for your own records. Omitted when unset. Case-sensitive and byte-exact. Many surveys may share the same id. We do not interpret this value."},"template":{"type":["object","null"],"description":"The template the survey was made from and the limits it must meet to publish, or null. Edits that break a limit are rejected.","properties":{"id":{"type":["string","null"],"description":"Template id (cmb_...), or null when the template can no longer be addressed"},"name":{"type":"string"},"constraints":{"type":"object","additionalProperties":false,"required":["questionTypes","optionTypes","optionCount","sampleSizes","defaultSampleSize","countries","defaultCountry"],"properties":{"questionTypes":{"type":"array","items":{"type":"string","enum":["head_to_head","ranked","open_ended","star_rating","click_test"]}},"optionTypes":{"type":"array","items":{"type":"string","enum":["text","image","video","url","product","image-set","audio"]}},"optionCount":{"type":"object","additionalProperties":false,"required":["min","max"],"properties":{"min":{"type":"integer"},"max":{"type":"integer"}}},"sampleSizes":{"type":"array","items":{"type":"string"}},"defaultSampleSize":{"type":"string"},"countries":{"type":"array","items":{"type":"string"}},"defaultCountry":{"type":"string"}}}}},"questions":{"type":"array","description":"Questions in the survey with options, responses, and AI metadata","items":{"type":"object","properties":{"id":{"type":"string","description":"Question ID (GUID)"},"type":{"type":"string","description":"Question type (head_to_head, ranked, open_ended, click_test, emoji_rating, star_rating, five_second_test, screen_recording, single_select, multi_select, likert, van_westendorp)"},"variant":{"type":["string","null"],"description":"Question variant for specialized display modes"},"value":{"type":"string","description":"Question text"},"translation":{"type":["string","null"],"description":"Translated question text"},"likertScale":{"type":["string","null"],"enum":["agreement5","agreement7","frequency","satisfaction",null],"description":"Likert scale preset, returned for likert questions whose variant matches one of the canonical presets. Null for non-likert questions or legacy likert questions with no recognized variant."},"options":{"type":["array","null"],"items":{"type":"object","properties":{"id":{"type":"string","description":"Option GUID for round-trip updates"},"label":{"type":"string","description":"Option identifier label (e.g. \"Option A\")"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Option content: text string, Cloudinary URL, or array of URLs (image-set)"},"type":{"type":"string","description":"Option data type: text, image, video, product, or image-set"},"translation":{"type":["string","null"],"description":"Translated option text"},"product":{"type":["object","null"],"description":"Product data for product-type options (ASIN or custom mockups)","properties":{"asin":{"type":["string","null"],"description":"Amazon ASIN (null for custom mockups)"},"title":{"type":"string","description":"Product title"},"price":{"type":"number","description":"Product price"},"salePrice":{"type":["number","null"],"description":"Discounted/sale price. null when the product is not on sale."},"currency":{"type":["string","null"],"description":"Currency code for the price"},"rating":{"type":"number","description":"Star rating (0-5)"},"reviews":{"type":"number","description":"Number of reviews"},"reviewScore":{"type":["number","null"],"description":"Alias of rating for public API round-trip"},"numRatings":{"type":["number","null"],"description":"Alias of reviews for public API round-trip"},"image":{"type":"string","description":"Product image URL"}}},"imageSetDirection":{"type":"string","description":"Image stack layout direction: horizontal or vertical (image-set options only)"},"mockupType":{"type":"string","description":"Product mockup rendering style: serp or listing (product options only)"},"mockup":{"type":"object","description":"The mockup template a text option shows: `template` is its lookup key and `values` its stored field values, images at their PickFu media CDN copies. `values` leaves out the display field, which is the option's `value`. On update, leaving `mockup` out or sending it back unchanged keeps the page, and `mockup: null` removes the question's template.","properties":{"template":{"type":"string"},"values":{"type":"object","additionalProperties":true}}}}},"description":"Answer options for this question"},"context":{"type":["object","null"],"description":"Additional context provided with the question (e.g. a product description or image)","properties":{"type":{"type":"string","description":"Context type (text or media)"},"value":{"type":"string","description":"Context content: the text, or for media the hosted media URL"},"text":{"type":"string","description":"Caption shown with the image. Present only on a media context that has one; send it back with the media URL to keep both."},"translation":{"type":["string","null"],"description":"Translated context text"}}},"results":{"type":["object","null"],"description":"Aggregated, page-faithful summary of the outcome for this question — the same percentages and ranking shown on the results page. Null for question types without a simple per-option aggregate (open_ended, click_test, likert, five_second_test, screen_recording, round_robin) or before any responses arrive. For ranked questions, `votes` is the final instant-runoff tally the percentage is computed from, and differs from the first-choice count shown beside each option on the page; the winner exceeds 50%.","properties":{"totalResponses":{"type":"number","description":"Number of valid responses the percentages are computed against"},"winningOptionId":{"type":["string","null"],"description":"GUID of the winning option, or null on a tie / before a winner is decided"},"averageScore":{"type":"number","description":"Average rating, returned for rating questions only (emoji_rating, star_rating)"},"options":{"type":"array","description":"Per-option results, ordered by rank (winner first)","items":{"type":"object","properties":{"id":{"type":"string","description":"Option GUID"},"label":{"type":["string","null"],"description":"Option label (e.g. \"A\")"},"votes":{"type":"number","description":"Vote count; the final instant-runoff tally for ranked questions"},"percentage":{"type":"number","description":"round(votes / totalResponses * 100), matching the results page"},"rank":{"type":["number","null"],"description":"Final placement (1 = winner)"},"isWinner":{"type":"boolean","description":"Whether this option is the winner"}}}}}},"responses":{"type":"array","description":"Respondent answers for this question","items":{"type":"object","properties":{"id":{"type":"string","description":"Response ID"},"pinned":{"type":"boolean","description":"Whether the response is pinned"},"explanation":{"type":["string","null"],"description":"Written explanation from the respondent"},"translation":{"type":["string","null"],"description":"Translated explanation text"},"chosenOption":{"type":["string","null"],"description":"Label of the option chosen by the respondent"},"selectedOptions":{"type":["array","null"],"description":"Labels of options selected by the respondent for multi-select questions","items":{"type":"string"}},"score":{"type":["number","null"],"description":"Rating score (for emoji_rating, star_rating question types)"},"clicks":{"type":["array","null"],"description":"Click coordinates for click_test questions","items":{"type":"object","properties":{"number":{"type":"number","description":"Click sequence number"},"xCoord":{"type":"number","description":"X coordinate of the click"},"yCoord":{"type":"number","description":"Y coordinate of the click"}}}},"ranking":{"type":["array","null"],"description":"Respondent's ranking of options for ranked question types. Each entry pairs a rank (1 = top pick) with the option label.","items":{"type":"object","properties":{"rank":{"type":"number","description":"Rank position (1 = respondent's top pick)"},"option":{"type":["string","null"],"description":"Option label at this rank"}}}},"media":{"type":["string","null"],"description":"Media URL (for screen_recording question types)"},"mediaTranscription":{"type":["string","null"],"description":"Transcription of the recorded media"},"matchup":{"type":["object","null"],"description":"Head-to-head matchup pairing shown to the respondent","properties":{"option1":{"type":"string","description":"First option in the matchup"},"option2":{"type":"string","description":"Second option in the matchup"}}},"statements":{"type":["array","null"],"description":"Per-statement responses for likert question types. Each entry pairs a statement with the numeric value the respondent picked on the configured scale. DEV-3149.","items":{"type":"object","properties":{"id":{"type":"string","description":"GUID of the statement (the question option)"},"statement":{"type":["string","null"],"description":"Statement text"},"value":{"type":"number","description":"Numeric value the respondent picked on the Likert scale (1..N for the configured scale)"}}}},"prices":{"type":["object","null"],"description":"Van Westendorp price-sensitivity responses. Four numeric prices the respondent provided for the four standardized PSM questions.","properties":{"tooCheap":{"type":"number","description":"Price at which the product would be so cheap that quality is questionable"},"bargain":{"type":"number","description":"Price at which the product would be a bargain"},"expensive":{"type":"number","description":"Price at which the product starts to feel expensive but is still worth considering"},"tooExpensive":{"type":"number","description":"Price at which the product would be too expensive to consider"}}},"respondent":{"type":"array","description":"Demographic traits of the respondent","items":{"type":"object","properties":{"trait":{"type":"string","description":"Trait category name"},"value":{"type":"string","description":"Trait value"}}}}}}},"ai":{"type":"object","description":"AI-generated metadata such as summaries and key themes for this question","additionalProperties":{"type":"string"}}}}}}},"cost":{"type":"object","description":"Cost information for the survey","properties":{"amount":{"type":"number","description":"Survey cost in dollars"},"balance":{"type":"number","description":"Credit balance in dollars"},"currency":{"type":"string","description":"Currency code (USD)"},"canPayWithBalance":{"type":"boolean","description":"Whether balance covers the cost"},"quotedCreditsCost":{"type":"number","description":"Post-discount cost in credits, after free credits applied (1 credit = $2 USD)"},"creditsCostSubtotal":{"type":"number","description":"Pre-discount cost in credits (1 credit = $2 USD)"},"discounts":{"type":"array","description":"Credit-side discount line items, each entry is [label, amountInCredits]. Amounts are denominated in credits so they subtract directly from creditsCostSubtotal","items":{"type":"array","items":{"type":"string"}}},"discountsMoney":{"type":"array","description":"Dollar-side discount line items, each entry is [label, formattedDollarAmount] (e.g. \"$20.08\")","items":{"type":"array","items":{"type":"string"}}},"planRequired":{"type":["null","string"],"description":"Plan tier required for current survey configuration, or null if the current plan is sufficient"},"priceLines":{"type":"array","description":"The survey builder's price summary, each entry is [label, formattedDollarAmount] (e.g. [\"Head-to-Head: Text Length (+1.2x)\", \"$10.00\"]). Each amount is that line's cost for the whole sample: base price, extra options, text or video length, targeting and reporting. A $0.00 line is included free. The lines come before discounts: they add up to `creditsCostSubtotal` in dollars, and `discountsMoney` takes that down to `amount`","items":{"type":"array","items":{"type":"string"}}}}},"completionEstimate":{"type":"object","description":"Estimated completion-time bucket for the current audience","properties":{"bucket":{"type":"string","description":"Completion-time bucket: SUPER_EASY (<2h), EASY (1-2 days), MEDIUM (up to 2 weeks), HARD (may take longer), MAY_NOT_COMPLETE"},"estimatedMinutes":{"type":["null","number"],"description":"Estimated completion time in minutes, or null when unavailable"},"status":{"type":"string","description":"ready when an estimate exists, pending while computing"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"code":{"type":"string"},"param":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"422":{"description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","content":{"application/json":{"schema":{"type":"object","description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"code":{"type":"string"},"param":{"type":"string","description":"The request field to change."},"message":{"type":"string"},"violations":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"param":{"type":"string"},"message":{"type":"string"},"allowed":{},"received":{}}}},"blanks":{"type":"array","description":"Blanks still to fill, for TEMPLATE_BLANKS_UNFILLED.","items":{"type":"object","properties":{"name":{"type":"string"},"placeholder":{"type":["null","string"]}}}}}}}}},"428":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"429":{"description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","content":{"application/json":{"schema":{"type":"object","description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"code":{"type":"string"},"param":{"type":"string","description":"The request field to change."},"message":{"type":"string"},"violations":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"param":{"type":"string"},"message":{"type":"string"},"allowed":{},"received":{}}}},"blanks":{"type":"array","description":"Blanks still to fill, for TEMPLATE_BLANKS_UNFILLED.","items":{"type":"object","properties":{"name":{"type":"string"},"placeholder":{"type":["null","string"]}}}}}}}}},"503":{"description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","content":{"application/json":{"schema":{"type":"object","description":"A request a template cannot satisfy: the first problem as `code` and `param`, and every problem in `violations`. A product combo template lists each limit with its allowed and received values; a mockup template lists each option field to change, as a path such as `questions[0].options[1].mockup.values.icon`.","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"code":{"type":"string"},"param":{"type":"string","description":"The request field to change."},"message":{"type":"string"},"violations":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"param":{"type":"string"},"message":{"type":"string"},"allowed":{},"received":{}}}},"blanks":{"type":"array","description":"Blanks still to fill, for TEMPLATE_BLANKS_UNFILLED.","items":{"type":"object","properties":{"name":{"type":"string"},"placeholder":{"type":["null","string"]}}}}}}}}}}}},"/surveys/{id}/responses":{"get":{"operationId":"getSurveyResponses","summary":"Get survey responses","tags":["Responses"],"description":"Returns paginated individual responses for a survey. Each response includes the respondent's answer, written explanation, demographic traits, and media (if applicable). Use `question_id` to filter responses to a specific question, `text` to search response explanations, and `traits` to filter by respondent demographics.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"in":"query","name":"limit","required":false,"description":"Results per page (1-100)"},{"schema":{"type":"string"},"in":"query","name":"question_id","required":false,"description":"Filter responses to a specific question by its GUID"},{"schema":{"type":"string"},"in":"query","name":"language","required":false,"description":"Language code for response translations (e.g. ES, FR, DE)"},{"schema":{"type":"string","maxLength":255},"in":"query","name":"text","required":false,"description":"Keyword to filter responses by explanation text (case-insensitive)"},{"schema":{"type":"string"},"in":"query","name":"traits","required":false,"description":"Comma-separated trait value permalinks to filter by respondent demographics (e.g. \"male,age-25-34\"). Values within the same trait use OR logic; across different traits use AND logic."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","description":"ISO 4217 currency derived from the survey target country"},"data":{"type":"array","description":"List of individual responses","items":{"type":"object","properties":{"id":{"type":"string","description":"Response ID"},"pinned":{"type":"boolean","description":"Whether the response is pinned"},"explanation":{"type":["string","null"],"description":"Written explanation from the respondent"},"translation":{"type":["string","null"],"description":"Translated explanation text"},"chosenOption":{"type":["string","null"],"description":"Label of the option chosen by the respondent"},"selectedOptions":{"type":["array","null"],"description":"Labels of options selected by the respondent for multi-select questions","items":{"type":"string"}},"score":{"type":["number","null"],"description":"Rating score (for emoji_rating, star_rating question types)"},"clicks":{"type":["array","null"],"description":"Click coordinates for click_test questions","items":{"type":"object","properties":{"number":{"type":"number","description":"Click sequence number"},"xCoord":{"type":"number","description":"X coordinate of the click"},"yCoord":{"type":"number","description":"Y coordinate of the click"}}}},"ranking":{"type":["array","null"],"description":"Respondent's ranking of options for ranked question types. Each entry pairs a rank (1 = top pick) with the option label.","items":{"type":"object","properties":{"rank":{"type":"number","description":"Rank position (1 = respondent's top pick)"},"option":{"type":["string","null"],"description":"Option label at this rank"}}}},"media":{"type":["string","null"],"description":"Media URL (for screen_recording question types)"},"mediaTranscription":{"type":["string","null"],"description":"Transcription of the recorded media"},"matchup":{"type":["object","null"],"description":"Head-to-head matchup pairing shown to the respondent","properties":{"option1":{"type":"string","description":"First option in the matchup"},"option2":{"type":"string","description":"Second option in the matchup"}}},"statements":{"type":["array","null"],"description":"Per-statement responses for likert question types. Each entry pairs a statement with the numeric value the respondent picked on the configured scale. DEV-3149.","items":{"type":"object","properties":{"id":{"type":"string","description":"GUID of the statement (the question option)"},"statement":{"type":["string","null"],"description":"Statement text"},"value":{"type":"number","description":"Numeric value the respondent picked on the Likert scale (1..N for the configured scale)"}}}},"prices":{"type":["object","null"],"description":"Van Westendorp price-sensitivity responses. Four numeric prices the respondent provided for the four standardized PSM questions.","properties":{"tooCheap":{"type":"number","description":"Price at which the product would be so cheap that quality is questionable"},"bargain":{"type":"number","description":"Price at which the product would be a bargain"},"expensive":{"type":"number","description":"Price at which the product starts to feel expensive but is still worth considering"},"tooExpensive":{"type":"number","description":"Price at which the product would be too expensive to consider"}}},"respondent":{"type":"array","description":"Demographic traits of the respondent","items":{"type":"object","properties":{"trait":{"type":"string","description":"Trait category name"},"value":{"type":"string","description":"Trait value"}}}},"question_id":{"type":["string","null"],"description":"GUID of the question this response belongs to (for multi-question surveys)"}}}},"pagination":{"type":"object","description":"Pagination metadata","properties":{"page":{"type":"number","description":"Current page number"},"limit":{"type":"number","description":"Results per page"},"total":{"type":"number","description":"Total number of results"},"totalPages":{"type":"number","description":"Total number of pages"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"statusCode":{"type":"number"}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"code":{"type":"string"},"availableLanguages":{"type":"array","items":{"type":"string"}}}}}}}}}},"/surveys/{id}/responses/{responseId}/pin":{"put":{"operationId":"updateResponsePin","summary":"Pin or unpin a response","tags":["Responses"],"description":"Pins or unpins an individual response on a survey. Pinned responses are marked as noteworthy for easy retrieval. This is idempotent — pinning an already-pinned response returns 200 with the same state.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["pinned"],"properties":{"pinned":{"type":"boolean","description":"true to pin the response, false to unpin"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"},{"schema":{"type":"string"},"in":"path","name":"responseId","required":true,"description":"Response GUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string","description":"Response GUID"},"pinned":{"type":"boolean","description":"Pin state after update"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/responses/{id}/rate":{"post":{"operationId":"rateResponse","summary":"Rate a response","tags":["Responses"],"description":"Marks an individual respondent comment as helpful or not_helpful.\n\nCalling this with `rating: \"helpful\"` records a positive vote.\n\nCalling with `rating: \"not_helpful\"` flags the response as low-quality. For non-admin users this counts against a per-survey flag cap. Free (pay-as-you-go) survey owners may flag up to 10% of the sample size (rounded up); subscribed (PickFu+/Enterprise) owners have no cap. Returns 409 when the cap is exceeded. When the cap is not exceeded the response — and, on multi-question surveys, all responses from the same respondent — is automatically marked as rejected, the survey's valid-answer count is recalculated, and a previously completed survey may be reopened to collect replacement responses.\n\nThe endpoint is upserting: re-rating the same response replaces the previous rating and preserves any existing `comment` when one is not re-supplied. Switching a previous `not_helpful` rating to `helpful` records the new vote but does NOT un-reject the answer that was auto-rejected by the prior flag.\n\nUse `DELETE /v1/responses/{id}/rate` to remove a rating; note that DELETE does NOT un-reject an answer that was rejected by a prior `not_helpful` rating, and removing a flag does free up cap space — repeatedly flagging then deleting can reject more answers than the cap allows without tripping it.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["rating"],"additionalProperties":false,"properties":{"rating":{"type":"string","enum":["helpful","not_helpful"],"description":"Whether the response was helpful or not. \"not_helpful\" flags the response as low-quality and may auto-reject it; see endpoint description for the full effect."},"comment":{"type":"string","maxLength":500,"description":"Optional reason or note attached to the rating."}}}}}},"parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$","maxLength":64},"in":"path","name":"id","required":true,"description":"Response (answer) GUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string","description":"Response GUID"},"rating":{"type":"string","enum":["helpful","not_helpful"],"description":"The rating that was applied"},"comment":{"type":["string","null"]}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}},"delete":{"operationId":"deleteResponseRating","summary":"Remove a response rating","tags":["Responses"],"description":"Removes a previously-applied helpful / not_helpful rating from a response. Returns 404 if no rating exists. Does not un-reject answers that were auto-rejected by a prior not_helpful rating.","parameters":[{"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,64}$","maxLength":64},"in":"path","name":"id","required":true,"description":"Response (answer) GUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys/{id}/publish":{"post":{"operationId":"publishSurvey","summary":"Publish survey","tags":["Surveys"],"description":"Publishes a draft survey and begins collecting responses from the target audience.\n\n### Prerequisites\n- Survey must be in `unpublished` (draft) status\n- Account must have sufficient credits\n- All required fields must be complete (at least one question with options)\n\nAfter publishing, the survey status changes to `pending` or `in-progress` and credits are deducted from your account.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey ID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","description":"Full survey data including questions, options, and metadata","properties":{"id":{"type":"string","description":"Unique survey GUID"},"name":{"type":["string","null"],"description":"Survey name/title"},"country":{"type":"string","description":"Two-letter country code (e.g. US, GB)"},"currency":{"type":"string","description":"ISO 4217 currency derived from the survey target country"},"sampleSize":{"type":"number","description":"Number of respondents requested"},"numResponses":{"type":["number","null"],"description":"Number of responses collected so far"},"status":{"type":"string","description":"Survey status: unpublished, in-progress, completed, or archived (deleted is also possible here for soft-deleted surveys, which the list endpoint excludes). Same vocabulary as the list endpoint — a survey always has the identical status string on both."},"targeting":{"type":"array","items":{"type":"string"},"description":"Array of targeting trait permalinks applied to this survey"},"reporting":{"type":"array","items":{"type":"string"},"description":"Array of reporting trait permalinks for demographic breakdowns"},"reportingDefaultsApplied":{"type":"array","items":{"type":"string"},"description":"Reporting trait permalinks that were auto-injected as free defaults (based on plan level and country), not explicitly requested by the caller"},"tags":{"type":"array","description":"Tags associated with the survey","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string","description":"Tag name"}}}},"projects":{"type":"array","description":"Projects the survey belongs to","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":"string","description":"Project name"}}}},"surveyUrl":{"type":"string","description":"Public URL to view the survey results"},"surveyIntent":{"type":"string","description":"AI-interpreted intent of the survey"},"externalId":{"type":"string","description":"Optional opaque correlation key for your own records. Omitted when unset. Case-sensitive and byte-exact. Many surveys may share the same id. We do not interpret this value."},"template":{"type":["object","null"],"description":"The template the survey was made from and the limits it must meet to publish, or null. Edits that break a limit are rejected.","properties":{"id":{"type":["string","null"],"description":"Template id (cmb_...), or null when the template can no longer be addressed"},"name":{"type":"string"},"constraints":{"type":"object","additionalProperties":false,"required":["questionTypes","optionTypes","optionCount","sampleSizes","defaultSampleSize","countries","defaultCountry"],"properties":{"questionTypes":{"type":"array","items":{"type":"string","enum":["head_to_head","ranked","open_ended","star_rating","click_test"]}},"optionTypes":{"type":"array","items":{"type":"string","enum":["text","image","video","url","product","image-set","audio"]}},"optionCount":{"type":"object","additionalProperties":false,"required":["min","max"],"properties":{"min":{"type":"integer"},"max":{"type":"integer"}}},"sampleSizes":{"type":"array","items":{"type":"string"}},"defaultSampleSize":{"type":"string"},"countries":{"type":"array","items":{"type":"string"}},"defaultCountry":{"type":"string"}}}}},"questions":{"type":"array","description":"Questions in the survey with options, responses, and AI metadata","items":{"type":"object","properties":{"id":{"type":"string","description":"Question ID (GUID)"},"type":{"type":"string","description":"Question type (head_to_head, ranked, open_ended, click_test, emoji_rating, star_rating, five_second_test, screen_recording, single_select, multi_select, likert, van_westendorp)"},"variant":{"type":["string","null"],"description":"Question variant for specialized display modes"},"value":{"type":"string","description":"Question text"},"translation":{"type":["string","null"],"description":"Translated question text"},"likertScale":{"type":["string","null"],"enum":["agreement5","agreement7","frequency","satisfaction",null],"description":"Likert scale preset, returned for likert questions whose variant matches one of the canonical presets. Null for non-likert questions or legacy likert questions with no recognized variant."},"options":{"type":["array","null"],"items":{"type":"object","properties":{"id":{"type":"string","description":"Option GUID for round-trip updates"},"label":{"type":"string","description":"Option identifier label (e.g. \"Option A\")"},"value":{"oneOf":[{"type":"string"},{"type":"array","items":{"type":"string"}}],"description":"Option content: text string, Cloudinary URL, or array of URLs (image-set)"},"type":{"type":"string","description":"Option data type: text, image, video, product, or image-set"},"translation":{"type":["string","null"],"description":"Translated option text"},"product":{"type":["object","null"],"description":"Product data for product-type options (ASIN or custom mockups)","properties":{"asin":{"type":["string","null"],"description":"Amazon ASIN (null for custom mockups)"},"title":{"type":"string","description":"Product title"},"price":{"type":"number","description":"Product price"},"salePrice":{"type":["number","null"],"description":"Discounted/sale price. null when the product is not on sale."},"currency":{"type":["string","null"],"description":"Currency code for the price"},"rating":{"type":"number","description":"Star rating (0-5)"},"reviews":{"type":"number","description":"Number of reviews"},"reviewScore":{"type":["number","null"],"description":"Alias of rating for public API round-trip"},"numRatings":{"type":["number","null"],"description":"Alias of reviews for public API round-trip"},"image":{"type":"string","description":"Product image URL"}}},"imageSetDirection":{"type":"string","description":"Image stack layout direction: horizontal or vertical (image-set options only)"},"mockupType":{"type":"string","description":"Product mockup rendering style: serp or listing (product options only)"},"mockup":{"type":"object","description":"The mockup template a text option shows: `template` is its lookup key and `values` its stored field values, images at their PickFu media CDN copies. `values` leaves out the display field, which is the option's `value`. On update, leaving `mockup` out or sending it back unchanged keeps the page, and `mockup: null` removes the question's template.","properties":{"template":{"type":"string"},"values":{"type":"object","additionalProperties":true}}}}},"description":"Answer options for this question"},"context":{"type":["object","null"],"description":"Additional context provided with the question (e.g. a product description or image)","properties":{"type":{"type":"string","description":"Context type (text or media)"},"value":{"type":"string","description":"Context content: the text, or for media the hosted media URL"},"text":{"type":"string","description":"Caption shown with the image. Present only on a media context that has one; send it back with the media URL to keep both."},"translation":{"type":["string","null"],"description":"Translated context text"}}},"results":{"type":["object","null"],"description":"Aggregated, page-faithful summary of the outcome for this question — the same percentages and ranking shown on the results page. Null for question types without a simple per-option aggregate (open_ended, click_test, likert, five_second_test, screen_recording, round_robin) or before any responses arrive. For ranked questions, `votes` is the final instant-runoff tally the percentage is computed from, and differs from the first-choice count shown beside each option on the page; the winner exceeds 50%.","properties":{"totalResponses":{"type":"number","description":"Number of valid responses the percentages are computed against"},"winningOptionId":{"type":["string","null"],"description":"GUID of the winning option, or null on a tie / before a winner is decided"},"averageScore":{"type":"number","description":"Average rating, returned for rating questions only (emoji_rating, star_rating)"},"options":{"type":"array","description":"Per-option results, ordered by rank (winner first)","items":{"type":"object","properties":{"id":{"type":"string","description":"Option GUID"},"label":{"type":["string","null"],"description":"Option label (e.g. \"A\")"},"votes":{"type":"number","description":"Vote count; the final instant-runoff tally for ranked questions"},"percentage":{"type":"number","description":"round(votes / totalResponses * 100), matching the results page"},"rank":{"type":["number","null"],"description":"Final placement (1 = winner)"},"isWinner":{"type":"boolean","description":"Whether this option is the winner"}}}}}},"responses":{"type":"array","description":"Respondent answers for this question","items":{"type":"object","properties":{"id":{"type":"string","description":"Response ID"},"pinned":{"type":"boolean","description":"Whether the response is pinned"},"explanation":{"type":["string","null"],"description":"Written explanation from the respondent"},"translation":{"type":["string","null"],"description":"Translated explanation text"},"chosenOption":{"type":["string","null"],"description":"Label of the option chosen by the respondent"},"selectedOptions":{"type":["array","null"],"description":"Labels of options selected by the respondent for multi-select questions","items":{"type":"string"}},"score":{"type":["number","null"],"description":"Rating score (for emoji_rating, star_rating question types)"},"clicks":{"type":["array","null"],"description":"Click coordinates for click_test questions","items":{"type":"object","properties":{"number":{"type":"number","description":"Click sequence number"},"xCoord":{"type":"number","description":"X coordinate of the click"},"yCoord":{"type":"number","description":"Y coordinate of the click"}}}},"ranking":{"type":["array","null"],"description":"Respondent's ranking of options for ranked question types. Each entry pairs a rank (1 = top pick) with the option label.","items":{"type":"object","properties":{"rank":{"type":"number","description":"Rank position (1 = respondent's top pick)"},"option":{"type":["string","null"],"description":"Option label at this rank"}}}},"media":{"type":["string","null"],"description":"Media URL (for screen_recording question types)"},"mediaTranscription":{"type":["string","null"],"description":"Transcription of the recorded media"},"matchup":{"type":["object","null"],"description":"Head-to-head matchup pairing shown to the respondent","properties":{"option1":{"type":"string","description":"First option in the matchup"},"option2":{"type":"string","description":"Second option in the matchup"}}},"statements":{"type":["array","null"],"description":"Per-statement responses for likert question types. Each entry pairs a statement with the numeric value the respondent picked on the configured scale. DEV-3149.","items":{"type":"object","properties":{"id":{"type":"string","description":"GUID of the statement (the question option)"},"statement":{"type":["string","null"],"description":"Statement text"},"value":{"type":"number","description":"Numeric value the respondent picked on the Likert scale (1..N for the configured scale)"}}}},"prices":{"type":["object","null"],"description":"Van Westendorp price-sensitivity responses. Four numeric prices the respondent provided for the four standardized PSM questions.","properties":{"tooCheap":{"type":"number","description":"Price at which the product would be so cheap that quality is questionable"},"bargain":{"type":"number","description":"Price at which the product would be a bargain"},"expensive":{"type":"number","description":"Price at which the product starts to feel expensive but is still worth considering"},"tooExpensive":{"type":"number","description":"Price at which the product would be too expensive to consider"}}},"respondent":{"type":"array","description":"Demographic traits of the respondent","items":{"type":"object","properties":{"trait":{"type":"string","description":"Trait category name"},"value":{"type":"string","description":"Trait value"}}}}}}},"ai":{"type":"object","description":"AI-generated metadata such as summaries and key themes for this question","additionalProperties":{"type":"string"}}}}}}},"cost":{"type":"object","description":"Cost information for the survey","properties":{"amount":{"type":"number","description":"Survey cost in dollars"},"balance":{"type":"number","description":"Credit balance in dollars"},"currency":{"type":"string","description":"Currency code (USD)"},"canPayWithBalance":{"type":"boolean","description":"Whether balance covers the cost"},"quotedCreditsCost":{"type":"number","description":"Post-discount cost in credits, after free credits applied (1 credit = $2 USD)"},"creditsCostSubtotal":{"type":"number","description":"Pre-discount cost in credits (1 credit = $2 USD)"},"discounts":{"type":"array","description":"Credit-side discount line items, each entry is [label, amountInCredits]. Amounts are denominated in credits so they subtract directly from creditsCostSubtotal","items":{"type":"array","items":{"type":"string"}}},"discountsMoney":{"type":"array","description":"Dollar-side discount line items, each entry is [label, formattedDollarAmount] (e.g. \"$20.08\")","items":{"type":"array","items":{"type":"string"}}},"planRequired":{"type":["null","string"],"description":"Plan tier required for current survey configuration, or null if the current plan is sufficient"},"priceLines":{"type":"array","description":"The survey builder's price summary, each entry is [label, formattedDollarAmount] (e.g. [\"Head-to-Head: Text Length (+1.2x)\", \"$10.00\"]). Each amount is that line's cost for the whole sample: base price, extra options, text or video length, targeting and reporting. A $0.00 line is included free. The lines come before discounts: they add up to `creditsCostSubtotal` in dollars, and `discountsMoney` takes that down to `amount`","items":{"type":"array","items":{"type":"string"}}}}},"completionEstimate":{"type":"object","description":"Estimated completion-time bucket for the current audience","properties":{"bucket":{"type":"string","description":"Completion-time bucket: SUPER_EASY (<2h), EASY (1-2 days), MEDIUM (up to 2 weeks), HARD (may take longer), MAY_NOT_COMPLETE"},"estimatedMinutes":{"type":["null","number"],"description":"Estimated completion time in minutes, or null when unavailable"},"status":{"type":"string","description":"ready when an estimate exists, pending while computing"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number"},"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"code":{"type":"string","enum":["no_payment_method","payment_failed","authentication_required","charge_error"],"description":"Why the saved card could not cover the part of the poll the credit balance does not: no card on file, the card was declined, the card needs a confirmation step the API cannot complete, or a payment error on PickFu's side rather than the card (retry, or add credits)."}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}}}}},"/surveys/{id}/stop":{"post":{"operationId":"stopSurvey","summary":"Stop survey","tags":["Surveys"],"description":"Stops a live survey that is currently collecting responses. This is irreversible — the survey will be marked as complete and no further responses will be collected.\n\n### Prerequisites\n- Survey must be in `in-progress` status (published and not yet done)\n- Stopping a completed or draft survey returns 409 Conflict","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey ID (GUID)"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"message":{"type":"string"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys/{id}/respondents":{"post":{"operationId":"addRespondents","summary":"Add respondents","tags":["Surveys"],"description":"Adds more respondents to a completed survey by extending the sample size. The `respondentsAmount` parameter is the **new total** number of respondents (not the number to add).\n\n### Prerequisites\n- Survey must be completed (`done` status)\n- Panel-sourced surveys only\n- Under 1000 total respondents\n- Account must have sufficient credits\n\nUse `preview: true` to get a cost estimate without making changes. Credits-only — card payment is not supported via the API.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["respondentsAmount"],"properties":{"respondentsAmount":{"type":"integer","minimum":1,"maximum":1000,"description":"The new total number of respondents (not the delta). Must be greater than the current amount."},"preview":{"type":"boolean","default":false,"description":"If true, returns cost estimate without making changes."}},"additionalProperties":false}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey ID (GUID)"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"preview":{"type":"boolean"},"data":{"type":"object","properties":{"currentRespondents":{"type":"integer"},"newRespondents":{"type":"integer"},"additionalRespondents":{"type":"integer"},"amount":{"type":"number"},"balance":{"type":"number"},"currency":{"type":"string"},"canPayWithBalance":{"type":"boolean"},"id":{"type":"string"},"respondentsAmount":{"type":"integer"},"state":{"type":"string"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"402":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"},"amount":{"type":"number"},"balance":{"type":"number"},"currency":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys/{id}/followup-answers":{"get":{"operationId":"getFollowupAnswers","summary":"Get follow-up answers","tags":["Surveys"],"description":"Returns paginated historical follow-up answers for a survey. Each item is a respondent's reply to a follow-up question.\n\nUse the `response_id` query parameter to filter to follow-ups for a single original response. Items where `refunded: true` indicate the follow-up was not delivered (e.g. the respondent declined or the request expired) and the credit was refunded.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"in":"query","name":"limit","required":false,"description":"Results per page (1-100)"},{"schema":{"type":"string"},"in":"query","name":"response_id","required":false,"description":"Filter follow-up answers to a single original response by its GUID. Use the `id` field returned by GET /v1/surveys/{id}/responses."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey ID (GUID)"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","description":"List of follow-up answers","items":{"type":"object","properties":{"responseId":{"type":"string","description":"GUID of the original response (parent) this follow-up was sent for"},"questionId":{"type":["string","null"],"description":"GUID of the original question the parent response was for (multi-question surveys only)"},"question":{"type":"string","description":"The follow-up question that was sent"},"answer":{"type":["string","null"],"description":"The respondent's answer to the follow-up question"},"respondedAt":{"type":["string","null"],"description":"When the respondent answered the follow-up (ISO 8601)"},"refunded":{"type":"boolean","description":"True when the follow-up was not delivered (e.g. respondent declined or the request expired). The credit charged is refunded."}}}},"pagination":{"type":"object","description":"Pagination metadata","properties":{"page":{"type":"number","description":"Current page number"},"limit":{"type":"number","description":"Results per page"},"total":{"type":"number","description":"Total number of results"},"totalPages":{"type":"number","description":"Total number of pages"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"string"}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/tags":{"get":{"operationId":"listTags","summary":"List tags","tags":["Tags"],"description":"Returns a paginated list of tags scoped to your team/account. Use the `query` parameter to search tag names.","parameters":[{"schema":{"type":"string"},"in":"query","name":"query","required":false,"description":"Search filter for tag names"},{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"in":"query","name":"limit","required":false,"description":"Number of tags per page"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"tags":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string"}}}},"pagination":{"type":"object","properties":{"page":{"type":"number"},"limit":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"}}}}}}}}}}}},"post":{"operationId":"createTag","summary":"Create tag","tags":["Tags"],"description":"Creates a new tag. Tag names must be unique within your team/account (1-100 characters). Returns 409 Conflict if a tag with the same name already exists.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":100,"description":"Tag name"}},"additionalProperties":false}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string"}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/templates":{"get":{"operationId":"listTemplates","summary":"List product combo templates","tags":["Templates"],"description":"Lists the product combos you can create a poll from: ready-made single-question polls at a fixed price per respondent. Returns public combos plus those made for you or your team, yours first. Filter by text, access, country or option type. Call get template for one template's full constraints, audience and option slots.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20},"in":"query","name":"limit","required":false},{"schema":{"type":"string","maxLength":255},"in":"query","name":"query","required":false,"description":"Case-insensitive text matched against template names, descriptions and features"},{"schema":{"type":"string","enum":["mine","public","all"],"default":"all"},"in":"query","name":"access","required":false,"description":"`mine` lists templates made for you or your team, `public` the rest"},{"schema":{"type":"string","enum":["US","FR","GB","CH","ES","IT","JP","MX","KR","BR","DE","CA","AU","ZA","IN","PL","SE","GT"]},"in":"query","name":"country","required":false,"description":"Only templates that can run in this country"},{"schema":{"type":"string","enum":["text","image","video","url","product","image-set","audio"]},"in":"query","name":"optionType","required":false,"description":"Only templates that accept this kind of option"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["templates","pagination"],"properties":{"templates":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name","description","access","questionTypes","optionCount","pricePerResponse","url"],"properties":{"id":{"type":"string","description":"Template id, `cmb_<slug>`; pass it to get template"},"name":{"type":"string"},"description":{"type":"string"},"access":{"type":"string","enum":["mine","public"],"description":"`mine` when the template was made for you or your team"},"questionTypes":{"type":"array","items":{"type":"string","enum":["head_to_head","ranked","open_ended","star_rating","click_test"]}},"optionCount":{"type":"object","additionalProperties":false,"required":["min","max"],"properties":{"min":{"type":"integer"},"max":{"type":"integer"}}},"pricePerResponse":{"type":"number","description":"Price per respondent in US dollars at the template's default country"},"url":{"type":"string","description":"Opens the template in PickFu"}}}},"pagination":{"type":"object","additionalProperties":false,"required":["page","limit","total","totalPages","hasMore"],"properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"hasMore":{"type":"boolean"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/templates/{id}":{"get":{"operationId":"getTemplate","summary":"Get product combo template","tags":["Templates"],"description":"Returns one product combo template by its cmb_ id: the question and its blanks, the allowed question types, option types and counts, sample sizes and countries with their defaults, option slots, the preset, choosable and blocked audience, reporting traits, context help and an example poll.","parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["id","name","description","access","questionTypes","optionCount","pricePerResponse","url","originalPricePerResponse","question","constraints","optionSlots","audience","reporting","context","exampleUrl"],"properties":{"id":{"type":"string","description":"Template id, `cmb_<slug>`; pass it to get template"},"name":{"type":"string"},"description":{"type":"string"},"access":{"type":"string","enum":["mine","public"],"description":"`mine` when the template was made for you or your team"},"questionTypes":{"type":"array","items":{"type":"string","enum":["head_to_head","ranked","open_ended","star_rating","click_test"]}},"optionCount":{"type":"object","additionalProperties":false,"required":["min","max"],"properties":{"min":{"type":"integer"},"max":{"type":"integer"}}},"pricePerResponse":{"type":"number","description":"Price per respondent in US dollars at the template's default country"},"url":{"type":"string","description":"Opens the template in PickFu"},"originalPricePerResponse":{"type":["number","null"],"description":"Price per respondent before the template discount"},"question":{"type":"object","additionalProperties":false,"required":["text","blanks"],"properties":{"text":{"type":["string","null"],"description":"Question text; `{{name}}` marks a blank to fill"},"blanks":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["name","placeholder"],"properties":{"name":{"type":"string"},"placeholder":{"type":["string","null"]}}}}}},"constraints":{"type":"object","additionalProperties":false,"required":["questionTypes","optionTypes","optionCount","sampleSizes","defaultSampleSize","countries","defaultCountry"],"properties":{"questionTypes":{"type":"array","items":{"type":"string","enum":["head_to_head","ranked","open_ended","star_rating","click_test"]}},"optionTypes":{"type":"array","items":{"type":"string","enum":["text","image","video","url","product","image-set","audio"]}},"optionCount":{"type":"object","additionalProperties":false,"required":["min","max"],"properties":{"min":{"type":"integer"},"max":{"type":"integer"}}},"sampleSizes":{"type":"array","items":{"type":"string"}},"defaultSampleSize":{"type":"string"},"countries":{"type":"array","items":{"type":"string"}},"defaultCountry":{"type":"string"}}},"optionSlots":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["label","helpText","kind","presetValue"],"properties":{"label":{"type":"string"},"helpText":{"type":["string","null"]},"kind":{"type":["string","null"],"enum":["text","image","video","url","product","image-set","audio",null]},"presetValue":{"type":["string","null"]}}}},"audience":{"type":"object","additionalProperties":false,"required":["presetRequired","preset","choosable","openSlots","blocked"],"properties":{"presetRequired":{"type":"boolean","description":"Whether the survey must target every preset value"},"preset":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["trait","value"],"properties":{"trait":{"type":"object","additionalProperties":false,"required":["permalink","label"],"properties":{"permalink":{"type":"string"},"label":{"type":"string"}}},"value":{"type":"object","additionalProperties":false,"required":["permalink","label"],"properties":{"permalink":{"type":"string"},"label":{"type":"string"}}}}}},"choosable":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["permalink","label"],"properties":{"permalink":{"type":"string"},"label":{"type":"string"}}},"description":"Traits whose value the survey may choose"},"openSlots":{"type":"integer","description":"How many other traits the survey may add"},"blocked":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["permalink","label"],"properties":{"permalink":{"type":"string"},"label":{"type":"string"}}},"description":"Traits the survey may not target"}}},"reporting":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["permalink","label"],"properties":{"permalink":{"type":"string"},"label":{"type":"string"}}}},"context":{"type":["object","null"],"additionalProperties":false,"required":["help"],"properties":{"help":{"type":["string","null"]}}},"exampleUrl":{"type":["string","null"]}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"statusCode":{"type":"integer"},"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/mockup-templates":{"get":{"operationId":"listMockupTemplates","summary":"List mockup templates","tags":["Surveys"],"description":"Lists the first-party mockup templates an option of a text question can show, such as an App Store product page, with the values each takes as JSON Schema. Name one on every option of a question as `mockup: { template, values }`, beside the option's `value`, which fills the template's display field.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20},"in":"query","name":"limit","required":false},{"schema":{"type":"string","minLength":1,"maxLength":100},"in":"query","name":"lookupKey","required":false,"description":"Return only the template with this key, such as `app-store-page`; none when no template has it."}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["templates","pagination"],"properties":{"templates":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["lookupKey","name","category","displayField","valuesSchema","sampleValues","importSources"],"properties":{"lookupKey":{"type":"string","description":"The template's key; send it as an option's `mockup.template`."},"name":{"type":"string","description":"What the template shows"},"category":{"type":["string","null"],"description":"The store the template looks like, such as `apple`"},"displayField":{"type":["object","null"],"additionalProperties":false,"description":"The field an option's `value` fills, such as the app name; leave it out of `values`.","properties":{"name":{"type":"string"},"label":{"type":"string"},"maxLength":{"type":["integer","null"]}}},"valuesSchema":{"type":"object","additionalProperties":true,"description":"JSON Schema for an option's `mockup.values`: one property per field, titled with its label. Images are https URLs; PickFu copies each to its media CDN when the option is saved. A choice field is a string `enum`. A list field is an array of objects one level deep, each object holding one item's fields."},"sampleValues":{"type":"object","additionalProperties":true,"description":"Example values the template renders well"},"importSources":{"type":"array","items":{"type":"string"},"description":"Stores whose listings can fill the template: send `mockup.import: { source, id }` with one of these as `source` instead of typing every value. Empty when it is filled by hand only."}}}},"pagination":{"type":"object","additionalProperties":false,"required":["page","limit","total","totalPages","hasMore"],"properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"hasMore":{"type":"boolean"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/mockup-backdrops":{"get":{"operationId":"listMockupBackdrops","summary":"List mockup backdrops","tags":["Surveys"],"description":"Lists the shelf photos a shelf mockup template can draw products onto: PickFu's gallery and your team's own, each with its frozen image and its shelf lines. Name one on every option of a question as the template's `backdrop` value; every option of a question uses the same one.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20},"in":"query","name":"limit","required":false}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["backdrops","pagination"],"properties":{"backdrops":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["id","name","scope","imageUrl","width","height","shelves","createdAt"],"properties":{"id":{"type":"string","description":"The backdrop's id; send it as a shelf template's `mockup.values.backdrop`."},"name":{"type":["string","null"]},"scope":{"type":"string","enum":["gallery","team"],"description":"`gallery` for PickFu's backdrops, which every team can use; `team` for your team's own."},"imageUrl":{"type":"string","description":"The photo, frozen on PickFu's media CDN"},"width":{"type":"integer","description":"Image pixels"},"height":{"type":"integer","description":"Image pixels"},"shelves":{"type":"array","minItems":1,"maxItems":4,"description":"Each shelf's front edge, top to bottom, as fractions of the image: `y` down from the top, `left` and `right` across.","items":{"type":"object","additionalProperties":false,"required":["y","left","right"],"properties":{"y":{"type":"number","minimum":0,"maximum":1},"left":{"type":"number","minimum":0,"maximum":1},"right":{"type":"number","minimum":0,"maximum":1}}}},"createdAt":{"type":"string","format":"date-time"}}}},"pagination":{"type":"object","additionalProperties":false,"required":["page","limit","total","totalPages","hasMore"],"properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"},"hasMore":{"type":"boolean"}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/projects":{"get":{"operationId":"listProjects","summary":"List projects","tags":["Projects"],"description":"Returns a paginated list of projects scoped to your team/account. Use query parameters to filter by bookmarked or archived status.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"in":"query","name":"limit","required":false,"description":"Number of projects per page"},{"schema":{"type":"boolean"},"in":"query","name":"bookmarked","required":false,"description":"Filter to bookmarked projects only"},{"schema":{"type":"boolean"},"in":"query","name":"archived","required":false,"description":"Filter to archived projects only"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":["string","null"],"description":"Project name"},"description":{"type":["string","null"],"description":"Project description"},"goal":{"type":["string","null"],"description":"Project goal"},"archived":{"type":"boolean","description":"Whether the project is archived"},"bookmarked":{"type":"boolean","description":"Whether the project is bookmarked"},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"},"url":{"type":"string","description":"Direct URL to the project page"},"user":{"type":["string","null"],"description":"Creator email/login"},"surveyCount":{"type":"integer","description":"Number of surveys in the project"}}}},"pagination":{"type":"object","description":"Pagination metadata","properties":{"page":{"type":"number","description":"Current page number"},"limit":{"type":"number","description":"Results per page"},"total":{"type":"number","description":"Total number of results"},"totalPages":{"type":"number","description":"Total number of pages"}}}}}}}}}}}},"post":{"operationId":"createProject","summary":"Create project","tags":["Projects"],"description":"Creates a new project. Projects help organize related surveys. Both name and description are optional — a default name is used if omitted.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":255,"description":"Project name"},"description":{"type":"string","maxLength":5000,"description":"Project description"}}}}}},"responses":{"201":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":["string","null"],"description":"Project name"},"description":{"type":["string","null"],"description":"Project description"},"goal":{"type":["string","null"],"description":"Project goal"},"archived":{"type":"boolean","description":"Whether the project is archived"},"bookmarked":{"type":"boolean","description":"Whether the project is bookmarked"},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"},"url":{"type":"string","description":"Direct URL to the project page"},"user":{"type":["string","null"],"description":"Creator email/login"},"surveyCount":{"type":"integer","description":"Number of surveys in the project"},"surveys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Survey GUID"},"name":{"type":"string","description":"Survey name"},"url":{"type":"string","description":"URL to view survey results"},"status":{"type":"string","description":"Survey status: completed, in-progress, unpublished, or archived"},"type":{"type":"string","description":"Primary question type"},"countryCode":{"type":["string","null"],"description":"Two-letter country code"},"sampleSize":{"type":["number","null"],"description":"Number of respondents requested"},"numResponses":{"type":"number","description":"Number of responses collected"},"createdAt":{"type":["string","null"],"description":"Creation timestamp (ISO 8601)"},"publishedAt":{"type":["string","null"],"description":"Publication timestamp (ISO 8601)"},"completedAt":{"type":["string","null"],"description":"Completion timestamp (ISO 8601)"},"creatorName":{"type":["string","null"],"description":"Name of the team member who created the survey"},"targeting":{"type":"array","items":{"type":"string"},"description":"Targeting trait permalinks"},"tags":{"type":"array","description":"Tags associated with the survey","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string","description":"Tag name"}}}},"projects":{"type":"array","description":"Projects the survey belongs to","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":"string","description":"Project name"}}}},"externalId":{"type":"string","description":"Optional opaque correlation key. Omitted when unset. Case-sensitive and byte-exact."},"template":{"type":["object","null"],"description":"The template the survey was made from, or null. GET the survey for its constraints.","properties":{"id":{"type":["string","null"],"description":"Template id (cmb_...), or null when the template can no longer be addressed"},"name":{"type":"string"}}},"elements":{"type":"array","description":"Questions in this survey (summary view)","items":{"type":"object","properties":{"id":{"type":"string","description":"Question GUID"},"question":{"type":["string","null"],"description":"Question text"},"subtype":{"type":"string","description":"Question subtype"},"variant":{"type":["string","null"],"description":"Question variant"},"position":{"type":"number","description":"Display position"}}}}}},"description":"Surveys within the project, same shape as GET /v1/surveys"}}}}}}}}}}},"/projects/{id}":{"get":{"operationId":"getProject","summary":"Get project","tags":["Projects"],"description":"Retrieves a project by its unique GUID, including lightweight survey summaries.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project GUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":["string","null"],"description":"Project name"},"description":{"type":["string","null"],"description":"Project description"},"goal":{"type":["string","null"],"description":"Project goal"},"archived":{"type":"boolean","description":"Whether the project is archived"},"bookmarked":{"type":"boolean","description":"Whether the project is bookmarked"},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"},"url":{"type":"string","description":"Direct URL to the project page"},"user":{"type":["string","null"],"description":"Creator email/login"},"surveyCount":{"type":"integer","description":"Number of surveys in the project"},"surveys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Survey GUID"},"name":{"type":"string","description":"Survey name"},"url":{"type":"string","description":"URL to view survey results"},"status":{"type":"string","description":"Survey status: completed, in-progress, unpublished, or archived"},"type":{"type":"string","description":"Primary question type"},"countryCode":{"type":["string","null"],"description":"Two-letter country code"},"sampleSize":{"type":["number","null"],"description":"Number of respondents requested"},"numResponses":{"type":"number","description":"Number of responses collected"},"createdAt":{"type":["string","null"],"description":"Creation timestamp (ISO 8601)"},"publishedAt":{"type":["string","null"],"description":"Publication timestamp (ISO 8601)"},"completedAt":{"type":["string","null"],"description":"Completion timestamp (ISO 8601)"},"creatorName":{"type":["string","null"],"description":"Name of the team member who created the survey"},"targeting":{"type":"array","items":{"type":"string"},"description":"Targeting trait permalinks"},"tags":{"type":"array","description":"Tags associated with the survey","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string","description":"Tag name"}}}},"projects":{"type":"array","description":"Projects the survey belongs to","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":"string","description":"Project name"}}}},"externalId":{"type":"string","description":"Optional opaque correlation key. Omitted when unset. Case-sensitive and byte-exact."},"template":{"type":["object","null"],"description":"The template the survey was made from, or null. GET the survey for its constraints.","properties":{"id":{"type":["string","null"],"description":"Template id (cmb_...), or null when the template can no longer be addressed"},"name":{"type":"string"}}},"elements":{"type":"array","description":"Questions in this survey (summary view)","items":{"type":"object","properties":{"id":{"type":"string","description":"Question GUID"},"question":{"type":["string","null"],"description":"Question text"},"subtype":{"type":"string","description":"Question subtype"},"variant":{"type":["string","null"],"description":"Question variant"},"position":{"type":"number","description":"Display position"}}}}}},"description":"Surveys within the project, same shape as GET /v1/surveys"}}}}}}}}}},"patch":{"operationId":"updateProject","summary":"Update project","tags":["Projects"],"description":"Updates a project by its GUID. You can update the name, description, goal, bookmark status, and archive status. Only provided fields are updated.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string","maxLength":255,"description":"Project name"},"description":{"type":"string","maxLength":5000,"description":"Project description"},"goal":{"type":"string","maxLength":5000,"description":"Project goal"},"bookmark":{"type":"boolean","description":"Set to true to bookmark, false to unbookmark"},"archive":{"type":"boolean","description":"Set to true to archive, false to unarchive"}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Project GUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":["string","null"],"description":"Project name"},"description":{"type":["string","null"],"description":"Project description"},"goal":{"type":["string","null"],"description":"Project goal"},"archived":{"type":"boolean","description":"Whether the project is archived"},"bookmarked":{"type":"boolean","description":"Whether the project is bookmarked"},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"},"url":{"type":"string","description":"Direct URL to the project page"},"user":{"type":["string","null"],"description":"Creator email/login"},"surveyCount":{"type":"integer","description":"Number of surveys in the project"},"surveys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"Survey GUID"},"name":{"type":"string","description":"Survey name"},"url":{"type":"string","description":"URL to view survey results"},"status":{"type":"string","description":"Survey status: completed, in-progress, unpublished, or archived"},"type":{"type":"string","description":"Primary question type"},"countryCode":{"type":["string","null"],"description":"Two-letter country code"},"sampleSize":{"type":["number","null"],"description":"Number of respondents requested"},"numResponses":{"type":"number","description":"Number of responses collected"},"createdAt":{"type":["string","null"],"description":"Creation timestamp (ISO 8601)"},"publishedAt":{"type":["string","null"],"description":"Publication timestamp (ISO 8601)"},"completedAt":{"type":["string","null"],"description":"Completion timestamp (ISO 8601)"},"creatorName":{"type":["string","null"],"description":"Name of the team member who created the survey"},"targeting":{"type":"array","items":{"type":"string"},"description":"Targeting trait permalinks"},"tags":{"type":"array","description":"Tags associated with the survey","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Opaque tag identifier (tag_<32-hex>)"},"name":{"type":"string","description":"Tag name"}}}},"projects":{"type":"array","description":"Projects the survey belongs to","items":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string","description":"Project GUID"},"name":{"type":"string","description":"Project name"}}}},"externalId":{"type":"string","description":"Optional opaque correlation key. Omitted when unset. Case-sensitive and byte-exact."},"template":{"type":["object","null"],"description":"The template the survey was made from, or null. GET the survey for its constraints.","properties":{"id":{"type":["string","null"],"description":"Template id (cmb_...), or null when the template can no longer be addressed"},"name":{"type":"string"}}},"elements":{"type":"array","description":"Questions in this survey (summary view)","items":{"type":"object","properties":{"id":{"type":"string","description":"Question GUID"},"question":{"type":["string","null"],"description":"Question text"},"subtype":{"type":"string","description":"Question subtype"},"variant":{"type":["string","null"],"description":"Question variant"},"position":{"type":"number","description":"Display position"}}}}}},"description":"Surveys within the project, same shape as GET /v1/surveys"}}}}}}}}}}},"/playbooks":{"get":{"operationId":"listPlaybooks","summary":"List playbooks","tags":["Playbooks"],"description":"Returns a paginated list of available PickFu playbooks (step-by-step research guides). Each playbook is a structured sequence of polls designed for a specific research goal. Optionally filter by industry.","parameters":[{"schema":{"type":"integer","minimum":1,"default":1},"in":"query","name":"page","required":false,"description":"Page number"},{"schema":{"type":"integer","minimum":1,"maximum":50,"default":20},"in":"query","name":"limit","required":false,"description":"Number of playbooks per page"},{"schema":{"type":"string"},"in":"query","name":"industry","required":false,"description":"Filter playbooks by industry (e.g. \"ecommerce\" or \"E-commerce\", \"mobile apps\")"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"playbooks":{"type":"array","items":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"Unique playbook identifier (GUID)"},"name":{"type":"string","description":"Playbook name"},"description":{"type":["string","null"],"description":"Short description of the playbook"},"industry":{"type":["string","null"],"description":"Industry category"},"poll_count":{"type":"integer","description":"Number of surveys in this playbook"},"duration":{"type":["string","null"],"description":"Estimated completion time (e.g. \"2-3 days\")"},"icon":{"type":["string","null"],"description":"Icon identifier or emoji"},"icon_lucide":{"type":["string","null"],"description":"Lucide icon name for the UI"},"url":{"type":["string","null"],"description":"Direct URL to view this playbook on PickFu. Always null — no /playbooks/<slug> route exists"}}}},"pagination":{"type":"object","properties":{"total":{"type":"integer","description":"Total number of matching playbooks"},"page":{"type":"integer","description":"Current page number"},"limit":{"type":"integer","description":"Number of playbooks per page"},"totalPages":{"type":"integer","description":"Total number of pages"}}}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}}}}},"/playbooks/{slug}":{"get":{"operationId":"getPlaybook","summary":"Get playbook","tags":["Playbooks"],"description":"Retrieves a playbook by its slug. Returns the full structured playbook including goal, step-by-step instructions with poll creation URLs, and metadata. The steps_markdown field contains formatted instructions with embedded poll creation links.","parameters":[{"schema":{"type":"string"},"in":"path","name":"slug","required":true,"description":"Playbook slug (GUID)"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":["string","null"],"description":"Unique playbook identifier (GUID)"},"name":{"type":"string","description":"Playbook name"},"description":{"type":["string","null"],"description":"Short description of the playbook"},"industry":{"type":["string","null"],"description":"Industry category"},"poll_count":{"type":"integer","description":"Number of surveys in this playbook"},"duration":{"type":["string","null"],"description":"Estimated completion time (e.g. \"2-3 days\")"},"icon":{"type":["string","null"],"description":"Icon identifier or emoji"},"icon_lucide":{"type":["string","null"],"description":"Lucide icon name for the UI"},"url":{"type":["string","null"],"description":"Direct URL to view this playbook on PickFu. Always null — no /playbooks/<slug> route exists"},"goal":{"type":["string","null"],"description":"The research goal this playbook helps achieve"},"steps_markdown":{"type":["string","null"],"description":"Formatted instructions with embedded survey creation links"},"project_name_template":{"type":["string","null"],"description":"Template for the project name when starting this playbook"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}}}}},"/surveys/{id}/questions/{questionId}/heatmap":{"get":{"operationId":"getHeatmap","summary":"Get click-test heatmap","tags":["Surveys"],"description":"Returns a permanent CDN URL to a rendered heatmap PNG image for a click-test question. The heatmap composites all click data onto the original question image. Results are cached in Cloudinary — subsequent requests for the same click data return instantly. `regions` carries the click regions saved for the current image, with first-click counts from the same clicks, or null when the image has none.\n\n### Prerequisites\n- Question must be a `click-test` type\n- Question must have at least one click response\n- Returns 422 for non-click-test questions or questions with zero clicks","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"},{"schema":{"type":"string"},"in":"path","name":"questionId","required":true,"description":"Question GUID within the survey"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"heatmapUrl":{"type":"string","description":"Signed URL to the rendered heatmap PNG image"},"regions":{"type":["object","null"],"properties":{"imagePublicId":{"type":"string","description":"The question's current image"},"revision":{"type":"integer","description":"The current revision for that image; 0 when none"},"regions":{"type":"array","description":"Boxes as fractions of the image from its top left; empty when none","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":["string","null"]},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"}}}},"source":{"type":["string","null"],"description":"`template` (seeded from a mockup template), `detected` or `drawn`; null when none"},"counts":{"type":"object","properties":{"mode":{"type":"string","enum":["first","all"]},"respondents":{"type":"integer","description":"Respondents with at least one click, after filters"},"clicks":{"type":"integer","description":"Clicks counted; equals `respondents` in `first` mode"},"regions":{"type":"array","description":"One tally per region, in stored order","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":["string","null"]},"count":{"type":"integer"},"share":{"type":"integer","description":"Whole percent of respondents (`first`) or clicks (`all`); the regions and `outside` sum to 100, or are all 0 with nothing counted"},"ci95":{"type":["object","null"],"description":"Wilson 95% interval in percent, one decimal; null in `all` mode or with no respondents","properties":{"low":{"type":"number"},"high":{"type":"number"}}}}}},"outside":{"type":"object","description":"Clicks outside every region","properties":{"count":{"type":"integer"},"share":{"type":"integer","description":"Whole percent of respondents (`first`) or clicks (`all`); the regions and `outside` sum to 100, or are all 0 with nothing counted"},"ci95":{"type":["object","null"],"description":"Wilson 95% interval in percent, one decimal; null in `all` mode or with no respondents","properties":{"low":{"type":"number"},"high":{"type":"number"}}}}},"noClearWinner":{"type":["boolean","null"],"description":"A heuristic, not a significance test: true when the two most-clicked regions' intervals overlap (a tie always does), so no region should be called the winner yet. Null outside `first` mode, with fewer than two regions, or with no respondents."}}}},"description":"The question's click regions for its current image, counted from the same clicks the heatmap draws (first clicks, unfiltered); null when the image has none. GET /surveys/{id}/questions/{questionId}/click-regions describes the shape."}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"500":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys/{id}/questions/{questionId}/click-regions":{"get":{"operationId":"getClickRegions","summary":"Get click-test regions and counts","tags":["Surveys"],"description":"Returns the named boxes (regions) drawn on a click-test question's current image, and how respondents' clicks fall in them.\n\n### Counting\n- `mode=first` (default) counts each respondent's first click; `mode=all` counts every click.\n- Boxes are half-open: a click on an edge two regions share counts in the right or lower one. A box reaching the image's right or bottom edge includes it.\n- Each region and `outside` carry `count`, a whole-percent `share` (summing to 100) and, in `first` mode, a Wilson 95% interval `ci95` in percent.\n- `noClearWinner` is a heuristic, not a significance test: true when the two most-clicked regions' intervals overlap, so no region should be called the winner yet.\n\n### Filters\n- `traits`: comma-separated trait value permalinks, as on the responses endpoint.\n- `startX`, `startY`, `w`, `h`: a drag box as fractions of the image (all four or none). Only respondents with any click inside it are counted.\n\nRegions belong to an image: after the question's image is replaced, `revision` is 0 and `regions` is empty until regions are saved for the new image. A click test without clicks answers zero counts. Returns 422 for a question that is not a click test or has no image.","parameters":[{"schema":{"type":"string","enum":["first","all"]},"in":"query","name":"mode","required":false,"description":"`first` (default) counts each respondent's first click; `all` counts every click."},{"schema":{"type":"number","minimum":0,"maximum":1},"in":"query","name":"startX","required":false,"description":"Drag-box filter, left edge as a fraction. Send startX, startY, w and h together: only respondents with any click inside the box (edges included) are counted, by their own first click in `first` mode."},{"schema":{"type":"number","minimum":0,"maximum":1},"in":"query","name":"startY","required":false,"description":"Drag-box filter, top edge as a fraction"},{"schema":{"type":"number","minimum":-1,"maximum":1},"in":"query","name":"w","required":false,"description":"Drag-box filter, width; negative for a box dragged left"},{"schema":{"type":"number","minimum":-1,"maximum":1},"in":"query","name":"h","required":false,"description":"Drag-box filter, height; negative for a box dragged up"},{"schema":{"type":"string"},"in":"query","name":"traits","required":false,"description":"Comma-separated trait value permalinks, as on GET /surveys/{id}/responses: only matching respondents are counted. Traits outside the poll's trait set are refused with 400."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"},{"schema":{"type":"string"},"in":"path","name":"questionId","required":true,"description":"Question GUID within the survey; the survey GUID for a single-question poll"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"imagePublicId":{"type":"string","description":"The question's current image"},"revision":{"type":"integer","description":"The current revision for that image; 0 when none"},"regions":{"type":"array","description":"Boxes as fractions of the image from its top left; empty when none","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":["string","null"]},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"}}}},"source":{"type":["string","null"],"description":"`template` (seeded from a mockup template), `detected` or `drawn`; null when none"},"counts":{"type":"object","properties":{"mode":{"type":"string","enum":["first","all"]},"respondents":{"type":"integer","description":"Respondents with at least one click, after filters"},"clicks":{"type":"integer","description":"Clicks counted; equals `respondents` in `first` mode"},"regions":{"type":"array","description":"One tally per region, in stored order","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":["string","null"]},"count":{"type":"integer"},"share":{"type":"integer","description":"Whole percent of respondents (`first`) or clicks (`all`); the regions and `outside` sum to 100, or are all 0 with nothing counted"},"ci95":{"type":["object","null"],"description":"Wilson 95% interval in percent, one decimal; null in `all` mode or with no respondents","properties":{"low":{"type":"number"},"high":{"type":"number"}}}}}},"outside":{"type":"object","description":"Clicks outside every region","properties":{"count":{"type":"integer"},"share":{"type":"integer","description":"Whole percent of respondents (`first`) or clicks (`all`); the regions and `outside` sum to 100, or are all 0 with nothing counted"},"ci95":{"type":["object","null"],"description":"Wilson 95% interval in percent, one decimal; null in `all` mode or with no respondents","properties":{"low":{"type":"number"},"high":{"type":"number"}}}}},"noClearWinner":{"type":["boolean","null"],"description":"A heuristic, not a significance test: true when the two most-clicked regions' intervals overlap (a tie always does), so no region should be called the winner yet. Null outside `first` mode, with fewer than two regions, or with no respondents."}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}}}},"put":{"operationId":"saveClickRegions","summary":"Save click-test regions","tags":["Surveys"],"description":"Saves the whole set of regions for a click-test question's current image as a new revision, and returns it with unfiltered first-click counts. Allowed on draft, live and completed surveys for users who can edit the survey; requires an API key with write permission.\n\nSend the `imagePublicId` and `revision` the GET returned (revision 0 when there is none). Regions are fractions of the image (`x`, `y`, `w`, `h` in 0 to 1), at most 50, with unique keys; they may share an edge but not overlap. Saving regions equal to the current ones creates no revision.\n\n### Errors\n- 409 `CLICK_REGIONS_IMAGE_CHANGED`: the question's image was replaced since the GET. Reload and draw the regions again.\n- 409 `CLICK_REGIONS_STALE_REVISION`: someone saved since the GET, or a concurrent save won. Reload and reapply.\n- Both carry `current: { imagePublicId, revision }`.\n- 422 `CLICK_REGIONS_INVALID`: the message names each region to fix (overlap, out of bounds, zero size, duplicate key).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["imagePublicId","revision","regions"],"additionalProperties":false,"properties":{"imagePublicId":{"type":"string","minLength":1,"description":"The image the regions were drawn on: `imagePublicId` from the GET. A save for any other image is refused with 409 `CLICK_REGIONS_IMAGE_CHANGED`."},"revision":{"type":"integer","minimum":0,"description":"The revision being edited: `revision` from the GET, 0 when there is none yet. A save against an older revision is refused with 409 `CLICK_REGIONS_STALE_REVISION`."},"regions":{"type":"array","maxItems":50,"items":{"type":"object","required":["key","x","y","w","h"],"additionalProperties":false,"properties":{"key":{"type":"string","minLength":1,"maxLength":100,"description":"Unique within the set, such as `slot-3`"},"label":{"type":["string","null"],"maxLength":200,"description":"Shown to people reading results; null or omitted for none"},"x":{"type":"number","minimum":0,"maximum":1,"description":"Left edge, as a fraction of the image width"},"y":{"type":"number","minimum":0,"maximum":1,"description":"Top edge, as a fraction of the image height"},"w":{"type":"number","minimum":0,"maximum":1,"description":"Width, as a fraction of the image width; above 0"},"h":{"type":"number","minimum":0,"maximum":1,"description":"Height, as a fraction of the image height; above 0"}}},"description":"The whole set, replacing the current one. Boxes may share an edge but not overlap, and must lie within the image."}}}}}},"parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"},{"schema":{"type":"string"},"in":"path","name":"questionId","required":true,"description":"Question GUID within the survey; the survey GUID for a single-question poll"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"imagePublicId":{"type":"string","description":"The question's current image"},"revision":{"type":"integer","description":"The current revision for that image; 0 when none"},"regions":{"type":"array","description":"Boxes as fractions of the image from its top left; empty when none","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":["string","null"]},"x":{"type":"number"},"y":{"type":"number"},"w":{"type":"number"},"h":{"type":"number"}}}},"source":{"type":["string","null"],"description":"`template` (seeded from a mockup template), `detected` or `drawn`; null when none"},"counts":{"type":"object","properties":{"mode":{"type":"string","enum":["first","all"]},"respondents":{"type":"integer","description":"Respondents with at least one click, after filters"},"clicks":{"type":"integer","description":"Clicks counted; equals `respondents` in `first` mode"},"regions":{"type":"array","description":"One tally per region, in stored order","items":{"type":"object","properties":{"key":{"type":"string"},"label":{"type":["string","null"]},"count":{"type":"integer"},"share":{"type":"integer","description":"Whole percent of respondents (`first`) or clicks (`all`); the regions and `outside` sum to 100, or are all 0 with nothing counted"},"ci95":{"type":["object","null"],"description":"Wilson 95% interval in percent, one decimal; null in `all` mode or with no respondents","properties":{"low":{"type":"number"},"high":{"type":"number"}}}}}},"outside":{"type":"object","description":"Clicks outside every region","properties":{"count":{"type":"integer"},"share":{"type":"integer","description":"Whole percent of respondents (`first`) or clicks (`all`); the regions and `outside` sum to 100, or are all 0 with nothing counted"},"ci95":{"type":["object","null"],"description":"Wilson 95% interval in percent, one decimal; null in `all` mode or with no respondents","properties":{"low":{"type":"number"},"high":{"type":"number"}}}}},"noClearWinner":{"type":["boolean","null"],"description":"A heuristic, not a significance test: true when the two most-clicked regions' intervals overlap (a tie always does), so no region should be called the winner yet. Null outside `first` mode, with fewer than two regions, or with no respondents."}}}}}}}},"400":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["CLICK_REGIONS_IMAGE_CHANGED","CLICK_REGIONS_STALE_REVISION"]},"message":{"type":"string"},"current":{"type":"object","description":"The image and revision to reload","properties":{"imagePublicId":{"type":"string"},"revision":{"type":"integer"}}}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys/{id}/questions/{questionId}/van-westendorp":{"get":{"operationId":"getVanWestendorpResults","summary":"Get Van Westendorp aggregate results","tags":["Surveys"],"description":"Returns the aggregated Van Westendorp Price Sensitivity Meter analysis for a van_westendorp question: the four cumulative respondent-price curves (Too cheap / Bargain / Expensive / Too expensive), the four named price intersections (PMC, OPP, IPP, PME), per-bucket histograms, and a confidence signal. Useful when the caller wants the analyzed price points without parsing every respondent's raw quartet themselves.\n\n### Prerequisites\n- Question must be a `van_westendorp` type\n- Question must have at least one approved response\n- Returns 422 for non-VW questions or questions with no approved responses yet","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"},{"schema":{"type":"string"},"in":"path","name":"questionId","required":true,"description":"Question GUID within the survey (must be a van_westendorp question)"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"currency":{"type":"string","description":"ISO 4217 currency derived from the survey target country"},"priceRange":{"type":"object","description":"Price-axis bounds derived from respondent answers (used by curves + histograms).","properties":{"min":{"type":"number"},"max":{"type":"number"},"step":{"type":"number"}}},"curves":{"type":"object","description":"Cumulative respondent percentages at each price step, one entry per axis price (indices align across all four curves and with priceRange.min..max stepped by priceRange.step).","properties":{"tooCheap":{"type":"array","items":{"type":"number"}},"bargain":{"type":"array","items":{"type":"number"}},"expensive":{"type":"array","items":{"type":"number"}},"tooExpensive":{"type":"array","items":{"type":"number"}}}},"intersections":{"type":"object","description":"Named Van Westendorp price points. Ordering invariant: PMC ≤ OPP ≤ IPP ≤ PME.","properties":{"PMC":{"type":"object","properties":{"price":{"type":"number"},"pct":{"type":"number"}},"description":"Point of Marginal Cheapness — tooCheap × expensive intersection (lower bound of acceptable range)"},"OPP":{"type":"object","properties":{"price":{"type":"number"},"pct":{"type":"number"}},"description":"Optimal Price Point — tooCheap × tooExpensive intersection"},"IPP":{"type":"object","properties":{"price":{"type":"number"},"pct":{"type":"number"}},"description":"Indifference Price Point — bargain × expensive intersection (typical market price)"},"PME":{"type":"object","properties":{"price":{"type":"number"},"pct":{"type":"number"}},"description":"Point of Marginal Expensiveness — bargain × tooExpensive intersection (upper bound of acceptable range)"}}},"nms":{"type":"array","items":{"type":"number"},"description":"Percentage of respondents for whom each price is within their acceptable range — neither too cheap nor too expensive — computed as max(0, 100 − tooCheap − tooExpensive) at each price step (indices align with the curves). Not the full Newton-Miller-Smith purchase-probability model, which requires extra trial questions this question type does not collect."},"histograms":{"type":"object","description":"Per-bucket distributions of respondent prices for each of the four PSM questions.","properties":{"tooCheap":{"type":"array","items":{"type":"object","properties":{"price":{"type":"number"},"count":{"type":"number"}}}},"bargain":{"type":"array","items":{"type":"object","properties":{"price":{"type":"number"},"count":{"type":"number"}}}},"expensive":{"type":"array","items":{"type":"object","properties":{"price":{"type":"number"},"count":{"type":"number"}}}},"tooExpensive":{"type":"array","items":{"type":"object","properties":{"price":{"type":"number"},"count":{"type":"number"}}}}}},"confidence":{"type":"string","enum":["high","medium","low"],"description":"Quality signal based on respondent count and data spread"}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"422":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys/{id}/exports":{"get":{"operationId":"getSurveyExports","summary":"List survey exports","tags":["Surveys"],"description":"Returns metadata and download URLs for all export formats associated with a survey: CSV results, PDF reports, and PNG screenshots.\n\nThe `csv` block points to the PickFu API CSV proxy endpoint and is only available once the survey has been published and completed. PDF and PNG entries are returned for each rendered language.\n\nRate limit: 30 requests per minute per caller.","parameters":[{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"}],"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"csv":{"type":"object","properties":{"available":{"type":"boolean","description":"Whether the CSV export is available (the survey must be published and complete)"},"version":{"type":["string","null"],"description":"CSV export version. v2 is the default and most recent format."},"url":{"type":["string","null"],"description":"Authenticated URL to download the CSV results bytes via the PickFu API."}}},"pdf":{"type":"array","description":"PDF report exports. Each entry corresponds to one rendered language.","items":{"type":"object","properties":{"url":{"type":"string","description":"Direct CDN URL to the PDF file"},"language":{"type":"string","description":"Language code (ISO 639-1) for this PDF"}}}},"png":{"type":"array","description":"PNG screenshot exports of the results page. Each entry is one rendered language and may be a preview thumbnail.","items":{"type":"object","properties":{"url":{"type":"string","description":"Direct CDN URL to the PNG file"},"language":{"type":"string","description":"Language code (ISO 639-1) for this PNG"},"isPreview":{"type":"boolean","description":"True when the PNG is a preview thumbnail rather than a full-resolution screenshot"}}}}}}}}}}},"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/surveys/{id}/exports/csv":{"get":{"operationId":"getSurveyExportCsv","summary":"Download survey CSV export","tags":["Surveys"],"description":"Streams the CSV export of survey responses as `text/csv`. Use the `version` query parameter to switch between the v1 and v2 CSV formats — v2 is the default.\n\nAuthentication: standard Bearer token, OR a short-lived signed token via the `t` query parameter (issued by `/v1/surveys/{id}/exports`).\n\n### Prerequisites\n- Survey must be published and completed\n- Returns 409 Conflict if the survey is not yet ready for export\n- Returns 502 Bad Gateway if the upstream export service is unavailable\n\nRate limit: 10 requests per minute per caller.","parameters":[{"schema":{"type":"string","enum":["v1","v2"]},"in":"query","name":"version","required":false,"description":"CSV export format version. Defaults to v2 (long-form) if omitted."},{"schema":{"type":"string","maxLength":512},"in":"query","name":"t","required":false,"description":"Optional short-lived signed token. When present and valid, the request is authenticated by the token instead of the Authorization header. Tokens are issued by the `/v1/surveys/{id}/exports` metadata endpoint."},{"schema":{"type":"string"},"in":"path","name":"id","required":true,"description":"Survey GUID"}],"responses":{"401":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"403":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"404":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"409":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}},"502":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string"},"message":{"type":"string"}}}}}}}}},"/organization":{"post":{"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["organizationId"],"properties":{"organizationId":{"type":"string","minLength":1}},"additionalProperties":false}}}},"responses":{"200":{"description":"Default Response"}}}},"/api-keys":{"post":{"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":255},"permissions":{"type":"array","items":{"type":"string","enum":["read","write","spend"]},"minItems":1,"uniqueItems":true}},"additionalProperties":false}}}},"responses":{"200":{"description":"Default Response"}}},"get":{"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100},"in":"query","name":"limit","required":false},{"schema":{"type":"string"},"in":"query","name":"before","required":false},{"schema":{"type":"string"},"in":"query","name":"after","required":false}],"responses":{"200":{"description":"Default Response"}}}},"/api-keys/{id}":{"delete":{"parameters":[{"schema":{"type":"string","minLength":1},"in":"path","name":"id","required":true}],"responses":{"200":{"description":"Default Response"}}}},"/media/generate":{"post":{"operationId":"generateMedia","summary":"Generate media","tags":["Media"],"description":"Generates an image from a text prompt using AI. The generated image is uploaded to the PickFu CDN and a permanent URL is returned.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["prompt"],"additionalProperties":false,"properties":{"prompt":{"type":"string","minLength":1,"maxLength":10000,"description":"Text prompt describing the image to generate"},"type":{"type":"string","enum":["image"],"default":"image","description":"Media type to generate (default: image)"},"aspectRatio":{"type":"string","enum":["1:1","2:3","3:2","3:4","4:3","4:5","5:4","9:16","16:9","21:9"],"default":"1:1","description":"Aspect ratio of the generated image (default: 1:1)"},"imageUrls":{"type":"array","maxItems":3,"items":{"type":"string","pattern":"^(https?:\\/\\/|data:)","maxLength":8388608},"description":"Up to 3 reference image URLs (https://… or data: URIs) the model can see while generating. Useful for preserving product appearance across variants."}}}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"url":{"type":"string","description":"CDN URL of the generated image"},"model":{"type":"string","description":"Model used for generation (echoed for traceability)"},"aspectRatio":{"type":"string","description":"Aspect ratio of the generated image"},"prompt":{"type":"string","description":"The prompt used for generation"}}}}}}}},"402":{"description":"The team's platform credit balance cannot cover this action (only when platform credits are enforced)","content":{"application/json":{"schema":{"type":"object","description":"The team's platform credit balance cannot cover this action (only when platform credits are enforced)","properties":{"error":{"type":"string"},"code":{"type":"string","enum":["insufficient_platform_credits"]},"message":{"type":"string"},"required":{"type":"integer","description":"Platform credits the action costs"},"available":{"type":"integer","description":"Platform credits in the team's balance"},"shortfall":{"type":"integer","description":"required minus available"}}}}}}}}},"/media/upload":{"post":{"operationId":"uploadMedia","summary":"Upload media","tags":["Media"],"description":"Uploads an image or video to the PickFu CDN. Accepts either a URL (fetched and re-hosted) or base64-encoded data (max 20MB decoded).\n\nYouTube, Vimeo, and Wistia URLs are returned as-is since PickFu embeds them natively.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"url":{"type":"string","format":"uri","description":"HTTPS URL of the media to upload. Mutually exclusive with data."},"data":{"type":"string","description":"Base64-encoded media content. Mutually exclusive with url. Max 20MB."},"filename":{"type":"string","maxLength":255,"description":"Optional filename hint for the CDN public ID"},"resourceType":{"type":"string","enum":["image","video"],"description":"Resource type. Auto-detected from URL/content if omitted."}},"oneOf":[{"required":["url"]},{"required":["data"]}]}}}},"responses":{"200":{"description":"Default Response","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"data":{"type":"object","properties":{"url":{"type":"string","description":"CDN URL of the uploaded media"},"resourceType":{"type":"string","description":"Detected or specified resource type"},"embedded":{"type":"boolean","description":"True if the URL is an embeddable video platform (YouTube/Vimeo/Wistia) returned as-is"}}}}}}}}}}}},"servers":[{"url":"https://api.pickfu.com/v1","description":"Production"},{"url":"https://api.pickfu-sandbox.com/v1","description":"Sandbox"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Surveys","description":"Create, retrieve, update, and publish surveys. Surveys are the core resource — each contains one or more questions with answer options."},{"name":"Responses","description":"Retrieve individual responses (answers) for a survey, with pagination and per-question filtering."},{"name":"Tags","description":"Organize surveys with tags. Tags are scoped to your team/account."},{"name":"Projects","description":"Organize surveys into projects. Projects group related surveys and can be bookmarked or archived."},{"name":"Traits","description":"Audience targeting and reporting traits used to reach specific demographics and segment survey results."},{"name":"Playbooks","description":"Discover and retrieve step-by-step research playbooks. Each playbook is a structured sequence of polls designed for a specific research goal."},{"name":"Help","description":"Search the PickFu help center for articles and guides."},{"name":"Media","description":"Generate images from text prompts and upload media files to the PickFu CDN."},{"name":"Semantic Search","description":"Search completed surveys in your enrolled team account by meaning and answer evidence."}]}