Skip to content

People who answered X but never bought

Goal: the people who told the quiz they have dry skin (any answer you pick), finished it, and never bought, as a count against the buyers who answered the same, and as a list you can write to.

Uses: People search with a choice term, has_order and match: latest_completed_per_quiz. Scope: profiles:read.

Two calls with the same term: has_order: false for the people to write to (with has_marketing_consent: true), has_order: true for the buyers. match: latest_completed_per_quiz reads only each person’s latest completed run, so a retake that changed the answer moves them.

Terminal window
curl -X POST "https://api.octaneai.com/v1/profiles/search?limit=100" \
-H "Authorization: Bearer $OCTANE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"has_order": false,
"has_marketing_consent": true,
"match": "latest_completed_per_quiz",
"groups": [{ "all": [
{ "quiz_id": "quiz_7c9e6679742540de944be07fc1f90ae7", "kind": "choice", "op": "in", "page_key": "skin", "component_key": "image_choice-48su5", "option_labels": ["Dry"] }
] }]
}'

Errors to handle

StatusWhyWhat to do
403 insufficient_scopeThe key lacks profiles:read.Mint a key with the scope.
404 not_foundThe quiz_id is not this store’s or was deleted.Re-list with GET /v1/quizzes.
422 validation_errorAn unknown option label (errors[] lists the legal ones: one of: Combo, Dry), an unknown question (“the quiz has no such question”), or “The search took too long; narrow the filter”.Read the keys off GET /v1/quizzes/{quiz_id}/analytics/answers; for the timeout add from/to or run the body as an export.
429 rate_limitedTwo searches at 6 units each, or all 15 search slots busy.Sleep for Retry-After seconds.

Things to know

  • has_order: false means no order Octane AI linked to a quiz session. A person who bought without the quiz knowing (a different email at checkout, a purchase before the quiz existed) counts as a non-buyer here. Treat the count as “no attributed order”, and let your messaging tool’s own purchase data exclude known customers if that matters.
  • Labels or ids. option_labels are matched trim- and case-insensitively across the quiz’s published versions, so a renamed option still finds its old answers; option_ids is exact. Where the keys come from: GET /v1/quizzes/{quiz_id}/analytics/answers lists the questions with page_key, component_key and every option’s option_id and label.
  • Latest run wins. With match: latest_completed_per_quiz someone who answered Dry in June and Oily yesterday is out of both counts; the default any_session would keep them in.
  • Two counts, two searches. The buyer count is only there to size the opportunity (“1,155 of the people who said Dry bought”); total is exact to 5,000 and reads “5,000 or more” past that, so a share computed from a capped number is a floor.
  • Consent is the capture-time checkbox. has_marketing_consent is the checkbox beside the newest email or phone they gave; the list goes into a tool that honours current subscription status, it is not a send list on its own.
  • A cohort to write to in bulk is an export: the same groups, has_order, has_marketing_consent and match on POST /v1/exports with dataset: "profiles" build the whole file with every person’s answers.