---
name: sales-ditto
description: "Ditto (askditto.io) platform help — self-serve synthetic market research with 300,000+ census-calibrated AI personas across 15+ countries, run via a real REST API (Bearer auth, free-tier keys) and official Claude Code skills: recruit demographic research groups, launch studies, ask questions, poll async jobs, then get an AI analysis + shareable link. Use when setting up a Ditto research group or study, running a pricing or concept test against synthetic personas, filtering panels by country/state/age, getting a free-tier API key, wiring the recruit-to-study-to-analysis flow into Claude Code or a pipeline, hitting the 20-personas-per-recruit or sequential-questions limits, or deciding whether a synthetic 'yes' is real demand. Do NOT use for comparing synthetic-research, persona, or idea-validation tools across the market (use /sales-idea-validation) or analyzing real-customer NPS/VoC feedback (use /sales-customer-feedback)."
argument-hint: "[describe what you need help with in Ditto]"
license: MIT
version: 1.0.0
tags: [sales, pre-launch, platform]
github: "https://github.com/Ask-Ditto"
---

# Ditto Platform Help

Ditto (askditto.io) is a **self-serve synthetic market research** platform: recruit a
demographically filtered panel from **300,000+ census-calibrated AI personas** (across 15+
countries), run a **study**, ask questions, and get an **AI analysis** — in minutes instead of the
weeks/thousands a traditional focus group costs. Its edge in the synthetic-research cluster is a
**real REST API with a free-tier key** plus **official Claude Code skills**, so an agent can drive
the whole recruit → study → analysis flow. EY-validated at a **92% overlap** with focus groups (a
vendor-cited figure).

Its signal is **directional, not demand**: personas model existing/census/training data, so they
skew **agreeable, generic, and Western-biased** and can't surface a genuinely *new* unmet need.
Treat any synthetic result as a **hypothesis to disconfirm with real behavior**, never a green light.

## Step 1 — Gather context

If `references/learnings.md` exists, read it first for accumulated platform knowledge.

Ask only what you can't infer:

1. **What do you want from Ditto?**
   - A) **Recruit** a research group (demographic panel) — filter by country/state/age
   - B) **Run a study** — launch, ask questions, get the AI analysis + share link
   - C) **Automate** it — drive the recruit → study → questions → analysis flow via the API/Claude Code
   - D) **Get access** — a free-tier (`rk_free_`) key vs a paid (`rk_live_`) key with real filtering
   - E) **Interpret** a study/analysis you already ran, or decide **whether to trust it**
2. **What's the research question and who's the audience?** A sharp objective + panel yields usable
   answers; a vague one yields generic filler.

Skip-ahead: if the user wants to **compare** synthetic-research/persona/idea tools across the market,
or the validate-before-building *method*, that's a `/sales-idea-validation` question — route in Step 2.

## Step 2 — Route or answer directly

| If the user's question is about… | Route to |
|---|---|
| Comparing synthetic-research/persona/idea tools, or the validate-before-building **method** | `/sales-idea-validation {question}` |
| Running a **real** demand test (smoke-test page, waitlist, pre-sale) after synthetic signal | `/sales-idea-validation` or `/sales-funnel` `{question}` |
| Analyzing **real-customer** NPS/CSAT/VoC feedback (post-launch) | `/sales-customer-feedback {question}` |
| The pure-play interview-study API peer, or a **reusable persona with memory** | `/sales-syntheticusers` or `/sales-imario` `{question}` |

When routing, give the exact command: "This is a {domain} question — run: `/sales-idea-validation {original question}`"

Otherwise, answer Ditto-specific questions using Step 3.

## Step 3 — Ditto platform reference

