> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Persona Interview Marathon

> Use Speak to have voice conversations with 5 different personas about your positioning — rapid persona interviewing without recruitment or scheduling

## The Scenario

You need qualitative positioning feedback from five distinct audience segments — but you don't have three weeks for recruitment, incentive budgets, or a moderator. With Mavera's Speak surface, you have live voice conversations with AI personas, probe their reactions in real time, and extract structured insights. Five personas, five conversations, one afternoon.

<Info>
  **Mavera-only workflow.** No recruitment platforms, no incentive payments, no scheduling tools. Just Mavera's Personas, Speak, and Chat surfaces.
</Info>

***

## When to Use This

* Early-stage positioning validation with 2–3 hypotheses that need gut-checks.
* Founder-led discovery — practice your pitch with synthetic personas before real prospects.
* Message hierarchy testing — which proof points resonate first with each segment?
* Pre-launch readiness — talk to 5 ICP segments and capture objections.

***

## Architecture

```mermaid theme={"dark"}
flowchart LR
    A["Create Personas"] --> B["Start Speak Sessions"]
    B --> C["Conduct Interviews"]
    C --> D["Extract Insights"]
    D --> E["Report"]
```

| Mavera Surface                  | Role in Pipeline                               |
| ------------------------------- | ---------------------------------------------- |
| **Personas** (`POST /personas`) | Create 5 ICP personas with distinct priorities |
| **Speak** (`POST /speak`)       | Open voice conversation sessions               |
| **Chat** (OpenAI-compatible)    | Extract structured insights from transcripts   |

***

## What You Need

