API reference
Generated from the schemas the API validates against, so a field listed here is a field the API accepts.
OpenAPI 3.1: https://api.50heads.com/openapi.json. Generated from the same schemas, so it never drifts from this page. Load it into Postman, Insomnia or a client generator.
Pricing and config
Unauthenticated and rate limited. Estimate as often as you like; it never spends.
POST/v1/billing/estimate
Price, time and validation for a question draft.
No authentication.
Counts as half a request against the rate limit. validation lists anything that would stop the ask, one issue per field.
| Field | Type | Notes |
|---|---|---|
draft | object | required |
draft.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
draft.text | string | required up to 600 characters |
draft.context | string | up to 120 characters |
draft.language | string | pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
draft.options | object[] | up to 8 items, default [] |
draft.options[].label | string | required up to 40 characters |
draft.options[].imageUrl | string (URL) | |
draft.neither | boolean | default false |
draft.stimulus | object | |
draft.stimulus.imageUrl | string (URL) | |
draft.stimulus.audioUrl | string (URL) | |
draft.stimulus.text | string | up to 120 characters |
draft.stimulus.exposureMs | integer | 2000–10000 |
draft.n | integer | 10–5000, default 50 |
draft.tier | 1 | 2 | 3 | default 1 |
draft.rush | boolean | default false |
draft.targeting | object | |
draft.targeting.countries | string[] | up to 50 items, default [] |
draft.targeting.tags | string[] | up to 20 items, default [] |
draft.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
draft.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
draft.targeting.verifiedAge | boolean | |
draft.clickTest | object | |
draft.clickTest.maxTaps | integer | 1–5, default 1 |
draft.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
draft.publicResults | boolean | default false |
draft.reason | "off" | "optional" | "required" | default "off" |
draft.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
surface | "app" | "web" |
| Field | Type | Notes |
|---|---|---|
creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
creditsTotal | integer | required -9007199254740991–9007199254740991 |
payPerAnswer | integer | required -9007199254740991–9007199254740991 |
etaMinutes | integer | required -9007199254740991–9007199254740991 |
traits | integer | required -9007199254740991–9007199254740991 |
breakdown | object[] | required |
breakdown[].label | string | required |
breakdown[].value | string | required |
breakdownLine | string | required |
validation | object[] | required |
validation[].field | string | required |
validation[].code | string | required |
validation[].message | string | required |
poolSize | integer | null | required |
GET/v1/config
Credit exchange rates, the country table and question languages.
No authentication.
| Field | Type | Notes |
|---|---|---|
rates | map of number | required |
ratesDate | string | required |
countries | map of object | required |
defaultCountry | object | required |
defaultCountry.payMultiplier | number | required |
defaultCountry.minWithdrawalPence | integer | required -9007199254740991–9007199254740991 |
defaultCountry.payoutRails | string[] | required |
defaultCountry.otpChannel | "sms" | "whatsapp" | required |
defaultCountry.taxFields | string[] | required |
defaultCountry.tier2Available | boolean | required |
defaultCountry.currency | "GBP" | "USD" | "EUR" | "CAD" | required |
defaultCountry.wiseFields | object[] | |
defaultCountry.wiseFields[].key | string | required |
defaultCountry.wiseFields[].label | string | required |
defaultCountry.wiseFields[].example | string | |
defaultCountry.wiseFields[].pattern | string | |
questionLanguages | "en" | "es" | "pt" | "hi" | "fr" | "de" | "id" | "tl"[] | required |
reverifyDays | integer | required -9007199254740991–9007199254740991 |
tier1PayPence | integer | required -9007199254740991–9007199254740991 |
tier2PayMultiplier | number | required |
answeringCountries | string[] | |
webTopUpStorefronts | string[] |
GET/v1/templates
Fixed-price question templates.
No authentication.
| Field | Type | Notes |
|---|---|---|
templates | object[] | required |
templates[].id | string | required |
templates[].name | string | required |
templates[].description | string | required |
templates[].draft | object | required |
templates[].draft.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
templates[].draft.text | string | required up to 600 characters |
templates[].draft.context | string | up to 120 characters |
templates[].draft.language | string | required pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
templates[].draft.options | object[] | required up to 8 items, default [] |
templates[].draft.neither | boolean | required default false |
templates[].draft.stimulus | object | |
templates[].draft.n | integer | required 10–5000, default 50 |
templates[].draft.tier | 1 | 2 | 3 | required default 1 |
templates[].draft.rush | boolean | required default false |
templates[].draft.targeting | object | |
templates[].draft.clickTest | object | |
templates[].draft.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
templates[].draft.publicResults | boolean | required default false |
templates[].draft.reason | "off" | "optional" | "required" | required default "off" |
templates[].draft.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
templates[].priceCredits | integer | required -9007199254740991–9007199254740991 |
GET/v1/public/countries
Where heads answer from, the languages they read and pool size bands by tier.
No authentication.
| Field | Type | Notes |
|---|---|---|
countries | object[] | required |
countries[].code | string | required up to 2 characters, at least 2 characters |
countries[].name | string | required |
countries[].languages | string[] | required |
countries[].tier2Available | boolean | required |
countries[].poolBands | object | required |
countries[].poolBands.tier1 | string | null | required |
countries[].poolBands.tier2 | string | null | required |
countries[].poolBands.tier3 | string | null | required |
updatedAt | string | required |
GET/v1/tags
The self-declared tags you can target at any tier, by group (one trait per group).
No authentication.
| Field | Type | Notes |
|---|---|---|
groups | object[] | required |
groups[].id | "life_stage" | "household" | "income" | "education" | "occupation" | "interests" | "habits" | "shopping" | "health" | "media" | "pets" | "tech" | required |
groups[].label | string | required |
groups[].why | string | required |
groups[].max | integer | required -9007199254740991–9007199254740991 |
tags | object[] | required |
tags[].id | string | required |
tags[].group | "life_stage" | "household" | "income" | "education" | "occupation" | "interests" | "habits" | "shopping" | "health" | "media" | "pets" | "tech" | required |
tags[].label | string | required |
GET/v1/public/stats
Heads online now, answers this week and the median time to fifty answers.
No authentication.
| Field | Type | Notes |
|---|---|---|
headsOnlineNow | integer | required -9007199254740991–9007199254740991 |
answersThisWeek | integer | required -9007199254740991–9007199254740991 |
medianMinutesTo50 | number | required |
headEarningsPerHour | object | required |
headEarningsPerHour.low | integer | required -9007199254740991–9007199254740991 |
headEarningsPerHour.high | integer | required -9007199254740991–9007199254740991 |
updatedAt | string | required |
Questions
Ask, wait and read results. Asking reserves the full price from your credits; answers not given are refunded when the question closes.
POST/v2/questions
Ask a question.
API key or OAuth token with questions:write. Idempotency-Key header required.
Requires an Idempotency-Key header (a UUID). The same key returns the same question for 24 hours; a different body with the same key is idempotency_conflict. Fails with insufficient_credits, spend_cap_exceeded or content_refused without spending anything.
| Field | Type | Notes |
|---|---|---|
draft | object | required |
draft.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
draft.text | string | required up to 600 characters |
draft.context | string | up to 120 characters |
draft.language | string | pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
draft.options | object[] | up to 8 items, default [] |
draft.options[].label | string | required up to 40 characters |
draft.options[].imageUrl | string (URL) | |
draft.neither | boolean | default false |
draft.stimulus | object | |
draft.stimulus.imageUrl | string (URL) | |
draft.stimulus.audioUrl | string (URL) | |
draft.stimulus.text | string | up to 120 characters |
draft.stimulus.exposureMs | integer | 2000–10000 |
draft.n | integer | 10–5000, default 50 |
draft.tier | 1 | 2 | 3 | default 1 |
draft.rush | boolean | default false |
draft.targeting | object | |
draft.targeting.countries | string[] | up to 50 items, default [] |
draft.targeting.tags | string[] | up to 20 items, default [] |
draft.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
draft.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
draft.targeting.verifiedAge | boolean | |
draft.clickTest | object | |
draft.clickTest.maxTaps | integer | 1–5, default 1 |
draft.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
draft.publicResults | boolean | default false |
draft.reason | "off" | "optional" | "required" | default "off" |
draft.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
fromDraftId | string | |
then | object[] | up to 3 items |
then[].type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | default "free_text" |
then[].text | string | required up to 600 characters, at least 8 characters |
then[].options | object[] | up to 8 items, default [] |
then[].options[].label | string | required up to 40 characters |
then[].options[].imageUrl | string (URL) | |
then[].n | integer | 10–5000, default 20 |
then[].tier | 1 | 2 | 3 | default 2 |
then[].minConfidence | "low" | "medium" | "high" | |
then[].reason | "off" | "optional" | "required" | |
variantOf | string | |
templateId | string | |
projectId | string | null | |
labels | string[] | up to 10 items |
externalRef | string | up to 100 characters, pattern ^[\w.:\-/#@+]+$ |
| Field | Type | Notes |
|---|---|---|
question | object | required |
question.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
question.text | string | required up to 600 characters |
question.context | string | up to 120 characters |
question.language | string | required pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
question.options | object[] | required up to 8 items, default [] |
question.options[].label | string | required up to 40 characters |
question.options[].imageUrl | string (URL) | |
question.neither | boolean | required default false |
question.stimulus | object | |
question.stimulus.imageUrl | string (URL) | |
question.stimulus.audioUrl | string (URL) | |
question.stimulus.text | string | up to 120 characters |
question.stimulus.exposureMs | integer | 2000–10000 |
question.n | integer | required 10–5000, default 50 |
question.tier | 1 | 2 | 3 | required default 1 |
question.rush | boolean | required default false |
question.targeting | object | |
question.targeting.countries | string[] | required up to 50 items, default [] |
question.targeting.tags | string[] | required up to 20 items, default [] |
question.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
question.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
question.targeting.verifiedAge | boolean | |
question.clickTest | object | |
question.clickTest.maxTaps | integer | required 1–5, default 1 |
question.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
question.publicResults | boolean | required default false |
question.reason | "off" | "optional" | "required" | required default "off" |
question.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
question.id | string | required |
question.status | "draft" | "scheduled" | "live" | "complete" | "underfilled" | "cancelled" | "refused" | required |
question.source | "app" | "portal" | "api" | "mcp" | required |
question.answered | integer | required -9007199254740991–9007199254740991 |
question.creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
question.creditsReserved | integer | required -9007199254740991–9007199254740991 |
question.creditsSpent | integer | required -9007199254740991–9007199254740991 |
question.etaMinutes | integer | required -9007199254740991–9007199254740991 |
question.leaderLine | string | null | required |
question.refusedCategory | string | null | required |
question.publicCode | string | null | required |
question.createdAt | string | required |
question.liveAt | string | null | required |
question.closedAt | string | null | required |
question.teamId | string | null | |
question.askedBy | object | null | |
question.askedBy.id | string | required |
question.askedBy.name | string | null | required |
question.projectId | string | null | |
question.labels | string[] | |
question.archived | boolean | |
question.bookmarked | boolean | |
question.externalRef | string | null |
GET/v2/questions
Your questions, newest first.
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
status | "draft" | "scheduled" | "live" | "complete" | "underfilled" | "cancelled" | "refused" | |
since | string | |
limit | integer | 1–100 |
cursor | string | |
projectId | string | |
label | string | |
externalRef | string | |
archived | "exclude" | "only" | "include" | |
bookmarked | boolean | |
mine | boolean |
| Field | Type | Notes |
|---|---|---|
questions | object[] | required |
questions[].type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
questions[].text | string | required up to 600 characters |
questions[].context | string | up to 120 characters |
questions[].language | string | required pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
questions[].options | object[] | required up to 8 items, default [] |
questions[].options[].label | string | required up to 40 characters |
questions[].options[].imageUrl | string (URL) | |
questions[].neither | boolean | required default false |
questions[].stimulus | object | |
questions[].stimulus.imageUrl | string (URL) | |
questions[].stimulus.audioUrl | string (URL) | |
questions[].stimulus.text | string | up to 120 characters |
questions[].stimulus.exposureMs | integer | 2000–10000 |
questions[].n | integer | required 10–5000, default 50 |
questions[].tier | 1 | 2 | 3 | required default 1 |
questions[].rush | boolean | required default false |
questions[].targeting | object | |
questions[].targeting.countries | string[] | required up to 50 items, default [] |
questions[].targeting.tags | string[] | required up to 20 items, default [] |
questions[].targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
questions[].targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
questions[].targeting.verifiedAge | boolean | |
questions[].clickTest | object | |
questions[].clickTest.maxTaps | integer | required 1–5, default 1 |
questions[].scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
questions[].publicResults | boolean | required default false |
questions[].reason | "off" | "optional" | "required" | required default "off" |
questions[].contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
questions[].id | string | required |
questions[].status | "draft" | "scheduled" | "live" | "complete" | "underfilled" | "cancelled" | "refused" | required |
questions[].source | "app" | "portal" | "api" | "mcp" | required |
questions[].answered | integer | required -9007199254740991–9007199254740991 |
questions[].creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
questions[].creditsReserved | integer | required -9007199254740991–9007199254740991 |
questions[].creditsSpent | integer | required -9007199254740991–9007199254740991 |
questions[].etaMinutes | integer | required -9007199254740991–9007199254740991 |
questions[].leaderLine | string | null | required |
questions[].refusedCategory | string | null | required |
questions[].publicCode | string | null | required |
questions[].createdAt | string | required |
questions[].liveAt | string | null | required |
questions[].closedAt | string | null | required |
questions[].teamId | string | null | |
questions[].askedBy | object | null | |
questions[].askedBy.id | string | required |
questions[].askedBy.name | string | null | required |
questions[].projectId | string | null | |
questions[].labels | string[] | |
questions[].archived | boolean | |
questions[].bookmarked | boolean | |
questions[].externalRef | string | null | |
nextCursor | string | null | required |
GET/v2/questions/{id}
One question and its progress.
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
question | object | required |
question.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
question.text | string | required up to 600 characters |
question.context | string | up to 120 characters |
question.language | string | required pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
question.options | object[] | required up to 8 items, default [] |
question.options[].label | string | required up to 40 characters |
question.options[].imageUrl | string (URL) | |
question.neither | boolean | required default false |
question.stimulus | object | |
question.stimulus.imageUrl | string (URL) | |
question.stimulus.audioUrl | string (URL) | |
question.stimulus.text | string | up to 120 characters |
question.stimulus.exposureMs | integer | 2000–10000 |
question.n | integer | required 10–5000, default 50 |
question.tier | 1 | 2 | 3 | required default 1 |
question.rush | boolean | required default false |
question.targeting | object | |
question.targeting.countries | string[] | required up to 50 items, default [] |
question.targeting.tags | string[] | required up to 20 items, default [] |
question.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
question.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
question.targeting.verifiedAge | boolean | |
question.clickTest | object | |
question.clickTest.maxTaps | integer | required 1–5, default 1 |
question.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
question.publicResults | boolean | required default false |
question.reason | "off" | "optional" | "required" | required default "off" |
question.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
question.id | string | required |
question.status | "draft" | "scheduled" | "live" | "complete" | "underfilled" | "cancelled" | "refused" | required |
question.source | "app" | "portal" | "api" | "mcp" | required |
question.answered | integer | required -9007199254740991–9007199254740991 |
question.creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
question.creditsReserved | integer | required -9007199254740991–9007199254740991 |
question.creditsSpent | integer | required -9007199254740991–9007199254740991 |
question.etaMinutes | integer | required -9007199254740991–9007199254740991 |
question.leaderLine | string | null | required |
question.refusedCategory | string | null | required |
question.publicCode | string | null | required |
question.createdAt | string | required |
question.liveAt | string | null | required |
question.closedAt | string | null | required |
question.teamId | string | null | |
question.askedBy | object | null | |
question.askedBy.id | string | required |
question.askedBy.name | string | null | required |
question.projectId | string | null | |
question.labels | string[] | |
question.archived | boolean | |
question.bookmarked | boolean | |
question.externalRef | string | null |
PATCH/v2/questions/{id}
Complete early once minAnswers heads have answered, or file it: project, labels, archive, bookmark and a set-once externalRef.
API key or OAuth token with questions:write.
If that many have already answered, the question closes now and what was not answered is refunded. Changing an externalRef once set is refused with 409 external_ref_set.
| Field | Type | Notes |
|---|---|---|
minAnswers | integer | 1–5000 |
projectId | string | null | |
labels | string[] | up to 10 items |
archived | boolean | |
bookmarked | boolean | |
externalRef | string | up to 100 characters, pattern ^[\w.:\-/#@+]+$ |
| Field | Type | Notes |
|---|---|---|
question | object | required |
question.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
question.text | string | required up to 600 characters |
question.context | string | up to 120 characters |
question.language | string | required pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
question.options | object[] | required up to 8 items, default [] |
question.options[].label | string | required up to 40 characters |
question.options[].imageUrl | string (URL) | |
question.neither | boolean | required default false |
question.stimulus | object | |
question.stimulus.imageUrl | string (URL) | |
question.stimulus.audioUrl | string (URL) | |
question.stimulus.text | string | up to 120 characters |
question.stimulus.exposureMs | integer | 2000–10000 |
question.n | integer | required 10–5000, default 50 |
question.tier | 1 | 2 | 3 | required default 1 |
question.rush | boolean | required default false |
question.targeting | object | |
question.targeting.countries | string[] | required up to 50 items, default [] |
question.targeting.tags | string[] | required up to 20 items, default [] |
question.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
question.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
question.targeting.verifiedAge | boolean | |
question.clickTest | object | |
question.clickTest.maxTaps | integer | required 1–5, default 1 |
question.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
question.publicResults | boolean | required default false |
question.reason | "off" | "optional" | "required" | required default "off" |
question.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
question.id | string | required |
question.status | "draft" | "scheduled" | "live" | "complete" | "underfilled" | "cancelled" | "refused" | required |
question.source | "app" | "portal" | "api" | "mcp" | required |
question.answered | integer | required -9007199254740991–9007199254740991 |
question.creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
question.creditsReserved | integer | required -9007199254740991–9007199254740991 |
question.creditsSpent | integer | required -9007199254740991–9007199254740991 |
question.etaMinutes | integer | required -9007199254740991–9007199254740991 |
question.leaderLine | string | null | required |
question.refusedCategory | string | null | required |
question.publicCode | string | null | required |
question.createdAt | string | required |
question.liveAt | string | null | required |
question.closedAt | string | null | required |
question.teamId | string | null | |
question.askedBy | object | null | |
question.askedBy.id | string | required |
question.askedBy.name | string | null | required |
question.projectId | string | null | |
question.labels | string[] | |
question.archived | boolean | |
question.bookmarked | boolean | |
question.externalRef | string | null |
GET/v2/questions/labels
Labels in use in the account, most used first.
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
labels | object[] | required |
labels[].label | string | required |
labels[].count | integer | required -9007199254740991–9007199254740991 |
GET/v2/questions/{id}/result
The result so far. Partial while the question is live.
API key or OAuth token with questions:read.
With a filter, the distribution, breakdowns and answers are of matching answers only; nUnfiltered counts them all and suppressed is true when a country or age band matched too few to show. insights is the summary of written answers once there is one.
| Field | Type | Notes |
|---|---|---|
option | integer | 0–8 |
tier | integer | 1–3 |
country | string | up to 2 characters, at least 2 characters |
age_band | string | |
q | string | up to 100 characters |
| Field | Type | Notes |
|---|---|---|
result | object | required |
result.questionId | string | required |
result.status | "in_progress" | "complete" | "underfilled" | "cancelled" | required |
result.nRequested | integer | required -9007199254740991–9007199254740991 |
result.nAccepted | integer | required -9007199254740991–9007199254740991 |
result.distribution | object[] | required |
result.distribution[].option | string | required |
result.distribution[].count | integer | required -9007199254740991–9007199254740991 |
result.distribution[].share | number | required |
result.distribution[].averageRank | number | |
result.distribution[].appearances | integer | -9007199254740991–9007199254740991 |
result.distribution[].strength | number | |
result.distribution[].rank | integer | -9007199254740991–9007199254740991 |
result.mean | number | null | required |
result.summary | object | required |
result.summary.winner | string | null | required |
result.summary.margin | number | null | required |
result.summary.confidence | "low" | "medium" | "high" | null | required |
result.summary.note | string | required |
result.summary.suggestedFollowUp | string | null | required |
result.tier | integer | required -9007199254740991–9007199254740991 |
result.language | string | required |
result.verificationLine | string | required |
result.medianSeconds | number | null | required |
result.creditsSpent | integer | required -9007199254740991–9007199254740991 |
result.answers | object[] | required |
result.answers[].option | string | null | required |
result.answers[].text | string | null | required |
result.answers[].translatedText | string | null | |
result.answers[].reason | string | null | |
result.answers[].translatedReason | string | null | |
result.answers[].tier | integer | required -9007199254740991–9007199254740991 |
result.answers[].attestationRef | string | required |
result.answers[].answeredAt | string | required |
result.answers[].pinned | boolean | |
result.answers[].flag | object | null | |
result.answers[].taps | object[] | |
result.breakdown | object[] | |
result.breakdown[].tagId | string | required |
result.breakdown[].label | string | required |
result.breakdown[].n | integer | required -9007199254740991–9007199254740991 |
result.breakdown[].distribution | object[] | required |
result.refundCredits | integer | required -9007199254740991–9007199254740991 |
result.breakdowns | object[] | |
result.breakdowns[].dimension | "country" | "tier" | "age_band" | "gender" | "tag" | required |
result.breakdowns[].segments | object[] | required |
result.clicks | object | |
result.clicks.imageUrl | string | null | required |
result.clicks.taps | integer | required -9007199254740991–9007199254740991 |
result.clicks.points | object[] | required |
result.clicks.grid | integer[] | required |
result.clicks.gridSize | integer | required -9007199254740991–9007199254740991 |
result.clicks.hotspots | object[] | required |
result.clicks.heatmapUrl | string | null | required |
result.sentiment | object | |
result.sentiment.positive | number | required |
result.sentiment.neutral | number | required |
result.sentiment.negative | number | required |
result.translationLanguage | string | null | |
result.insights | object | null | |
result.insights.questionId | string | required |
result.insights.language | string | required |
result.insights.sourceLanguage | string | required |
result.insights.takeaway | string | required |
result.insights.themes | object[] | required up to 8 items |
result.insights.sentiment | object | required |
result.insights.basedOn | integer | required -9007199254740991–9007199254740991 |
result.insights.answersAtTime | integer | required -9007199254740991–9007199254740991 |
result.insights.original | object | null | required |
result.insights.kind | "interim" | "final" | required |
result.insights.generatedAt | string | required |
result.insights.refreshAfter | string | null | required |
result.insights.engine | string | required |
result.filter | object | |
result.filter.option | integer | 0–8 |
result.filter.tier | integer | 1–3 |
result.filter.country | object | |
result.filter.ageBand | string | pattern ^[0-9]{2}(-[0-9]{2}|\+)$ |
result.filter.gender | "woman" | "man" | "non_binary" | |
result.filter.q | string | up to 100 characters |
result.nUnfiltered | integer | -9007199254740991–9007199254740991 |
result.suppressed | boolean | |
result.facets | object | |
result.facets.tiers | object[] | required |
result.facets.countries | object[] | required |
result.facets.ageBands | object[] | required |
result.facets.genders | object[] |
GET/v2/questions/{id}/answers
Matching answers, newest first, a page at a time, with reasons and translations.
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
option | integer | 0–8 |
tier | integer | 1–3 |
country | string | up to 2 characters, at least 2 characters |
age_band | string | |
q | string | up to 100 characters |
limit | integer | 1–200 |
cursor | string | up to 200 characters |
| Field | Type | Notes |
|---|---|---|
questionId | string | required |
filter | object | required |
filter.option | integer | 0–8 |
filter.tier | integer | 1–3 |
filter.country | object | |
filter.ageBand | string | pattern ^[0-9]{2}(-[0-9]{2}|\+)$ |
filter.gender | "woman" | "man" | "non_binary" | |
filter.q | string | up to 100 characters |
total | integer | required -9007199254740991–9007199254740991 |
nUnfiltered | integer | required -9007199254740991–9007199254740991 |
suppressed | boolean | required |
answers | object[] | required |
answers[].option | string | null | required |
answers[].text | string | null | required |
answers[].translatedText | string | null | |
answers[].reason | string | null | |
answers[].translatedReason | string | null | |
answers[].tier | integer | required -9007199254740991–9007199254740991 |
answers[].attestationRef | string | required |
answers[].answeredAt | string | required |
answers[].pinned | boolean | |
answers[].flag | object | null | |
answers[].flag.reason | "off_topic" | "low_effort" | "abusive" | "automated" | required |
answers[].flag.status | "open" | "upheld" | "dismissed" | required |
answers[].flag.refundCredits | integer | required -9007199254740991–9007199254740991 |
answers[].flag.createdAt | string | required |
answers[].flag.decidedAt | string | null | required |
answers[].taps | object[] | |
answers[].taps[].x | number | required 0–1 |
answers[].taps[].y | number | required 0–1 |
translationLanguage | string | null | required |
nextCursor | string | null | required |
GET/v2/questions/{id}/insights
The summary of the written answers: themes with counts and quotes, sentiment, a takeaway.
API key or OAuth token with questions:read.
Made by a machine from the reasons and free text, never from who answered; counts and quotes are computed from the answers. Written in the account's language, with the question-language original.
| Field | Type | Notes |
|---|---|---|
insights | object | null | required |
insights.questionId | string | required |
insights.language | string | required |
insights.sourceLanguage | string | required |
insights.takeaway | string | required |
insights.themes | object[] | required up to 8 items |
insights.themes[].label | string | required |
insights.themes[].count | integer | required -9007199254740991–9007199254740991 |
insights.themes[].share | number | required |
insights.themes[].sentiment | "positive" | "neutral" | "negative" | required |
insights.themes[].option | string | null | required |
insights.themes[].quotes | string[] | required up to 3 items |
insights.sentiment | object | required |
insights.sentiment.positive | integer | required -9007199254740991–9007199254740991 |
insights.sentiment.neutral | integer | required -9007199254740991–9007199254740991 |
insights.sentiment.negative | integer | required -9007199254740991–9007199254740991 |
insights.basedOn | integer | required -9007199254740991–9007199254740991 |
insights.answersAtTime | integer | required -9007199254740991–9007199254740991 |
insights.original | object | null | required |
insights.original.takeaway | string | required |
insights.original.themes | object[] | required |
insights.kind | "interim" | "final" | required |
insights.generatedAt | string | required |
insights.refreshAfter | string | null | required |
insights.engine | string | required |
POST/v2/questions/{id}/insights
Make a fresh summary now: once every 10 minutes while live; the final one when it closes.
API key or OAuth token with questions:read.
429 rate_limited with retryAfterMs while a recent summary stands; 409 too_few_answers under three written answers.
| Field | Type | Notes |
|---|---|---|
insights | object | null | required |
insights.questionId | string | required |
insights.language | string | required |
insights.sourceLanguage | string | required |
insights.takeaway | string | required |
insights.themes | object[] | required up to 8 items |
insights.themes[].label | string | required |
insights.themes[].count | integer | required -9007199254740991–9007199254740991 |
insights.themes[].share | number | required |
insights.themes[].sentiment | "positive" | "neutral" | "negative" | required |
insights.themes[].option | string | null | required |
insights.themes[].quotes | string[] | required up to 3 items |
insights.sentiment | object | required |
insights.sentiment.positive | integer | required -9007199254740991–9007199254740991 |
insights.sentiment.neutral | integer | required -9007199254740991–9007199254740991 |
insights.sentiment.negative | integer | required -9007199254740991–9007199254740991 |
insights.basedOn | integer | required -9007199254740991–9007199254740991 |
insights.answersAtTime | integer | required -9007199254740991–9007199254740991 |
insights.original | object | null | required |
insights.original.takeaway | string | required |
insights.original.themes | object[] | required |
insights.kind | "interim" | "final" | required |
insights.generatedAt | string | required |
insights.refreshAfter | string | null | required |
insights.engine | string | required |
GET/v2/questions/{id}/wait
Hold the request until the question is answered, up to 25 seconds a call.
API key or OAuth token with questions:read.
Call again while done is false. minAnswers completes early once that many heads have answered.
| Field | Type | Notes |
|---|---|---|
seconds | integer | 1–25 |
minAnswers | integer | 1–9007199254740991 |
| Field | Type | Notes |
|---|---|---|
result | object | required |
result.questionId | string | required |
result.status | "in_progress" | "complete" | "underfilled" | "cancelled" | required |
result.nRequested | integer | required -9007199254740991–9007199254740991 |
result.nAccepted | integer | required -9007199254740991–9007199254740991 |
result.distribution | object[] | required |
result.distribution[].option | string | required |
result.distribution[].count | integer | required -9007199254740991–9007199254740991 |
result.distribution[].share | number | required |
result.distribution[].averageRank | number | |
result.distribution[].appearances | integer | -9007199254740991–9007199254740991 |
result.distribution[].strength | number | |
result.distribution[].rank | integer | -9007199254740991–9007199254740991 |
result.mean | number | null | required |
result.summary | object | required |
result.summary.winner | string | null | required |
result.summary.margin | number | null | required |
result.summary.confidence | "low" | "medium" | "high" | null | required |
result.summary.note | string | required |
result.summary.suggestedFollowUp | string | null | required |
result.tier | integer | required -9007199254740991–9007199254740991 |
result.language | string | required |
result.verificationLine | string | required |
result.medianSeconds | number | null | required |
result.creditsSpent | integer | required -9007199254740991–9007199254740991 |
result.answers | object[] | required |
result.answers[].option | string | null | required |
result.answers[].text | string | null | required |
result.answers[].translatedText | string | null | |
result.answers[].reason | string | null | |
result.answers[].translatedReason | string | null | |
result.answers[].tier | integer | required -9007199254740991–9007199254740991 |
result.answers[].attestationRef | string | required |
result.answers[].answeredAt | string | required |
result.answers[].pinned | boolean | |
result.answers[].flag | object | null | |
result.answers[].taps | object[] | |
result.breakdown | object[] | |
result.breakdown[].tagId | string | required |
result.breakdown[].label | string | required |
result.breakdown[].n | integer | required -9007199254740991–9007199254740991 |
result.breakdown[].distribution | object[] | required |
result.refundCredits | integer | required -9007199254740991–9007199254740991 |
result.breakdowns | object[] | |
result.breakdowns[].dimension | "country" | "tier" | "age_band" | "gender" | "tag" | required |
result.breakdowns[].segments | object[] | required |
result.clicks | object | |
result.clicks.imageUrl | string | null | required |
result.clicks.taps | integer | required -9007199254740991–9007199254740991 |
result.clicks.points | object[] | required |
result.clicks.grid | integer[] | required |
result.clicks.gridSize | integer | required -9007199254740991–9007199254740991 |
result.clicks.hotspots | object[] | required |
result.clicks.heatmapUrl | string | null | required |
result.sentiment | object | |
result.sentiment.positive | number | required |
result.sentiment.neutral | number | required |
result.sentiment.negative | number | required |
result.translationLanguage | string | null | |
result.insights | object | null | |
result.insights.questionId | string | required |
result.insights.language | string | required |
result.insights.sourceLanguage | string | required |
result.insights.takeaway | string | required |
result.insights.themes | object[] | required up to 8 items |
result.insights.sentiment | object | required |
result.insights.basedOn | integer | required -9007199254740991–9007199254740991 |
result.insights.answersAtTime | integer | required -9007199254740991–9007199254740991 |
result.insights.original | object | null | required |
result.insights.kind | "interim" | "final" | required |
result.insights.generatedAt | string | required |
result.insights.refreshAfter | string | null | required |
result.insights.engine | string | required |
result.filter | object | |
result.filter.option | integer | 0–8 |
result.filter.tier | integer | 1–3 |
result.filter.country | object | |
result.filter.ageBand | string | pattern ^[0-9]{2}(-[0-9]{2}|\+)$ |
result.filter.gender | "woman" | "man" | "non_binary" | |
result.filter.q | string | up to 100 characters |
result.nUnfiltered | integer | -9007199254740991–9007199254740991 |
result.suppressed | boolean | |
result.facets | object | |
result.facets.tiers | object[] | required |
result.facets.countries | object[] | required |
result.facets.ageBands | object[] | required |
result.facets.genders | object[] | |
done | boolean | required |
POST/v2/questions/{id}/cancel
Stop a live question and refund the answers not given.
API key or OAuth token with questions:write.
| Field | Type | Notes |
|---|---|---|
question | object | required |
question.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
question.text | string | required up to 600 characters |
question.context | string | up to 120 characters |
question.language | string | required pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
question.options | object[] | required up to 8 items, default [] |
question.options[].label | string | required up to 40 characters |
question.options[].imageUrl | string (URL) | |
question.neither | boolean | required default false |
question.stimulus | object | |
question.stimulus.imageUrl | string (URL) | |
question.stimulus.audioUrl | string (URL) | |
question.stimulus.text | string | up to 120 characters |
question.stimulus.exposureMs | integer | 2000–10000 |
question.n | integer | required 10–5000, default 50 |
question.tier | 1 | 2 | 3 | required default 1 |
question.rush | boolean | required default false |
question.targeting | object | |
question.targeting.countries | string[] | required up to 50 items, default [] |
question.targeting.tags | string[] | required up to 20 items, default [] |
question.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
question.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
question.targeting.verifiedAge | boolean | |
question.clickTest | object | |
question.clickTest.maxTaps | integer | required 1–5, default 1 |
question.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
question.publicResults | boolean | required default false |
question.reason | "off" | "optional" | "required" | required default "off" |
question.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
question.id | string | required |
question.status | "draft" | "scheduled" | "live" | "complete" | "underfilled" | "cancelled" | "refused" | required |
question.source | "app" | "portal" | "api" | "mcp" | required |
question.answered | integer | required -9007199254740991–9007199254740991 |
question.creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
question.creditsReserved | integer | required -9007199254740991–9007199254740991 |
question.creditsSpent | integer | required -9007199254740991–9007199254740991 |
question.etaMinutes | integer | required -9007199254740991–9007199254740991 |
question.leaderLine | string | null | required |
question.refusedCategory | string | null | required |
question.publicCode | string | null | required |
question.createdAt | string | required |
question.liveAt | string | null | required |
question.closedAt | string | null | required |
question.teamId | string | null | |
question.askedBy | object | null | |
question.askedBy.id | string | required |
question.askedBy.name | string | null | required |
question.projectId | string | null | |
question.labels | string[] | |
question.archived | boolean | |
question.bookmarked | boolean | |
question.externalRef | string | null | |
refundCredits | integer | required -9007199254740991–9007199254740991 |
GET/v2/questions/{id}/export.csv
Every answer as CSV: option or text, reason, translations, tier, attestation reference, time, and taps for a click test.
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
option | integer | 0–8 |
tier | integer | 1–3 |
country | string | up to 2 characters, at least 2 characters |
age_band | string | |
q | string | up to 100 characters |
GET/v2/questions/{id}/export.pdf
A one-page PDF report: the question, the chart, what it means and the answers (pinned first).
API key or OAuth token with questions:read.
GET/v2/questions/{id}/export.png
The chart as a PNG to share: size=square (1080×1080, default), wide (1200×675) or story (1080×1920).
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
size | "square" | "wide" | "story" |
POST/v2/questions/{id}/exports
A PDF report or PNG chart as a signed link that works for an hour without signing in.
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
format | "pdf" | "png" | required |
size | "square" | "wide" | "story" |
| Field | Type | Notes |
|---|---|---|
export | object | required |
export.format | "pdf" | "png" | required |
export.size | "square" | "wide" | "story" | null | required |
export.url | string | required |
export.filename | string | required |
export.expiresAt | string | required |
POST/v2/questions/{id}/heads
Reopen a finished question for n more heads, same wording and targeting; answers merge. dryRun quotes only.
API key or OAuth token with questions:write. Idempotency-Key header required.
Needs an Idempotency-Key unless dryRun. The question must be complete or underfilled.
| Field | Type | Notes |
|---|---|---|
n | integer | required 1–5000 |
dryRun | boolean |
| Field | Type | Notes |
|---|---|---|
question | object | |
question.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
question.text | string | required up to 600 characters |
question.context | string | up to 120 characters |
question.language | string | required pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
question.options | object[] | required up to 8 items, default [] |
question.options[].label | string | required up to 40 characters |
question.options[].imageUrl | string (URL) | |
question.neither | boolean | required default false |
question.stimulus | object | |
question.stimulus.imageUrl | string (URL) | |
question.stimulus.audioUrl | string (URL) | |
question.stimulus.text | string | up to 120 characters |
question.stimulus.exposureMs | integer | 2000–10000 |
question.n | integer | required 10–5000, default 50 |
question.tier | 1 | 2 | 3 | required default 1 |
question.rush | boolean | required default false |
question.targeting | object | |
question.targeting.countries | string[] | required up to 50 items, default [] |
question.targeting.tags | string[] | required up to 20 items, default [] |
question.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
question.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
question.targeting.verifiedAge | boolean | |
question.clickTest | object | |
question.clickTest.maxTaps | integer | required 1–5, default 1 |
question.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
question.publicResults | boolean | required default false |
question.reason | "off" | "optional" | "required" | required default "off" |
question.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
question.id | string | required |
question.status | "draft" | "scheduled" | "live" | "complete" | "underfilled" | "cancelled" | "refused" | required |
question.source | "app" | "portal" | "api" | "mcp" | required |
question.answered | integer | required -9007199254740991–9007199254740991 |
question.creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
question.creditsReserved | integer | required -9007199254740991–9007199254740991 |
question.creditsSpent | integer | required -9007199254740991–9007199254740991 |
question.etaMinutes | integer | required -9007199254740991–9007199254740991 |
question.leaderLine | string | null | required |
question.refusedCategory | string | null | required |
question.publicCode | string | null | required |
question.createdAt | string | required |
question.liveAt | string | null | required |
question.closedAt | string | null | required |
question.teamId | string | null | |
question.askedBy | object | null | |
question.askedBy.id | string | required |
question.askedBy.name | string | null | required |
question.projectId | string | null | |
question.labels | string[] | |
question.archived | boolean | |
question.bookmarked | boolean | |
question.externalRef | string | null | |
quote | object | required |
quote.n | integer | required -9007199254740991–9007199254740991 |
quote.creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
quote.creditsTotal | integer | required -9007199254740991–9007199254740991 |
quote.etaMinutes | integer | required -9007199254740991–9007199254740991 |
quote.newTarget | integer | required -9007199254740991–9007199254740991 |
quote.line | string | required |
creditsReserved | integer | -9007199254740991–9007199254740991 |
POST/v2/questions/{id}/answers/{ref}/flag
Flag one answer, named by its attestation reference, for review. Upheld: removed and refunded.
API key or OAuth token with questions:write.
| Field | Type | Notes |
|---|---|---|
reason | "off_topic" | "low_effort" | "abusive" | "automated" | required |
note | string | up to 500 characters |
| Field | Type | Notes |
|---|---|---|
flag | object | required |
flag.reason | "off_topic" | "low_effort" | "abusive" | "automated" | required |
flag.status | "open" | "upheld" | "dismissed" | required |
flag.refundCredits | integer | required -9007199254740991–9007199254740991 |
flag.createdAt | string | required |
flag.decidedAt | string | null | required |
flag.id | string | required |
flag.attestationRef | string | required |
POST/v2/questions/{id}/answers/{ref}/pin
Pin an answer to the top of the results and the PDF report, or unpin it.
API key or OAuth token with questions:write.
| Field | Type | Notes |
|---|---|---|
pinned | boolean | required |
| Field | Type | Notes |
|---|---|---|
pinned | boolean | required |
GET/v2/questions/{id}/heatmap.png
A click test's heatmap as a transparent PNG to lay over the image. Add ?aspect=width/height to match it.
API key or OAuth token with questions:read.
POST/v2/questions/{id}/dispute
Dispute a result within 7 days of it closing.
API key or OAuth token with questions:write.
| Field | Type | Notes |
|---|---|---|
reason | string | required up to 2000 characters, at least 10 characters |
| Field | Type | Notes |
|---|---|---|
ok | true | required |
GET/v1/public/results/{code}
A result its requester made public.
No authentication.
| Field | Type | Notes |
|---|---|---|
question | object | required |
question.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
question.text | string | required up to 600 characters |
question.context | string | up to 120 characters |
question.language | string | required pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
question.options | object[] | required up to 8 items, default [] |
question.options[].label | string | required up to 40 characters |
question.options[].imageUrl | string (URL) | |
question.neither | boolean | required default false |
question.stimulus | object | |
question.stimulus.imageUrl | string (URL) | |
question.stimulus.audioUrl | string (URL) | |
question.stimulus.text | string | up to 120 characters |
question.stimulus.exposureMs | integer | 2000–10000 |
question.n | integer | required 10–5000, default 50 |
question.tier | 1 | 2 | 3 | required default 1 |
question.rush | boolean | required default false |
question.targeting | object | |
question.targeting.countries | string[] | required up to 50 items, default [] |
question.targeting.tags | string[] | required up to 20 items, default [] |
question.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
question.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
question.targeting.verifiedAge | boolean | |
question.clickTest | object | |
question.clickTest.maxTaps | integer | required 1–5, default 1 |
question.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
question.publicResults | boolean | required default false |
question.reason | "off" | "optional" | "required" | required default "off" |
question.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
question.id | string | required |
question.status | "draft" | "scheduled" | "live" | "complete" | "underfilled" | "cancelled" | "refused" | required |
question.source | "app" | "portal" | "api" | "mcp" | required |
question.answered | integer | required -9007199254740991–9007199254740991 |
question.creditsPerAnswer | integer | required -9007199254740991–9007199254740991 |
question.creditsReserved | integer | required -9007199254740991–9007199254740991 |
question.creditsSpent | integer | required -9007199254740991–9007199254740991 |
question.etaMinutes | integer | required -9007199254740991–9007199254740991 |
question.leaderLine | string | null | required |
question.refusedCategory | string | null | required |
question.publicCode | string | null | required |
question.createdAt | string | required |
question.liveAt | string | null | required |
question.closedAt | string | null | required |
question.teamId | string | null | |
question.askedBy | object | null | |
question.askedBy.id | string | required |
question.askedBy.name | string | null | required |
question.projectId | string | null | |
question.labels | string[] | |
question.archived | boolean | |
question.bookmarked | boolean | |
question.externalRef | string | null | |
result | object | required |
result.questionId | string | required |
result.status | "in_progress" | "complete" | "underfilled" | "cancelled" | required |
result.nRequested | integer | required -9007199254740991–9007199254740991 |
result.nAccepted | integer | required -9007199254740991–9007199254740991 |
result.distribution | object[] | required |
result.distribution[].option | string | required |
result.distribution[].count | integer | required -9007199254740991–9007199254740991 |
result.distribution[].share | number | required |
result.distribution[].averageRank | number | |
result.distribution[].appearances | integer | -9007199254740991–9007199254740991 |
result.distribution[].strength | number | |
result.distribution[].rank | integer | -9007199254740991–9007199254740991 |
result.mean | number | null | required |
result.summary | object | required |
result.summary.winner | string | null | required |
result.summary.margin | number | null | required |
result.summary.confidence | "low" | "medium" | "high" | null | required |
result.summary.note | string | required |
result.summary.suggestedFollowUp | string | null | required |
result.tier | integer | required -9007199254740991–9007199254740991 |
result.language | string | required |
result.verificationLine | string | required |
result.medianSeconds | number | null | required |
result.creditsSpent | integer | required -9007199254740991–9007199254740991 |
result.answers | object[] | required |
result.answers[].option | string | null | required |
result.answers[].text | string | null | required |
result.answers[].translatedText | string | null | |
result.answers[].reason | string | null | |
result.answers[].translatedReason | string | null | |
result.answers[].tier | integer | required -9007199254740991–9007199254740991 |
result.answers[].attestationRef | string | required |
result.answers[].answeredAt | string | required |
result.answers[].pinned | boolean | |
result.answers[].flag | object | null | |
result.answers[].taps | object[] | |
result.breakdown | object[] | |
result.breakdown[].tagId | string | required |
result.breakdown[].label | string | required |
result.breakdown[].n | integer | required -9007199254740991–9007199254740991 |
result.breakdown[].distribution | object[] | required |
result.refundCredits | integer | required -9007199254740991–9007199254740991 |
result.breakdowns | object[] | |
result.breakdowns[].dimension | "country" | "tier" | "age_band" | "gender" | "tag" | required |
result.breakdowns[].segments | object[] | required |
result.clicks | object | |
result.clicks.imageUrl | string | null | required |
result.clicks.taps | integer | required -9007199254740991–9007199254740991 |
result.clicks.points | object[] | required |
result.clicks.grid | integer[] | required |
result.clicks.gridSize | integer | required -9007199254740991–9007199254740991 |
result.clicks.hotspots | object[] | required |
result.clicks.heatmapUrl | string | null | required |
result.sentiment | object | |
result.sentiment.positive | number | required |
result.sentiment.neutral | number | required |
result.sentiment.negative | number | required |
result.translationLanguage | string | null | |
result.insights | object | null | |
result.insights.questionId | string | required |
result.insights.language | string | required |
result.insights.sourceLanguage | string | required |
result.insights.takeaway | string | required |
result.insights.themes | object[] | required up to 8 items |
result.insights.sentiment | object | required |
result.insights.basedOn | integer | required -9007199254740991–9007199254740991 |
result.insights.answersAtTime | integer | required -9007199254740991–9007199254740991 |
result.insights.original | object | null | required |
result.insights.kind | "interim" | "final" | required |
result.insights.generatedAt | string | required |
result.insights.refreshAfter | string | null | required |
result.insights.engine | string | required |
result.filter | object | |
result.filter.option | integer | 0–8 |
result.filter.tier | integer | 1–3 |
result.filter.country | object | |
result.filter.ageBand | string | pattern ^[0-9]{2}(-[0-9]{2}|\+)$ |
result.filter.gender | "woman" | "man" | "non_binary" | |
result.filter.q | string | up to 100 characters |
result.nUnfiltered | integer | -9007199254740991–9007199254740991 |
result.suppressed | boolean | |
result.facets | object | |
result.facets.tiers | object[] | required |
result.facets.countries | object[] | required |
result.facets.ageBands | object[] | required |
result.facets.genders | object[] |
Drafts and uploads
Save work in progress and upload images before you ask.
GET/v1/drafts
Saved drafts.
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
drafts | object[] | required |
drafts[].id | string | required |
drafts[].draft | object | required |
drafts[].draft.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
drafts[].draft.text | string | up to 600 characters |
drafts[].draft.context | string | up to 120 characters |
drafts[].draft.language | string | pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
drafts[].draft.options | object[] | up to 8 items, default [] |
drafts[].draft.neither | boolean | default false |
drafts[].draft.stimulus | object | |
drafts[].draft.n | integer | 10–5000, default 50 |
drafts[].draft.tier | 1 | 2 | 3 | default 1 |
drafts[].draft.rush | boolean | default false |
drafts[].draft.targeting | object | |
drafts[].draft.clickTest | object | |
drafts[].draft.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
drafts[].draft.publicResults | boolean | default false |
drafts[].draft.reason | "off" | "optional" | "required" | default "off" |
drafts[].draft.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
drafts[].updatedAt | string | required |
POST/v1/drafts
Save a draft. PUT /v1/drafts/{id} updates one; DELETE removes it.
API key or OAuth token with questions:write.
| Field | Type | Notes |
|---|---|---|
type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
text | string | up to 600 characters |
context | string | up to 120 characters |
language | string | pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
options | object[] | up to 8 items, default [] |
options[].label | string | required up to 40 characters |
options[].imageUrl | string (URL) | |
neither | boolean | default false |
stimulus | object | |
stimulus.imageUrl | string (URL) | |
stimulus.audioUrl | string (URL) | |
stimulus.text | string | up to 120 characters |
stimulus.exposureMs | integer | 2000–10000 |
n | integer | 10–5000, default 50 |
tier | 1 | 2 | 3 | default 1 |
rush | boolean | default false |
targeting | object | |
targeting.countries | string[] | up to 50 items, default [] |
targeting.tags | string[] | up to 20 items, default [] |
targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
targeting.verifiedAge | boolean | |
clickTest | object | |
clickTest.maxTaps | integer | 1–5, default 1 |
scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
publicResults | boolean | default false |
reason | "off" | "optional" | "required" | default "off" |
contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" |
| Field | Type | Notes |
|---|---|---|
id | string | required |
draft | object | required |
draft.type | "single_choice" | "multi_choice" | "ab_image" | "pairwise" | "scale_1_5" | "ranking" | "yes_mostly_no" | "free_text" | "click_test" | "reaction" | required |
draft.text | string | up to 600 characters |
draft.context | string | up to 120 characters |
draft.language | string | pattern ^[a-z]{2}(-[A-Z]{2})?$, default "en" |
draft.options | object[] | up to 8 items, default [] |
draft.options[].label | string | required up to 40 characters |
draft.options[].imageUrl | string (URL) | |
draft.neither | boolean | default false |
draft.stimulus | object | |
draft.stimulus.imageUrl | string (URL) | |
draft.stimulus.audioUrl | string (URL) | |
draft.stimulus.text | string | up to 120 characters |
draft.stimulus.exposureMs | integer | 2000–10000 |
draft.n | integer | 10–5000, default 50 |
draft.tier | 1 | 2 | 3 | default 1 |
draft.rush | boolean | default false |
draft.targeting | object | |
draft.targeting.countries | string[] | required up to 50 items, default [] |
draft.targeting.tags | string[] | required up to 20 items, default [] |
draft.targeting.ageBands | "18-24" | "25-34" | "35-44" | "45-54" | "55-64" | "65+"[] | up to 6 items |
draft.targeting.genders | "woman" | "man" | "non_binary"[] | up to 3 items |
draft.targeting.verifiedAge | boolean | |
draft.clickTest | object | |
draft.clickTest.maxTaps | integer | required 1–5, default 1 |
draft.scheduledFor | string (date-time) | pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$ |
draft.publicResults | boolean | default false |
draft.reason | "off" | "optional" | "required" | default "off" |
draft.contentFlag | "none" | "medical" | "violence" | "distressing" | "alcohol_gambling" | "political" | |
updatedAt | string | required |
POST/v1/uploads
A pre-signed URL to upload an image or sound clip.
API key or OAuth token with questions:write.
PUT the file to uploadUrl with the returned headers (the URL is the credential, for 15 minutes), then use publicUrl in the question. Images are checked and their metadata stripped before heads see them.
| Field | Type | Notes |
|---|---|---|
kind | "image" | "audio" | required |
contentType | string | required |
bytes | integer | required -9007199254740991–9007199254740991 |
| Field | Type | Notes |
|---|---|---|
uploadUrl | string | required |
publicUrl | string | required |
headers | map of string | required |
POST/v1/uploads/import
Copy an image from a public https link into 50heads.
API key or OAuth token with questions:write.
The image is fetched on our side (public https hosts only, three redirects at most), checked like an upload and stored. JPEG, PNG or WebP up to 5 MB.
| Field | Type | Notes |
|---|---|---|
url | string (URL) | required |
| Field | Type | Notes |
|---|---|---|
publicUrl | string | required |
width | integer | null | required |
height | integer | null | required |
Projects
Group questions into projects in the account the key belongs to (yours or a team's). Label, archive and give each question your own reference with the question routes.
GET/v1/projects
Projects in use, or the archived ones.
API key or OAuth token with questions:read.
| Field | Type | Notes |
|---|---|---|
archived | boolean |
| Field | Type | Notes |
|---|---|---|
projects | object[] | required |
projects[].id | string | required |
projects[].name | string | required |
projects[].description | string | null | required |
projects[].goal | string | null | required |
projects[].bookmarked | boolean | required |
projects[].archived | boolean | required |
projects[].questionCount | integer | required -9007199254740991–9007199254740991 |
projects[].createdAt | string | required |
projects[].updatedAt | string | required |
POST/v1/projects
Make a project.
API key or OAuth token with questions:write.
| Field | Type | Notes |
|---|---|---|
name | string | required up to 80 characters |
description | string | null | |
goal | string | null |
| Field | Type | Notes |
|---|---|---|
project | object | required |
project.id | string | required |
project.name | string | required |
project.description | string | null | required |
project.goal | string | null | required |
project.bookmarked | boolean | required |
project.archived | boolean | required |
project.questionCount | integer | required -9007199254740991–9007199254740991 |
project.createdAt | string | required |
project.updatedAt | string | required |
PATCH/v1/projects/{id}
Rename, bookmark or archive a project.
API key or OAuth token with questions:write.
| Field | Type | Notes |
|---|---|---|
name | string | up to 80 characters |
description | string | null | |
goal | string | null | |
bookmarked | boolean | |
archived | boolean |
| Field | Type | Notes |
|---|---|---|
project | object | required |
project.id | string | required |
project.name | string | required |
project.description | string | null | required |
project.goal | string | null | required |
project.bookmarked | boolean | required |
project.archived | boolean | required |
project.questionCount | integer | required -9007199254740991–9007199254740991 |
project.createdAt | string | required |
project.updatedAt | string | required |
DELETE/v1/projects/{id}
Delete a project. Its questions stay, outside any project.
API key or OAuth token with questions:write.
| Field | Type | Notes |
|---|---|---|
ok | true | required |
Credits
Balance and ledger. Credits are bought on the web; the API spends them.
GET/v1/billing/balance
Credits, what is reserved by live questions, and what is left under this key's daily cap.
API key or OAuth token with account:read.
| Field | Type | Notes |
|---|---|---|
credits | integer | required -9007199254740991–9007199254740991 |
reserved | integer | required -9007199254740991–9007199254740991 |
expiring | object[] | required |
expiring[].credits | integer | required -9007199254740991–9007199254740991 |
expiring[].expiresAt | string | required |
currency | "GBP" | "USD" | "EUR" | "CAD" | required |
capRemaining | integer | null | required |
freeQuestionToday | boolean | required |
GET/v1/billing/ledger
Every credit movement, newest first.
API key or OAuth token with account:read.
| Field | Type | Notes |
|---|---|---|
cursor | string |
| Field | Type | Notes |
|---|---|---|
rows | object[] | required |
rows[].id | string | required |
rows[].at | string | required |
rows[].kind | "purchase" | "ask" | "refund" | "say" | "bonus" | "referral" | "payout" | "payout_returned" | "fee" | "expiry" | "clawback" | "adjustment" | "tier2_fee" | "not_paid" | required |
rows[].title | string | required |
rows[].state | "pending" | "available" | "in_flight" | "paid" | "reversed" | "not_paid" | required |
rows[].amount | integer | required -9007199254740991–9007199254740991 |
rows[].ref | string | null | required |
rows[].notPaid | object | null | |
rows[].notPaid.id | string | required |
rows[].notPaid.source | "rejected" | "clawback" | required |
rows[].notPaid.reason | "too_fast" | "repeat" | "check_question" | "automated" | "linked_accounts" | "shared_payout_method" | "confirmed_fraud" | required |
rows[].notPaid.amount | integer | required -9007199254740991–9007199254740991 |
rows[].notPaid.status | "not_paid" | "appealed" | "upheld" | "not_upheld" | required |
rows[].notPaid.appealBy | string | null | required |
rows[].notPaid.decisionBy | string | null | required |
rows[].by | string | null | |
rows[].releaseAt | string | null | |
nextCursor | string | null | required |
POST/v1/billing/checkout
Start a card or bank-transfer purchase (portal session only).
Portal session only.
Not available to API keys: buying credits needs a signed-in person.
| Field | Type | Notes |
|---|---|---|
pack | string | required |
currency | "GBP" | "USD" | "EUR" | "CAD" | required |
method | "card" | "bank_transfer" | required |
returnPath | string | pattern ^\/app(\/[\w\-/]*)?$ |
Support
Open a ticket from a script or an agent. Replies come by email and in the portal.
POST/v1/support/tickets
Open a support ticket.
API key or OAuth token.
Signed in (key, OAuth or session), the reply goes to the account's email. Without a token, send email. 10 tickets an hour.
| Field | Type | Notes |
|---|---|---|
subject | string | required up to 140 characters, at least 3 characters |
body | string | required up to 5000 characters, at least 10 characters |
appVersion | string | up to 40 characters |
category | "payout" | "payout_failed" | "account" | "account_frozen" | "verification" | "question" | "billing" | "api" | "security" | "privacy" | "other" | |
email | string (email) | pattern ^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$ |
locale | string | up to 10 characters |
| Field | Type | Notes |
|---|---|---|
ticketId | string | required |
Webhook endpoints
Managed in the portal under Developers; listed here for completeness.
GET/v1/webhooks/endpoints
Your webhook endpoints.
Portal session only.
| Field | Type | Notes |
|---|---|---|
endpoints | object[] | required |
endpoints[].id | string | required |
endpoints[].url | string (URL) | required |
endpoints[].events | "question.reserved" | "question.completed" | "question.underfilled" | "question.cancelled" | "question.refused" | "credits.purchased" | "credits.low" | "credits.expiring" | "dispute.resolved" | "connection.cap_warning"[] | required |
endpoints[].secret | string | required |
endpoints[].createdAt | string | required |
endpoints[].lastDeliveryAt | string | null | required |
endpoints[].lastStatus | integer | null | required |
endpoints[].description | string | null | |
endpoints[].enabled | boolean | |
endpoints[].disabledReason | string | null | |
endpoints[].lastSuccessAt | string | null |
POST/v1/webhooks/endpoints
Add an endpoint. The secret is shown once.
Portal session only.
| Field | Type | Notes |
|---|---|---|
url | string (URL) | required |
events | "question.reserved" | "question.completed" | "question.underfilled" | "question.cancelled" | "question.refused" | "credits.purchased" | "credits.low" | "credits.expiring" | "dispute.resolved" | "connection.cap_warning"[] | required |
| Field | Type | Notes |
|---|---|---|
endpoint | object | required |
endpoint.id | string | required |
endpoint.url | string (URL) | required |
endpoint.events | "question.reserved" | "question.completed" | "question.underfilled" | "question.cancelled" | "question.refused" | "credits.purchased" | "credits.low" | "credits.expiring" | "dispute.resolved" | "connection.cap_warning"[] | required |
endpoint.secret | string | required |
endpoint.createdAt | string | required |
endpoint.lastDeliveryAt | string | null | required |
endpoint.lastStatus | integer | null | required |
endpoint.description | string | null | |
endpoint.enabled | boolean | |
endpoint.disabledReason | string | null | |
endpoint.lastSuccessAt | string | null |