**Read `references/platform-guide.md`** for the full reference — the module/automation-surface table
(what's API-accessible vs UI-only), best-effort pricing and the free-vs-paid key gates, the
Group → Study → Question → Analysis data model (JSON shapes), and quick-start recipes.

For raw endpoints, auth, JSON schemas, and the end-to-end Python script, read
`references/ditto-api-reference.md`.

Answer using only the relevant section — don't dump the full reference.

## Step 4 — Actionable guidance

- **A synthetic "yes" is not demand — say so every time.** Whatever the user asks, make explicit that
  Ditto's personas model census/existing/training data, so they run **agreeable, generic, and
  Western-biased** and can be **confidently wrong**. Frame every result as a **hypothesis to
  disconfirm with a real behavior test** (smoke-test click, reply, pre-sale) — keep the *objections,
  segments, and language* it surfaces (its real value), take the go/no-go from real strangers, and
  route the real test to `/sales-idea-validation`.
- **Present the EY "92% overlap" and all pricing as best-effort — cite the source, don't assert it.**
  The 92%-overlap-with-focus-groups figure is **EY-validated but vendor-cited**; paid pricing is
  **not publicly listed** (third-party sources cite an enterprise ~$50–75K/yr range). Say figures are
  best-effort and point the user to askditto.io to confirm before relying on them.
- **Start on the free tier, name its limits.** A `rk_free_` key (`free-tier-auth.sh`) gives ~**12
  shared US personas with no custom filters** — enough to build/debug the flow and read directional
  patterns. **Custom demographic filtering (country/state/age) needs a paid `rk_live_` key.** Tell
  the user to prototype on free, then upgrade only when they need real filtering — the request shapes
  are identical.
- **For automation, give the real endpoints and the hard limits.** Base **`https://app.askditto.io`**,
  auth **`Authorization: Bearer <key>`**. Core flow: `POST /v1/research-groups/recruit` → `POST
  /v1/research-studies` (set `shareable:true`, pass the group **`uuid`** not the numeric `id`) → `POST
  /v1/research-studies/{id}/questions` → poll **every** `job_id` via `GET /v1/jobs/{id}` to `finished`
  → repeat per question → `POST .../complete` → `POST .../share`. Enforce the limits: **questions are
  sequential** (poll all jobs before the next — no concurrency), **max 20 personas per recruit call**
  (use `/append`), **`group_size` not `size`**, **2-letter state codes**, **no income filter**, and
  **no webhooks** (job polling only). Pull a concrete cURL/Python snippet from the references.
- **Sharpen the panel and objective — output tracks input.** A vague audience or objective yields
  generic filler; recommend **over-recruit-and-curate** (recruit/`append` a wider panel, `GET` the
  profiles, `POST /agents/remove` the misfits) and a specific objective before asking questions.

If you discover a gotcha or tip not in `references/learnings.md`, append it there with today's date.

## Gotchas

*Best-effort from research (2026-07) — pricing, the EY figure, persona counts/countries, and the API
surface move; verify at askditto.io and app.askditto.io/docs.*

- **Sycophancy / agreeableness bias.** Personas skew *favorable* — they can approve a concept or
  price real buyers would reject. Never read a positive synthetic reaction as validation.
- **Census-calibrated ≠ real behavior.** "Population-true" personas match demographic *distributions*,
  not the messy, unpredictable choices of a real person — and they can't surface a *new* unmet need.
- **Western/English and identity-flattening bias.** Outputs skew Western/majority and can flatten
  identity groups — be cautious generalizing across markets or narrow segments.
- **Free tier is deliberately thin.** `rk_free_` = ~12 **shared** personas, **no custom filters** —
  demographic filtering requires a paid `rk_live_` key. Don't promise country/state/age targeting on free.
- **Sequential questions + job polling.** The API rejects concurrent questions; each question fans out
  to one async job per persona. Poll **all** job_ids to `finished` (30–90s typical) before the next.
- **Field/format traps.** `group_size` (not `size`); use the group **`uuid`** (not `id`) for studies;
  **2-letter** state codes; **no income filter**; `response_text` may contain HTML to strip.

## Related skills

- `/sales-idea-validation` — The tool-agnostic validate-before-building method + the full synthetic-research/persona/validator tool landscape (use this to actually decide build-or-not; a synthetic "yes" is not demand)
- `/sales-syntheticusers` — Synthetic Users platform help (the pure-play interview-study peer with a documented public REST API [Python/TS SDKs, SSE streaming]; Ditto's edge is census-calibrated demographic panels + a free-tier key + official Claude Code skills)
- `/sales-imario` — iMario platform help (the reusable-persona canvas — a Synthetic Individual with cross-session memory run across six jobs; Ditto runs one-shot demographic studies but ships the real free-tier API)
- `/sales-societies` — Artificial Societies platform help (the self-serve network simulator that predicts how a post/message spreads; Ditto asks isolated personas, Societies models influence between them)
- `/sales-customer-feedback` — Real-customer NPS/CSAT/VoC strategy across tools (use once you have live customers; synthetic research is pre-launch only)
- `/sales-funnel` — Build the smoke-test / fake-door landing page that turns a synthetic hypothesis into a real demand test
- `/sales-do` — Not sure which skill to use? The router matches any sales objective to the right skill. Install: `npx skills add sales-skills/sales --skill sales-do -a claude-code`

## Examples

### Example 1: "Ditto's personas loved my pricing — should I ship it?"
**User says**: "I ran a Ditto study and 9 of 10 personas said $29/mo is fair. Green light?"
**Skill does**: Explains Ditto's personas **model census/training data and skew agreeable**, so a
near-unanimous "yes" is a **directional signal, not demand** — census-calibration matches
*distributions*, not real purchase behavior. Tells the user to **mine the answers for objections and
price language** (the real value) and take the go/no-go from a **real behavior test** — a pre-sale or
a "buy at $29" click — routed via `/sales-idea-validation`. Flags the **EY 92% overlap** claim as
vendor-cited.
**Result**: The founder keeps the pricing objections, runs a real pre-sale before committing.

### Example 2: Free vs paid — can I filter by demographics? (references/platform-guide.md)
**User says**: "I want US women 25–34 in Texas. Does the free Ditto key do that?"
**Skill does**: Says **no** — a `rk_free_` key is ~**12 shared US personas with no custom filters**;
**country/state/age filtering needs a paid `rk_live_` key**. Explains how to get the free key
(`free-tier-auth.sh`) to build the flow, then upgrade; notes the recruit constraints (**country
required, 2-letter state like "TX", no income filter, max 20 per call**) and that pricing is
best-effort/enterprise — confirm on askditto.io.
**Result**: The user prototypes on free, understands filtering is a paid gate, and budgets accordingly.

### Example 3: Automate a study end-to-end from Claude Code (developer/automation)
**User says**: "How do I recruit a panel, ask 3 questions, and export the analysis via the API?"
**Skill does**: Gives the flow — auth `Authorization: Bearer <key>`, base `https://app.askditto.io`;
`POST /v1/research-groups/recruit` → `POST /v1/research-studies` (`shareable:true`, group **uuid**) →
`POST /v1/research-studies/{id}/questions` **one at a time**, polling **every** `job_id` via
`GET /v1/jobs/{id}` to `finished` before the next → `POST .../complete` → `POST .../share`. Stresses
**no webhooks** (job polling only), **max 20 personas/recruit** (use `/append`), and points to the
Python script in `references/ditto-api-reference.md`; mentions the official Ask-Ditto Claude Code skills.
**Result**: The user wires the recruit → study → analyze → export flow with sequential polling, no webhooks.

## Troubleshooting

### "The personas agreed with everything — is that real signal?"
**Symptom**: Study answers are uniformly positive and agreeable.
**Cause**: LLM-based personas exhibit **sycophancy** and model plausible agreement — census
calibration fixes *who* they are, not the agreeableness bias.
**Solution**: Discard the "verdict," keep the **objections and language** surfaced, and validate with
**real behavior** (smoke test, pre-sale). Sharpen the objective and panel (over-recruit-and-curate) to
cut generic agreement. Cross-check via `/sales-idea-validation`.

### "My recruit call keeps 400-ing / the filter isn't applied"
**Symptom**: `POST /research-groups/recruit` returns 400/422, or the free key ignores your filters.
**Cause**: Wrong field name or format (`size` instead of `group_size`, "Texas" instead of "TX", an
`income` filter), missing required `country`, or a **free `rk_free_` key** (no custom filters — shared
personas only).
**Solution**: Use `group_size`, include `country`, use **2-letter** state codes, drop `income`, and
cap at **20 personas** (use `/append` for more). For real demographic filtering, use a paid `rk_live_`
key. See `references/ditto-api-reference.md`.

### "My study never 'finishes' — how do I know the answers are in?"
**Symptom**: After `POST .../questions` the responses aren't there and nothing calls back.
**Cause**: Responses are **async** (one job per persona) and there are **no webhooks**.
**Solution**: **Poll** `GET /v1/jobs/{job_id}` for **every** returned `job_id` until each shows
`finished` (30–90s typical, poll every 10–15s) **before** asking the next question, then `GET
/v1/research-studies/{id}/questions` to read answers and `POST .../complete` for the AI analysis.