| Requirement                        | Details                                                                                              |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------- |
| **Mavera API key**                 | Starts with `mvra_live_`. Get one at [Developer Settings](https://app.mavera.io/settings/developer). |
| **Python 3.8+** or **Node.js 18+** | `requests`/`openai` for Python; native `fetch` for Node.                                             |
| **Credits**                        | \~115–265 total. See [Credits Estimate](#credits-estimate).                                          |

```
MAVERA_API_KEY=mvra_live_your_key_here
```

***

## Step 1 — Create 5 ICP Personas

<CodeGroup>
  ```python Python theme={"dark"}
  import os, time, json, requests

  API_KEY = os.environ["MAVERA_API_KEY"]
  BASE = "https://app.mavera.io/api/v1"
  HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

  PERSONAS = [
      {"name": "Elena — SaaS Marketing Director", "role": "Marketing Director, 200-person B2B SaaS",
       "description": "Manages team of 8. Spending $40K/quarter on research agencies. Frustrated by slow turnaround. Needs HubSpot integration and 90-day ROI.",
       "traits": ["ROI-focused", "time-pressed", "integration-demanding", "data-driven"]},
      {"name": "Raj — E-commerce Founder", "role": "Founder & CEO, DTC brand ($5M ARR)",
       "description": "Bootstrapped, writes ad copy personally. Audience is millennial women 25–34. Relies on gut instinct and A/B testing. Budget-conscious but invests for ROAS.",
       "traits": ["scrappy", "gut-instinct-driven", "ROAS-obsessed", "hands-on"]},
      {"name": "Dr. Amara — Healthcare Comms Lead", "role": "Director of Communications, hospital network",
       "description": "Navigates HIPAA compliance and health literacy. Content for diverse populations with varying reading levels. Multiple compliance review cycles.",
       "traits": ["compliance-aware", "patient-first", "health-literacy-focused", "risk-averse"]},
      {"name": "Marcus — Agency Creative Director", "role": "Creative Director, mid-size ad agency",
       "description": "Oversees 12 clients in CPG, fintech, retail. Team of 15. Constantly pitching new business. AI-curious but skeptical about quality vs human creativity.",
       "traits": ["quality-obsessed", "client-facing", "AI-curious-but-skeptical", "pitch-driven"]},
      {"name": "Keiko — Enterprise Product Manager", "role": "Senior PM, Fortune 500 tech company",
       "description": "Platform with 10K+ enterprise customers. Validates feature positioning before engineering invests. Currently uses slow customer advisory boards and lagging NPS surveys.",
       "traits": ["analytical", "consensus-builder", "evidence-driven", "launch-velocity-focused"]},
  ]

  def create_persona(p):
      resp = requests.post(f"{BASE}/personas", headers=HEADERS, json={
          "name": p["name"], "role": p["role"], "description": p["description"], "traits": p["traits"]})
      resp.raise_for_status()
      data = resp.json()
      print(f"  Created: {data['name']} → {data['id']}")
      return data["id"]

  persona_ids = {}
  for p in PERSONAS:
      persona_ids[p["name"].split(" — ")[0]] = create_persona(p)
  ```

  ```javascript JavaScript theme={"dark"}
  const API_KEY = process.env.MAVERA_API_KEY;
  const BASE = "https://app.mavera.io/api/v1";
  const HEADERS = { Authorization: `Bearer ${API_KEY}`, "Content-Type": "application/json" };

  const PERSONAS = [
    { name: "Elena — SaaS Marketing Director", role: "Marketing Director, 200-person B2B SaaS",
      description: "Team of 8. $40K/quarter on agencies. Needs HubSpot integration and 90-day ROI.",
      traits: ["ROI-focused", "time-pressed", "integration-demanding", "data-driven"] },
    { name: "Raj — E-commerce Founder", role: "Founder & CEO, DTC brand ($5M ARR)",
      description: "Bootstrapped, writes ad copy. Audience: millennial women 25–34. ROAS-obsessed.",
      traits: ["scrappy", "gut-instinct-driven", "ROAS-obsessed", "hands-on"] },
    { name: "Dr. Amara — Healthcare Comms Lead", role: "Director of Communications, hospital network",
      description: "HIPAA compliance, health literacy. Diverse populations, multiple review cycles.",
      traits: ["compliance-aware", "patient-first", "health-literacy-focused", "risk-averse"] },
    { name: "Marcus — Agency Creative Director", role: "Creative Director, mid-size agency",
      description: "12 clients, team of 15. Constantly pitching. AI-curious but quality-skeptical.",
      traits: ["quality-obsessed", "client-facing", "AI-curious-but-skeptical", "pitch-driven"] },
    { name: "Keiko — Enterprise Product Manager", role: "Senior PM, Fortune 500 tech",
      description: "10K+ customers. Validates positioning before eng invests. Slow advisory boards.",
      traits: ["analytical", "consensus-builder", "evidence-driven", "launch-velocity-focused"] },
  ];

  async function createPersona(p) {
    const resp = await fetch(`${BASE}/personas`, { method: "POST", headers: HEADERS,
      body: JSON.stringify({ name: p.name, role: p.role, description: p.description, traits: p.traits }) });
    const data = await resp.json();
    if (data.error) throw new Error(data.error.message);
    return data.id;
  }

  const personaIds = {};
  for (const p of PERSONAS) personaIds[p.name.split(" — ")[0]] = await createPersona(p);
  ```
</CodeGroup>

***

## Step 2 — Define Interview Script

Seven phases from opening reaction through pricing to a closing suggestion. Consistent across all 5 interviews.

<CodeGroup>
  ```python Python theme={"dark"}
  POSITIONING = """
  Mavera is an AI-powered audience research platform that lets marketing teams
  test messaging, positioning, and creative with synthetic personas in minutes
  instead of weeks. No recruitment, no scheduling, no incentive budgets.
  """

  INTERVIEW_SCRIPT = [
      {"phase": "Opening", "prompt": f"React to this positioning:\n\n{POSITIONING}\n\nGut reaction?"},
      {"phase": "Comprehension", "prompt": "In your own words, what does this product do? Who is it for?"},
      {"phase": "Relevance", "prompt": "How relevant is this to your daily work? Give a specific recent example."},
      {"phase": "Differentiation", "prompt": "What alternatives do you use today? How does this compare?"},
      {"phase": "Objections", "prompt": "If someone pitched this to you, what's your first concern?"},
      {"phase": "Pricing", "prompt": "What would you expect to pay? What feels fair vs too expensive?"},
      {"phase": "Closing", "prompt": "One thing you'd change about how this product is described?"},
  ]
  ```

  ```javascript JavaScript theme={"dark"}
  const POSITIONING = `Mavera is an AI-powered audience research platform that lets marketing teams test messaging with synthetic personas in minutes instead of weeks. No recruitment, no scheduling.`;

  const INTERVIEW_SCRIPT = [
    { phase: "Opening", prompt: `React to this:\n\n${POSITIONING}\n\nGut reaction?` },
    { phase: "Comprehension", prompt: "In your own words, what does this do? Who is it for?" },
    { phase: "Relevance", prompt: "How relevant to your daily work? Give a specific example." },
    { phase: "Differentiation", prompt: "What alternatives do you use? How does this compare?" },
    { phase: "Objections", prompt: "If someone pitched this, what's your first concern?" },
    { phase: "Pricing", prompt: "What would you expect to pay? Fair vs too expensive?" },
    { phase: "Closing", prompt: "One thing you'd change about the description?" },
  ];
  ```
</CodeGroup>

***

## Step 3 — Run Speak Sessions

Start a Speak session for each persona and run through the interview script turn by turn.

<CodeGroup>
  ```python Python theme={"dark"}
  def run_interview(name, pid):
      print(f"\n{'─' * 50}\nINTERVIEW: {name}\n{'─' * 50}")

      session = requests.post(f"{BASE}/speak", headers=HEADERS, json={
          "persona_id": pid,
          "context": "You're in a product positioning interview. Answer honestly from your professional perspective.",
      }).json()

      transcript = []
      for step in INTERVIEW_SCRIPT:
          response = requests.post(f"{BASE}/speak/{session['id']}/messages",
                                   headers=HEADERS, json={"message": step["prompt"]}).json()
          answer = response.get("transcript", response.get("content", ""))
          print(f"  [{step['phase']}] {answer[:100]}...")
          transcript.append({"phase": step["phase"], "question": step["prompt"],
                             "answer": answer, "persona": name})
      return transcript

  all_transcripts = {}
  for name, pid in persona_ids.items():
      all_transcripts[name] = run_interview(name, pid)
  ```

  ```javascript JavaScript theme={"dark"}
  async function runInterview(name, pid) {
    console.log(`\n${"─".repeat(50)}\nINTERVIEW: ${name}\n${"─".repeat(50)}`);

    const session = await fetch(`${BASE}/speak`, { method: "POST", headers: HEADERS,
      body: JSON.stringify({ persona_id: pid,
        context: "You're in a positioning interview. Answer honestly from your professional perspective." }),
    }).then((r) => r.json());

    const transcript = [];
    for (const step of INTERVIEW_SCRIPT) {
      const response = await fetch(`${BASE}/speak/${session.id}/messages`, {
        method: "POST", headers: HEADERS, body: JSON.stringify({ message: step.prompt }),
      }).then((r) => r.json());
      const answer = response.transcript || response.content || "";
      console.log(`  [${step.phase}] ${answer.slice(0, 100)}...`);
      transcript.push({ phase: step.phase, question: step.prompt, answer, persona: name });
    }
    return transcript;
  }

  const allTranscripts = {};
  for (const [name, pid] of Object.entries(personaIds))
    allTranscripts[name] = await runInterview(name, pid);
  ```
</CodeGroup>

<Warning>
  Speak sessions are sequential — each turn waits for the response. Budget \~2–3 minutes per interview, \~10–15 minutes for all 5.
</Warning>

***

## Step 4 — Extract Structured Insights

Feed each transcript into Chat with a structured output schema.

<CodeGroup>
  ```python Python theme={"dark"}
  from openai import OpenAI

  mavera = OpenAI(api_key=API_KEY, base_url="https://app.mavera.io/api/v1")

  INSIGHT_SCHEMA = {"type": "json_schema", "json_schema": {"name": "interview_insights", "strict": True,
      "schema": {"type": "object", "properties": {
          "positioning_clarity": {"type": "number"}, "relevance_score": {"type": "number"},
          "primary_objection": {"type": "string"},
          "price_expectation_low": {"type": "number"}, "price_expectation_high": {"type": "number"},
          "current_alternatives": {"type": "array", "items": {"type": "string"}},
          "key_quote": {"type": "string"}, "suggested_change": {"type": "string"},
          "would_buy": {"type": "string", "enum": ["yes", "maybe", "no"]},
          "top_3_insights": {"type": "array", "items": {"type": "string"}},
      }, "required": ["positioning_clarity", "relevance_score", "primary_objection",
          "price_expectation_low", "price_expectation_high", "current_alternatives",
          "key_quote", "suggested_change", "would_buy", "top_3_insights"]}}}

  def extract_insights(name, transcript):
      formatted = "\n\n".join(f"[{t['phase']}]\nQ: {t['question']}\nA: {t['answer']}" for t in transcript)
      resp = mavera.responses.create(model="mavera-1", input=[
          {"role": "system", "content": "Extract structured insights from this positioning interview. Use exact quotes."},
          {"role": "user", "content": f"Interview with {name}:\n\n{formatted}"},
      ], extra_body={"response_format": INSIGHT_SCHEMA})
      return json.loads(resp.output[0].content[0].text)

  all_insights = {}
  for name, transcript in all_transcripts.items():
      ins = extract_insights(name, transcript)
      all_insights[name] = ins
      print(f"  {name}: clarity={ins['positioning_clarity']}/10, "
            f"relevance={ins['relevance_score']}/10, would_buy={ins['would_buy']}")
  ```

  ```javascript JavaScript theme={"dark"}
  const OpenAI = require("openai").default;
  const mavera = new OpenAI({ apiKey: API_KEY, baseURL: "https://app.mavera.io/api/v1" });

  const INSIGHT_SCHEMA = { type: "json_schema", json_schema: { name: "interview_insights", strict: true,
    schema: { type: "object", properties: {
      positioning_clarity: { type: "number" }, relevance_score: { type: "number" },
      primary_objection: { type: "string" },
      price_expectation_low: { type: "number" }, price_expectation_high: { type: "number" },
      current_alternatives: { type: "array", items: { type: "string" } },
      key_quote: { type: "string" }, suggested_change: { type: "string" },
      would_buy: { type: "string", enum: ["yes", "maybe", "no"] },
      top_3_insights: { type: "array", items: { type: "string" } },
    }, required: ["positioning_clarity", "relevance_score", "primary_objection",
      "price_expectation_low", "price_expectation_high", "current_alternatives",
      "key_quote", "suggested_change", "would_buy", "top_3_insights"] } } };

  async function extractInsights(name, transcript) {
    const formatted = transcript.map((t) => `[${t.phase}]\nQ: ${t.question}\nA: ${t.answer}`).join("\n\n");
    const resp = await mavera.responses.create({ model: "mavera-1", input: [
      { role: "system", content: "Extract structured insights from this interview. Use exact quotes." },
      { role: "user", content: `Interview with ${name}:\n\n${formatted}` },
    ], extra_body: { response_format: INSIGHT_SCHEMA } });
    return JSON.parse(resp.output[0].content[0].text);
  }

  const allInsights = {};
  for (const [name, transcript] of Object.entries(allTranscripts))
    allInsights[name] = await extractInsights(name, transcript);
  ```
</CodeGroup>

***

## Step 5 — Marathon Summary Report

<CodeGroup>
  ```python Python theme={"dark"}
  def print_marathon_report(insights):
      print("\n" + "=" * 70)
      print("PERSONA INTERVIEW MARATHON — SUMMARY")
      print("=" * 70)
      print(f"\n{'Persona':<20} {'Clarity':>8} {'Relevance':>10} {'Buy':>6} {'Price Range':>15}")
      print("─" * 60)
      for name, d in insights.items():
          pr = f"${d['price_expectation_low']}–${d['price_expectation_high']}"
          print(f"{name:<20} {d['positioning_clarity']:>7}/10 {d['relevance_score']:>9}/10 "
                f"{d['would_buy']:>6} {pr:>15}")

      print(f"\n{'─' * 60}\nOBJECTIONS\n{'─' * 60}")
      for name, d in insights.items():
          print(f"  {name}: {d['primary_objection']}")

      print(f"\n{'─' * 60}\nKEY QUOTES\n{'─' * 60}")
      for name, d in insights.items():
          print(f"  {name}: \"{d['key_quote']}\"")

      # Alternatives frequency
      alts = {}
      for d in insights.values():
          for a in d.get("current_alternatives", []):
              alts[a] = alts.get(a, 0) + 1
      print(f"\n{'─' * 60}\nALTERNATIVES MENTIONED\n{'─' * 60}")
      for a, c in sorted(alts.items(), key=lambda x: -x[1]):
          print(f"  {a}: {c} persona(s)")

  print_marathon_report(all_insights)
  with open("interview_marathon.json", "w") as f:
      json.dump(all_insights, f, indent=2)
  ```

  ```javascript JavaScript theme={"dark"}
  function printMarathonReport(insights) {
    console.log("\n" + "=".repeat(70));
    console.log("PERSONA INTERVIEW MARATHON — SUMMARY");
    console.log("=".repeat(70));
    for (const [name, d] of Object.entries(insights)) {
      console.log(`  ${name.padEnd(20)} clarity=${d.positioning_clarity}/10 relevance=${d.relevance_score}/10 ` +
        `buy=${d.would_buy} $${d.price_expectation_low}–$${d.price_expectation_high}`);
    }
    console.log("\nOBJECTIONS:");
    for (const [n, d] of Object.entries(insights)) console.log(`  ${n}: ${d.primary_objection}`);
    console.log("\nKEY QUOTES:");
    for (const [n, d] of Object.entries(insights)) console.log(`  ${n}: "${d.key_quote}"`);
  }
  printMarathonReport(allInsights);
  const fs = require("fs");
  fs.writeFileSync("interview_marathon.json", JSON.stringify(allInsights, null, 2));
  ```
</CodeGroup>

***

## Example Output

```
PERSONA INTERVIEW MARATHON — SUMMARY
══════════════════════════════════════════════════════════════════════════
Persona              Clarity  Relevance    Buy     Price Range
────────────────────────────────────────────────────────────────
Elena                   8/10      9/10    yes     $300–$800/mo
Raj                     7/10      6/10  maybe     $100–$300/mo
Dr. Amara               6/10      5/10  maybe     $200–$500/mo
Marcus                  9/10      8/10    yes     $500–$1500/mo
Keiko                   8/10      7/10  maybe     $400–$1000/mo

KEY QUOTES
────────────────────────────────────────────────────────────────
  Elena: "If this replaces one agency cycle per quarter, it pays for itself."
  Raj: "Cool tech, but I need to see it beat my gut on actual ROAS."
  Dr. Amara: "Can I trust synthetic personas for health messaging?"
  Marcus: "I'd use this for pitch prep in a heartbeat."
  Keiko: "Show me a case study where this predicted real user behavior."
```

***

## Variations

<AccordionGroup>
  <Accordion title="Add adaptive follow-up probes">
    Generate a follow-up question based on the persona's answer:

    ```python theme={"dark"}
    def adaptive_probe(session_id, previous_answer, phase):
        probe = mavera.responses.create(model="mavera-1", input=[
            {"role": "system", "content": "Generate one follow-up question probing deeper."},
            {"role": "user", "content": f"Phase: {phase}\nAnswer: {previous_answer}"},
        ])
        return requests.post(f"{BASE}/speak/{session_id}/messages",
            headers=HEADERS, json={"message": probe.output[0].content[0].text}).json()
    ```
  </Accordion>

  <Accordion title="Test multiple positioning statements">
    ```python theme={"dark"}
    for i, pos in enumerate([POSITIONING_A, POSITIONING_B]):
        INTERVIEW_SCRIPT[0]["prompt"] = f"React to this:\n\n{pos}\n\nGut reaction?"
        for name, pid in persona_ids.items():
            run_interview(f"{name}_v{i}", pid)
    ```
  </Accordion>

  <Accordion title="Feed insights into a Focus Group for validation">
    ```python theme={"dark"}
    objections = [ins["primary_objection"] for ins in all_insights.values()]
    fg_questions = [{"question": f"How concerning is: '{obj}'", "type": "NPS", "order": i+1}
                    for i, obj in enumerate(objections)]
    fg = requests.post(f"{BASE}/focus-groups", headers=HEADERS, json={
        "name": "Objection Validation", "persona_ids": list(persona_ids.values()),
        "sample_size": 25, "questions": fg_questions}).json()
    ```
  </Accordion>

  <Accordion title="Export transcripts to Markdown">
    ```python theme={"dark"}
    with open("interviews.md", "w") as f:
        for name, transcript in all_transcripts.items():
            f.write(f"# {name}\n\n")
            for t in transcript:
                f.write(f"## {t['phase']}\n**Q:** {t['question']}\n**A:** {t['answer']}\n\n---\n\n")
    ```
  </Accordion>
</AccordionGroup>

***

## Credits Estimate

| Operation                         | Typical Cost  | Notes                            |
| --------------------------------- | ------------- | -------------------------------- |
| Persona creation (×5)             | 0–25          | One-time; reuse across runs      |
| Speak sessions (×5, 7 turns each) | 100–200       | Primary cost driver              |
| Chat insight extraction (×5)      | 15–40         | Structured output per transcript |
| **Total**                         | **\~115–265** |                                  |

<Tip>
  Keep interviews to 5–7 questions for the best depth/cost balance. Add follow-up probes selectively rather than for every question.
</Tip>

***

## What's Next

<CardGroup cols={2}>
  <Card title="Industry Panel Simulation" icon="users" href="/playbooks/industry-panel-simulation">
    Switch from interviews to a structured Focus Group with 10 buying-committee personas
  </Card>

  <Card title="Message Testing Matrix" icon="table-cells" href="/playbooks/message-testing-matrix">
    Quantify interview findings with a systematic message × persona grid
  </Card>

  <Card title="Persona Debate" icon="scale-balanced" href="/playbooks/persona-debate">
    Pit opposing buyer types against each other for pricing insights
  </Card>

  <Card title="Generational Content Testing" icon="people-group" href="/playbooks/generational-content-testing">
    Test across age demographics instead of role-based personas
  </Card>

  <Card title="Persona Selection Guide" icon="user" href="/cookbooks/persona-selection">
    Choose the right persona types for your research goal
  </Card>

  <Card title="Credits & Budget" icon="coins" href="/cookbooks/credits-budget-alerts">
    Pre-flight checks and usage tracking
  </Card>
</CardGroup>
