---
title: "Ask a question."
method: POST
path: "/v2/questions"
tags: ["questions"]
---

# Ask a question.

`POST /v2/questions`

## Request

- Base URL: `https://api.50heads.com`
- URL: `https://api.50heads.com/v2/questions`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://auth.50heads.com/authorize`, token URL `https://auth.50heads.com/token`; client credentials, token URL `https://auth.50heads.com/token`, scopes: `questions:write`)

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_reached` or `content_refused` without spending anything. The portal and app are reminded once with `422 quality_reminder` (nothing stored or charged) when the wording review has a strong suggestion the writer has not taken; ask again with `acknowledgeQuality: true` and the same key to send it as written. The API and MCP are never reminded.

## Headers

- `Idempotency-Key` string, required

## Request body

- AskRequest
  - `draft` QuestionDraft, required
    - `type` 'single_choice' | 'multi_choice' | 'ab_image' | 'pairwise' | 'scale_1_5' | 'ranking' | 'yes_no' | 'yes_mostly_no' | 'free_text' | 'click_test' | 'reaction' | 'rate_each', required
    - `text` string, required
    - `context` string
    - `language` string
    - `options` object[]
      - `label` string, required
      - `imageUrl` string, uri
      - `imageUrls` string[]
    - `scaleLabels` object
      - `low` string, required
      - `high` string, required
    - `neither` boolean
    - `stimulus` object
      - `imageUrl` string, uri
      - `audioUrl` string, uri
      - `text` string
      - `exposureMs` integer
    - `n` integer
    - `tier` union
      - 1
      - 2
      - 3
    - `rush` boolean
    - `targeting` object
      - `countries` string[]
      - `tags` string[]
      - `ageBands` string[]
      - `genders` string[]
      - `verifiedAge` boolean
    - `clickTest` object
      - `maxTaps` integer
    - `scheduledFor` string, date-time
    - `publicResults` boolean
    - `reason` 'off' | 'optional' | 'required'
    - `goRule` object
      - `goAbove` number, required
      - `minAnswers` integer, required
    - `contentFlag` 'none' | 'medical' | 'violence' | 'distressing' | 'alcohol_gambling' | 'political'
    - `interestAudienceId` string
    - `minGrade` union
      - 1
      - 2
      - 3
    - `interestPrice` object
      - `perAnswerPence` integer, required
      - `headShareBps` integer, required
    - `answeredBy` 'heads' | 'private'
    - `openForDays` union
      - 1
      - 7
      - 14
      - 30
    - `shownAs` string
  - `fromDraftId` string
  - `then` object[]
    - `type` 'single_choice' | 'multi_choice' | 'ab_image' | 'pairwise' | 'scale_1_5' | 'ranking' | 'yes_no' | 'yes_mostly_no' | 'free_text' | 'click_test' | 'reaction' | 'rate_each'
    - `text` string, required
    - `options` object[]
      - `label` string, required
      - `imageUrl` string, uri
      - `imageUrls` string[]
    - `n` integer
    - `tier` union
      - 1
      - 2
      - 3
    - `minConfidence` 'low' | 'medium' | 'high'
    - `reason` 'off' | 'optional' | 'required'
  - `variantOf` string
  - `followUpOf` string
  - `templateId` string
  - `projectId` string, nullable
  - `labels` string[]
  - `externalRef` string
  - `privateDeclaration` object
    - `version` integer, required
  - `acknowledgeQuality` boolean

## Response `201`

OK

- AskResponse
  - `question` QuestionV2, required
    - `type` 'single_choice' | 'multi_choice' | 'ab_image' | 'pairwise' | 'scale_1_5' | 'ranking' | 'yes_no' | 'yes_mostly_no' | 'free_text' | 'click_test' | 'reaction' | 'rate_each', required
    - `text` string, required
    - `context` string
    - `language` string, required
    - `options` object[], required
      - `label` string, required
      - `imageUrl` string, uri
      - `imageUrls` string[]
    - `scaleLabels` object
      - `low` string, required
      - `high` string, required
    - `neither` boolean, required
    - `stimulus` object
      - `imageUrl` string, uri
      - `audioUrl` string, uri
      - `text` string
      - `exposureMs` integer
    - `n` integer, required
    - `tier` union, required
      - 1
      - 2
      - 3
    - `rush` boolean, required
    - `targeting` object
      - `countries` string[], required
      - `tags` string[], required
      - `ageBands` string[]
      - `genders` string[]
      - `verifiedAge` boolean
    - `clickTest` object
      - `maxTaps` integer, required
    - `scheduledFor` string, date-time
    - `publicResults` boolean, required
    - `reason` 'off' | 'optional' | 'required', required
    - `goRule` object
      - `goAbove` number, required
      - `minAnswers` integer, required
    - `contentFlag` 'none' | 'medical' | 'violence' | 'distressing' | 'alcohol_gambling' | 'political'
    - `interestAudienceId` string
    - `minGrade` union
      - 1
      - 2
      - 3
    - `interestPrice` object
      - `perAnswerPence` integer, required
      - `headShareBps` integer, required
    - `answeredBy` 'heads' | 'private', required
    - `openForDays` union, required
      - 1
      - 7
      - 14
      - 30
    - `shownAs` string
    - `id` string, required
    - `status` 'draft' | 'scheduled' | 'live' | 'complete' | 'underfilled' | 'canceled' | 'refused' | 'pending_approval' | 'closed', required
    - `source` 'app' | 'portal' | 'api' | 'mcp', required
    - `answered` integer, required
    - `creditsPerAnswer` integer, required
    - `creditsReserved` integer, required
    - `creditsSpent` integer, required
    - `etaMinutes` integer, required
    - `leaderLine` string, nullable, required
    - `refusedCategory` string, nullable, required
    - `publicCode` string, nullable, required
    - `createdAt` string, required
    - `liveAt` string, nullable, required
    - `closedAt` string, nullable, required
    - `teamId` string, nullable
    - `askedBy` object, nullable
      - `id` string, required
      - `name` string, nullable, required
    - `projectId` string, nullable
    - `labels` string[]
    - `archived` boolean
    - `bookmarked` boolean
    - `externalRef` string, nullable
    - `link` object, nullable
      - `url` string, required
      - `qrSvgUrl` string, required
      - `qrPngUrl` string, required
      - `closesAt` string, nullable, required
      - `views` integer, required
      - `started` integer, required
    - `setId` string, nullable
    - `setPosition` integer, nullable
    - `setCount` integer, nullable

## Other responses

- `202`: An approval policy holds this ask: `code: approval_required`. Its credits are held (nothing is spent) and nothing reaches heads until an approver decides. Read the outcome with GET /v1/approvals/{id}, or wait on the question; the same Idempotency-Key answers 202 again while it waits.
- `400`: The request is not valid; `error.details.validation` lists the fixes.
- `401`: No key or token, or it expired or was revoked.
- `402`: `insufficient_credits` or `spend_cap_reached`; nothing was spent.
- `403`: The key or token lacks the scope (`insufficient_scope`), or the action is not allowed.
- `409`: `idempotency_conflict`: that key was used for a different question.
- `429`: Too many requests; wait for Retry-After.

---

[API](https://skmtc.dev/50heads/apis/50heads-api.md) · [All operations](https://skmtc.dev/50heads/apis/50heads-api/llms.txt) · [OpenAPI document](https://skmtc.dev/50heads/apis/50heads-api/revisions/20175e8b00e3?raw)
