Minds Team

Panels API

Create and manage AI panels for surveying groups of minds with structured response aggregation. Ask questions, attach files, and export panel results.

Panels allow you to survey groups of AI minds with questions and receive aggregated, structured responses. This is useful for market research simulations, persona-based feedback gathering, and multi-perspective analysis.

Base URL: https://getminds.ai/api/v1 or https://api.getminds.ai/v1

Concepts

ConceptDescription
PanelA container for surveying multiple mind groups with questions
Mind GroupA collection of minds that respond together (e.g., "Gen Z Users", "Senior Developers")
QuestionA prompt sent to all minds in the panel's groups
Aggregated ResponseAI-classified and grouped responses with scale or categorical values

Guided Research Study Lifecycle

Use the guided lifecycle for multiple questions, a broader brief, an explicit method, a structured report, or analysis of a website, image, ad, video, or document. A single direct question can continue to use POST /panels/{panelId}/ask.

Do not create a study plan for an operational request against existing results. Use the panel export endpoints for “export this,” and use the summary endpoints to retrieve or re-present the current outcome. A new plan is needed only when the requested format changes what evidence must be collected.

The lifecycle is deliberately two-step:

  1. Preview a versioned draft. The planning model captures intent, the main source or asset, user questions, suggested questions, methods, outputs, missing inputs, and explicit confirmation questions.
  2. Revise the same draft until the user explicitly confirms its exact revision, then run it. The preview endpoint never starts research.

Preview or revise a plan

Endpoint: POST /api/v1/panels/{panelId}/research-plans/preview

New draft:

{
  "request": "Audit this campaign website with buyers and identify messaging gaps",
  "source": {
    "kind": "website",
    "label": "Campaign landing page",
    "url": "https://example.com/campaign"
  }
}

The response contains draftPlanId, revision, plan, confirmationQuestions, and nextAction. Every plan is a draft, even when status is needs_confirmation.

To answer a confirmation question or change the plan, create a new revision:

{
  "draftPlanId": "3a0c66e8-c2cd-4dbc-8ca7-363a5dcb5f1b",
  "revision": 1,
  "refinement": "Keep this simple and compare the two buyer groups",
  "answers": {
    "primary-source": "Use the campaign landing page"
  }
}

Draft revisions are stored durably with the panel. Stale revisions return 409 Conflict; only the draft creator may revise or confirm them.

Confirm and run the exact revision

Endpoint: POST /api/v1/panels/{panelId}/studies

{
  "draftPlanId": "3a0c66e8-c2cd-4dbc-8ca7-363a5dcb5f1b",
  "revision": 2,
  "confirmation": {
    "accepted": true,
    "advancedMethodOptIn": false
  }
}

The server reloads the stored revision, validates its method versions, configuration, runners, stages, and required confirmation capabilities, and queues it only after explicit acceptance. Advanced methods additionally require advancedMethodOptIn: true, but opt-in does not make an unavailable method executable. MaxDiff is available: the server builds balanced forced-choice tasks, the existing durable panel-questionnaire processor collects their locked categorical answers, and a registered deterministic calculation produces overall and per-Group rankings. Conjoint remains planned and is rejected at execution time.

The response includes a durable studyId and an immutable confirmed plan snapshot.

Plan limits are enforced twice. If the confirmed study would exceed the current Panel-answer allowance, POST /studies returns 403 with structured data.code: "PLAN_LIMIT" before the survey is queued. If an allowance is exhausted while an already queued survey is running, completed answers remain durable, remaining questions are not executed, and the study moves to status: "plan_limited" with separate completed and skipped progress plus planLimit details. This is not a completed study. Upgrade before starting a follow-up run for the remaining questions.

Study status

Endpoint: GET /api/v1/panels/{panelId}/studies/{studyId}

Returns status, per-question progress, the immutable confirmed plan, the separate server-prepared executionPlan, method stages, response/diagnostic artifacts, deterministic method calculations, and next actions. For adapter-backed methods, executionPlan contains the exact generated collection tasks while plan remains the revision the user approved. Poll this endpoint after execution rather than relying on client memory.

Clients must treat plan_limited as an explicit paywall outcome: show the upgrade action and explain that the survey stopped before all questions completed. Do not collapse it into completed, cancelled, or a generic processor failure.

Research method catalog

Endpoint: GET /api/v1/research-methods

Returns public method IDs and versions, an explicit executable boolean, availability (available, experimental, or planned), complexity, configuration JSON Schemas, stage kinds, artifact types, output types, and fallback methods. Only availability: "available" / executable: true methods can be passed to the current study runner. Internal runner identifiers are intentionally not exposed.

Flexible semantic summary

  • GET /api/v1/panels/{panelId}/summary retrieves the persisted summary.
  • POST /api/v1/panels/{panelId}/summary generates or refreshes it. The body accepts force and length (short, standard, or detailed).

Summary blocks are evidence contracts, not fixed widgets. Consumers may add new renderer logic without changing the underlying study. For website, image, ad, and video evidence, preserve heatmap or timeline-heatmap blocks instead of coercing them into donut charts.

List Panels

Retrieve all panels belonging to the authenticated user.

Endpoint: GET /api/v1/panels

Headers:

Authorization: Bearer minds_your_api_key

Response

{
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Consumer Research Panel",
      "flowMode": "panel",
      "createdAt": "2025-12-10T12:00:00.000Z",
      "updatedAt": "2025-12-10T14:30:00.000Z",
      "messageCount": 8,
      "groups": [
        {
          "id": "group-123",
          "name": "Gen Z Consumers",
          "sparkCount": 5,
          "sparks": [
            {
              "id": "spark-1",
              "name": "Emma",
              "discipline": "College Student",
              "profileImageUrl": "https://..."
            }
          ]
        }
      ]
    }
  ]
}

Response Fields

FieldTypeDescription
idstringUnique panel identifier
namestringPanel name
flowModestringAlways "panel" for panel flows
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last update timestamp
messageCountnumberTotal number of messages (questions + responses)
groupsarrayMind groups attached to this panel
groups[].sparkCountnumberNumber of minds in the group

Example Request

curl -X GET "https://getminds.ai/api/v1/panels" \
  -H "Authorization: Bearer minds_your_api_key"

Create Panel

Create a new panel with optional mind groups attached.

Endpoint: POST /api/v1/panels

Headers:

Authorization: Bearer minds_your_api_key
Content-Type: application/json

Request Body

{
  "name": "Product Feedback Panel",
  "groupIds": ["group-123", "group-456"]
}

Parameters

ParameterTypeRequiredDescription
namestringYesName of the panel
groupIdsarrayNoArray of mind group IDs to attach to the panel

Response

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Product Feedback Panel",
    "flowMode": "panel",
    "createdAt": "2025-12-10T12:00:00.000Z",
    "groups": [
      {
        "id": "group-123",
        "name": "Early Adopters",
        "sparks": [
          {
            "id": "spark-1",
            "name": "Alex",
            "discipline": "Tech Enthusiast",
            "profileImageUrl": "https://..."
          }
        ]
      }
    ]
  }
}

Example Request

curl -X POST "https://getminds.ai/api/v1/panels" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Market Research Panel",
    "groupIds": ["group-123", "group-456"]
  }'

Error Responses

400 Bad Request - Missing name

{
  "statusCode": 400,
  "message": "name is required"
}

404 Not Found - One or more groupIds not found or not accessible to the caller

{
  "statusCode": 404,
  "message": "Groups not found: 1f2e3d4c-..."
}

Get Panel Details

Retrieve a specific panel with all its groups and message history.

Endpoint: GET /api/v1/panels/{panelId}

Headers:

Authorization: Bearer minds_your_api_key

Response

{
  "data": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Consumer Research Panel",
    "flowMode": "panel",
    "createdAt": "2025-12-10T12:00:00.000Z",
    "updatedAt": "2025-12-10T14:30:00.000Z",
    "groups": [
      {
        "id": "group-123",
        "name": "Gen Z Consumers",
        "sparks": [
          {
            "id": "spark-1",
            "name": "Emma",
            "discipline": "College Student",
            "profileImageUrl": "https://..."
          }
        ]
      }
    ],
    "messages": [
      {
        "id": "msg-1",
        "role": "user",
        "content": "How important is sustainability when choosing products?",
        "metadata": {
          "groupIds": ["group-123"]
        },
        "createdAt": "2025-12-10T14:00:00.000Z"
      },
      {
        "id": "msg-2",
        "role": "assistant",
        "content": "How important is sustainability when choosing products?",
        "metadata": {
          "outputData": {
            "title": "How important is sustainability when choosing products?",
            "type": "scale",
            "groups": [
              {
                "group": "Gen Z Consumers",
                "value": "Very Important",
                "answers": [
                  {
                    "value": "9/10",
                    "persona": "Emma",
                    "discipline": "College Student",
                    "message": "Sustainability is a top priority for me..."
                  }
                ]
              }
            ]
          },
          "outputType": "bar"
        },
        "createdAt": "2025-12-10T14:00:30.000Z"
      }
    ]
  }
}

Example Request

curl -X GET "https://getminds.ai/api/v1/panels/550e8400-e29b-41d4-a716-446655440000" \
  -H "Authorization: Bearer minds_your_api_key"

Error Responses

403 Forbidden - Not authorized to access this panel

404 Not Found - Panel does not exist

Ask Panel Question

Send a question to all minds in the panel and receive streaming responses with aggregated results.

Endpoint: POST /api/v1/panels/{panelId}/ask

Headers:

Authorization: Bearer minds_your_api_key
Content-Type: application/json

Request Body

Basic question:

{
  "question": "What features would make you switch to a competitor product?",
  "groupIds": ["group-123"]
}

With attachments:

{
  "question": "Please review this product design and provide feedback",
  "attachments": [
    {
      "url": "https://example.com/design.pdf",
      "name": "Product Design v2",
      "type": "application/pdf"
    },
    {
      "path": "uploads/mockup.png",
      "name": "UI Mockup"
    }
  ],
  "links": [
    {
      "label": "https://competitor.com/product",
      "id": "link-1"
    }
  ],
  "keywords": [
    {
      "label": "sustainable packaging",
      "url": "https://example.com/article",
      "id": "keyword-1"
    }
  ]
}

Parameters

ParameterTypeRequiredDescription
questionstringYesThe question to ask all minds in the panel
groupIdsarrayNoLimit the question to specific groups (defaults to all groups)
attachmentsarrayNoFile attachments (PDFs, images, documents) to provide context. See file attachments below.
linksarrayNoURLs to fetch and analyze (uses Firecrawl for JS-heavy sites). Each has label (URL string) and optional id.
keywordsarrayNoKeywords with associated URLs for context. Each has label (keyword string), url (source URL), and optional id.
modelstringNoOverride the AI model used for panelist responses. Must be sent together with provider. See model override below.
providerstringNoAI provider for the model override: openai, anthropic, or google. Must be sent together with model.
disableDiversityCheckbooleanNoWhen true, skips the diversity-enforced regeneration loop (bigram self-similarity, value homogeneity, empty-bucket fill). Intended for ablation / benchmark runs where the orchestration layer is the variable under test. Default: false.
sourcePolicystringNoauto (default) or knowledge_only. The latter forbids request attachments/links/keywords and live web search, pre-retrieves each selected Mind's knowledge, and fails closed if any Mind has no matching evidence.

Each Mind's persisted policy is also enforced. A Mind saved as knowledge_only stays knowledge-only inside a mixed panel even when the panel request uses auto; only auto Minds may use shared web or request context.

For a durable knowledge-only request, use POST /api/v1/panels/{panelId}/runs with the same sourcePolicy. MCP ask_panel exposes the same parameter. responseMode: "queued" on /ask does not accept knowledge_only; use the durable runs endpoint instead.

Durable knowledge-only panel run

Durable runs survive client disconnects and are the recommended path for integrations. Supply a stable UUID in clientRequestId when you need safe retries. Reusing that UUID with the same normalized request returns the existing run; reusing it for different input returns 409.

curl -X POST "https://getminds.ai/api/v1/panels/{panelId}/runs" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "What does your source say about classroom smartphone rules?",
    "clientRequestId": "7c814f2a-2514-4db7-9e15-44c0e873caf8",
    "sourcePolicy": "knowledge_only"
  }'

Response: 202 Accepted

{
  "data": {
    "runId": "d3852cd2-1283-4e7a-a098-40bb6918f58e",
    "panelId": "9220f8af-e2d2-4a38-9f36-c1ab12cc667c",
    "clientRequestId": "7c814f2a-2514-4db7-9e15-44c0e873caf8",
    "questionGroupId": "e68fc257-bfb6-420f-9690-e604eaf672e2",
    "status": "queued",
    "dispatchState": "published",
    "acceptedAt": "2026-08-05T15:30:00.000Z",
    "statusUrl": "/api/v1/runs/d3852cd2-1283-4e7a-a098-40bb6918f58e",
    "eventsUrl": "/api/v1/runs/d3852cd2-1283-4e7a-a098-40bb6918f58e/events"
  }
}

Poll statusUrl until data.status is completed, cancelled, or failed. When completed, data.assistantMessageId points to the persisted panel answer. For ordered progress and replay, request eventsUrl?after={lastSequence}; the response includes the next cursor and current runStatus.

Knowledge-only panel runs reject attachments, links, and keywords. They disable live web search and prior panel-answer context, retrieve each selected Mind independently, and fail the run with KNOWLEDGE_SOURCE_UNAVAILABLE if any selected Mind has no matching processed knowledge. Upload and process the source for every Mind before starting the run.

Other relevant errors are 409 PANEL_MINDS_NOT_READY when a selected Mind is still training or failed training, and 409 when a clientRequestId is reused with different input.

Response (Server-Sent Events)

The endpoint returns a stream of Server-Sent Events (SSE). Each event is a JSON object with a type field.

Question Classification

Before processing, the system automatically classifies your question into one of three types:

TypeDescriptionExample Questions
scaleNumeric ratings (1-5, 1-10, etc.)"Rate this 1-5", "Score from 0-10"
categoricalDiscrete choices (yes/no, A/B/C)"Do you agree?", "Which do you prefer: A, B, or C?"
qualitativeOpen-ended opinions"What do you think?", "What concerns do you have?"

For qualitative questions, responses are automatically clustered into topics (e.g., "Privacy concerns", "Cost barriers"). Each response's value field contains its assigned topic.

Event Types

1. Start Event

{"type": "start", "total": 10}

Indicates the start of processing with total number of minds.

2. Classification Event

{
  "type": "classification",
  "classification": {
    "type": "scale",
    "scaleRange": [1, 5]
  }
}

Indicates how the question was classified. For scale questions, includes the detected range. For categorical questions, includes the detected options.

3. Answer Event

{
  "type": "answer",
  "sparkId": "spark-1",
  "sparkName": "Emma",
  "discipline": "College Student",
  "profileImageUrl": "https://...",
  "groupId": "group-123",
  "groupName": "Gen Z Consumers",
  "answer": "4\n\nI think this is a solid product but could improve..."
}

Sent for each mind's individual response. For scale/categorical questions, the answer starts with the rating/choice followed by reasoning.

4. Aggregating Event

{"type": "aggregating"}

Indicates AI is now aggregating all responses. For qualitative questions, this includes topic clustering.

5. Result Event

{
  "type": "result",
  "outputData": {
    "title": "What features would make you switch to a competitor product?",
    "type": "categorical",
    "classification": {
      "type": "categorical",
      "options": ["Yes", "No", "Maybe"]
    },
    "groups": [
      {
        "group": "Gen Z Consumers",
        "value": "Better Price",
        "alignmentScore": 82,
        "answers": [
          {
            "value": "Price",
            "persona": "Emma",
            "discipline": "College Student",
            "message": "A comparable plan is 20% cheaper[0], so I would switch for better pricing.",
            "imageUrl": "https://...",
            "reliabilityScore": 84,
            "citationSources": [
              {
                "id": "web-0-https://example.com/pricing",
                "title": "Competitor pricing",
                "url": "https://example.com/pricing",
                "domain": "example.com",
                "sourceType": "web"
              }
            ],
            "citationProvenance": {
              "mode": "generation",
              "status": "attributed",
              "recordedAt": "2026-07-20T17:00:00.000Z",
              "verifier": "panel-citations-v1"
            }
          }
        ]
      }
    ]
  },
  "outputType": "bar"
}

Contains the aggregated results with classified responses. alignmentScore and per-answer reliabilityScore are computed before the result is returned on v1 endpoints (see Alignment scoring).

6. Done Event

{"type": "done"}

Indicates the stream is complete.

Output Data Structure

FieldTypeDescription
titlestringThe original question
typestringResponse type: "scale", "categorical", or "qualitative"
classificationobjectClassification details (type, scaleRange, or options)
groupsarrayAggregated responses by spark group
groups[].groupstringGroup name
groups[].valuestringDominant value for the group (average for scale, most common for categorical, dominant topic for qualitative)
groups[].alignmentScorenumber?Average of per-answer reliabilityScore for the group (0–100). See Alignment scoring. Omitted when no answer in the group could be scored.
groups[].answersarrayIndividual mind responses
groups[].answers[].valuestringExtracted value: number for scale, choice for categorical, topic for qualitative
groups[].answers[].personastringSpark name
groups[].answers[].disciplinestringSpark discipline/role
groups[].answers[].messagestringFull response text (reasoning for scale/categorical, full answer for qualitative)
groups[].answers[].imageUrlstringSpark profile image URL
groups[].answers[].reliabilityScorenumber?Per-mind reliability score (0–100): how on-character this mind's answer was against its own persona definition. See Alignment scoring. Omitted when the evaluator was skipped (short systemPrompt, empty message) or failed.
groups[].answers[].citationSourcesarray?Server-owned source identities referenced by zero-based [N] markers in message. Private Mind files have a title but no URL. Underlying knowledge text is not returned.
groups[].answers[].citationProvenanceobject?Citation provenance. mode: "generation" means sources were attributed during the original turn; mode: "retroactive" means a historical answer was checked later against the Mind's then-current knowledge base.

Claim-level citations

Citation fields are optional. They appear only when a response contains a factual claim tied to retrieved Mind knowledge or web evidence. A marker such as [0] points to citationSources[0]; [0,1] means both sources support the preceding claim. Validate markers against the returned array and ignore unknown indexes.

citationProvenance.status: "attributed" records generation-time source attribution; it is not a claim that a separate verifier independently proved the answer. status: "verified" is used when an existing historical answer was checked later. Consumers should preserve the distinction and must not present retroactive verification as evidence captured during the original turn.

The per-Mind answer SSE event remains clean display text and does not include unresolved citation metadata. Use the final result.outputData.groups[].answers[] objects when citation rendering is required.

Response Types Explained

Scale responses:

  • value: The numeric rating (e.g., "4")
  • message: Brief reasoning for the rating
  • groups[].value: Average rating across the group

Categorical responses:

  • value: The chosen option (e.g., "Yes", "Option A")
  • message: Brief reasoning for the choice
  • groups[].value: Most common choice in the group

Qualitative responses:

  • value: Assigned topic/theme (e.g., "Privacy concerns", "Cost barriers")
  • message: Full response text
  • groups[].value: Dominant topic in the group
  • Topics are automatically clustered from all responses (3-6 topics identified)

Alignment scoring

Every panel answer includes two scores on the v1 API response:

  • groups[].answers[].reliabilityScore (0–100, integer, optional) — per-mind score of how on-character the mind's answer is against its own systemPrompt. Computed by re-evaluating the response with the same evaluator used for individual spark chats, so the v1 panel value is directly comparable to single-mind reliabilityScore values.
  • groups[].alignmentScore (0–100, integer, optional) — average of per-answer reliabilityScore for that group. The UI surfaces this as the per-group Alignment indicator (High / Medium / Low).

Label bands used by the UI (not in the payload, included here so API consumers can match):

BandRange
High67–100
Medium34–66
Low0–33

When fields are omitted: the evaluator skips answers where the mind's systemPrompt is shorter than 20 characters, where the answer message is empty, or when the evaluator call itself fails. If every answer in a group is skipped, that group's alignmentScore is also omitted.

Timing: on the v1 endpoints, scoring runs synchronously before the response is returned, so the scores are present in the same payload as the rest of outputData. This adds a few seconds of latency on top of panel generation; consumers that need a faster panel result without alignment should batch-evaluate downstream instead of relying on the inline score.

Status: this is a temporary stand-in for a future group-alignment metric (closeness to empirical research findings). The field names will be preserved when that lands; the semantics of alignmentScore may change.


File Attachments

You can attach files, links, and keywords to provide context for panel questions. Minds will receive the processed content before answering.

Attachment Types

1. File Attachments (attachments)

Upload documents, PDFs, images, spreadsheets for analysis:

{
  "question": "What improvements would you suggest for this product spec?",
  "attachments": [
    {
      "url": "https://example.com/product-spec.pdf",
      "name": "Product Specification v2.1",
      "type": "application/pdf"
    },
    {
      "path": "uploads/user-research.docx",
      "name": "User Research Findings"
    }
  ]
}

Supported formats:

  • Documents: PDF, DOCX, TXT, MD
  • Images: PNG, JPG, WEBP (with OCR)
  • Spreadsheets: CSV, XLSX

File sources:

  • url: External URL (downloaded and processed)
  • path: Supabase storage path (auto-signed and processed)

2. Link Attachments (links)

Fetch and analyze web pages (uses Firecrawl for JS-heavy sites + screenshots):

{
  "question": "Compare our pricing to these competitors",
  "links": [
    { "label": "https://competitor-a.com/pricing", "id": "link-1" },
    { "label": "https://competitor-b.com/pricing", "id": "link-2" }
  ]
}

Features:

  • JavaScript rendering (Firecrawl)
  • Screenshot capture for visual context
  • Markdown extraction
  • Automatic content truncation (3000 chars per link if multiple, 15000 if single)

3. Keyword Context (keywords)

Provide keywords with source URLs for additional context:

{
  "question": "How can we improve sustainability?",
  "keywords": [
    {
      "label": "circular economy",
      "url": "https://en.wikipedia.org/wiki/Circular_economy",
      "id": "kw-1"
    },
    {
      "label": "carbon neutral packaging",
      "url": "https://example.com/carbon-neutral-guide",
      "id": "kw-2"
    }
  ]
}

Complete Example with Attachments

curl -X POST "https://getminds.ai/api/v1/panels/panel-id/ask" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Based on this product design and competitor analysis, what features should we prioritize?",
    "groupIds": ["product-managers", "designers"],
    "attachments": [
      {
        "url": "https://example.com/product-design-v3.pdf",
        "name": "Product Design v3",
        "type": "application/pdf"
      }
    ],
    "links": [
      { "label": "https://competitor.com/features" }
    ],
    "keywords": [
      {
        "label": "user experience best practices",
        "url": "https://uxdesign.com/best-practices"
      }
    ]
  }'

Processing:

  • Files are analyzed in parallel (PDFs → text extraction, images → OCR/vision)
  • Links are fetched with Firecrawl (JS rendering + screenshots)
  • Content is injected into the question context for all minds
  • Failed attachments are gracefully handled with fallback messages

Tips:

  • Attach only relevant files (each adds processing time)
  • Use links for dynamic web content
  • Use keywords for additional web context
  • File processing timeout: 30s per file
  • Link fetching timeout: 15s per URL

Example Request

curl -X POST "https://getminds.ai/api/v1/panels/550e8400-e29b-41d4-a716-446655440000/ask" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "On a scale of 1-10, how likely are you to recommend this product?"
  }'

Example: JavaScript EventSource

const eventSource = new EventSource(
  'https://getminds.ai/api/v1/panels/{panelId}/ask',
  {
    headers: {
      'Authorization': 'Bearer minds_your_api_key',
      'Content-Type': 'application/json'
    }
  }
);

// Note: For POST requests with SSE, use fetch with ReadableStream
const response = await fetch('https://getminds.ai/api/v1/panels/{panelId}/ask', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer minds_your_api_key',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    question: 'How satisfied are you with the current pricing?'
  })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();

while (true) {
  const { done, value } = await reader.read();
  if (done) break;

  const chunk = decoder.decode(value);
  const lines = chunk.split('\n');

  for (const line of lines) {
    if (line.startsWith('data: ')) {
      const event = JSON.parse(line.slice(6));
      console.log('Event:', event.type, event);
    }
  }
}

Error Responses

400 Bad Request - Missing question or no groups attached

{
  "statusCode": 400,
  "message": "question is required"
}
{
  "statusCode": 400,
  "message": "No groups attached to this panel"
}
{
  "statusCode": 400,
  "message": "No minds in panel groups"
}

403 Forbidden - Not authorized to access this panel

404 Not Found - Panel does not exist

Model Override

By default, panel responses use your team's preferred provider when one is configured and eligible, otherwise the product default. You can override the model and provider per request to run experiments across model families:

curl -X POST "https://getminds.ai/api/v1/panels/{panelId}/ask" \
  -H "Authorization: Bearer minds_…_key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "Rate this 1-5",
    "model": "gpt-4o",
    "provider": "openai"
  }'

Supported providers: openai, anthropic, google. For panel requests, model and provider must be sent together. If only one is sent, the API returns 400 Bad Request. Per-request overrides take precedence over the team provider preference.

Disable Diversity Check

The panel orchestrator runs a post-generation diversity-enforced regeneration loop (bigram self-similarity check, value-homogeneity detection, empty-bucket fill) before aggregation. This is the L4 layer of the panel recipe.

For ablation studies and benchmark runs where you want to isolate the contribution of this layer, pass disableDiversityCheck: true:

curl -X POST "https://getminds.ai/api/v1/panels/{panelId}/ask" \
  -H "Authorization: Bearer minds_…_key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "What features matter most to you?",
    "disableDiversityCheck": true
  }'

With the flag enabled, panelist responses are returned exactly as initially generated — no second-pass regeneration is triggered, even if responses overlap heavily. Classification (L3), per-spark RAG (L2), and aggregation (L5) still run normally. Cost-savings: ~5–25% fewer LLM calls per panel question, depending on how many sparks the diversity check would have flagged.

When to use: Method comparisons, A/B tests of orchestration layers, reproducing baseline behavior. Production panels should leave this off (default).

Export Panel Results

Generate a structured report of all panel results in Markdown format.

Endpoint: POST /api/v1/panels/{panelId}/export

Headers:

Authorization: Bearer minds_your_api_key
Content-Type: application/json

Request Body

{
  "format": "md"
}

Parameters

ParameterTypeRequiredDescription
formatstringNoExport format. Currently only "md" (Markdown) is supported. Default: "md"

Response

{
  "data": {
    "format": "md",
    "content": "# Panel Report: Consumer Research Panel\n\n## Executive Summary\n\nThis panel survey gathered insights from 15 participants across 3 consumer groups...\n\n## Methodology\n\n- 3 groups, 15 participants\n- 5 questions asked\n\n## Results by Question\n\n### Q1: How important is sustainability when choosing products?\n\n**Type:** scale\n\n#### Gen Z Consumers (dominant: Very Important)\n\n..."
  }
}

Report Structure

The generated report includes:

  1. Executive Summary - 2-3 paragraph overview of key findings
  2. Methodology - Groups, participants, and structure
  3. Results by Question - Cross-group comparison with key insights and quotes
  4. Cross-Group Analysis - Patterns and trends across groups
  5. Conclusions & Recommendations - Actionable insights

Example Request

curl -X POST "https://getminds.ai/api/v1/panels/550e8400-e29b-41d4-a716-446655440000/export" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "format": "md"
  }'

Error Responses

403 Forbidden - Not authorized to access this panel

404 Not Found - Panel does not exist

Check Export Status

Check the status of a panel export job. If no jobId is provided, returns the status of the most recent export.

Endpoint: GET /api/v1/panels/{panelId}/export-status

Headers:

Authorization: Bearer minds_your_api_key

Query Parameters

ParameterTypeRequiredDescription
jobIdstringNoSpecific job ID. If omitted, returns the most recent export job

Response

{
  "data": {
    "status": "completed",
    "downloadUrl": "/api/v1/panels/{panelId}/export-download?jobId=job-123"
  }
}

Status Values

StatusDescription
queuedExport job is waiting to be processed
processingExport is being generated (includes progress field, 0-100)
completedExport is ready for download (includes downloadUrl field)
failedExport failed (includes error field with reason)

Example Request

curl -X GET "https://getminds.ai/api/v1/panels/{panelId}/export-status?jobId=job-123" \
  -H "Authorization: Bearer minds_your_api_key"

Error Responses

403 Forbidden - Not authorized to access this panel

404 Not Found - Panel or job does not exist


Download Export

Download the exported panel report as a PDF file.

Endpoint: GET /api/v1/panels/{panelId}/export-download

Headers:

Authorization: Bearer minds_your_api_key

Query Parameters

ParameterTypeRequiredDescription
jobIdstringYesThe export job ID (from export-status response)

Response

Returns a PDF file with appropriate headers:

  • Content-Type: application/pdf
  • Content-Disposition: attachment; filename="Panel-Report.pdf"

Example Request

curl -X GET "https://getminds.ai/api/v1/panels/{panelId}/export-download?jobId=job-123" \
  -H "Authorization: Bearer minds_your_api_key" \
  -o panel-report.pdf

Error Responses

400 Bad Request - Missing jobId parameter or job is not yet completed

403 Forbidden - Not authorized to access this panel

404 Not Found - Panel or job does not exist


Workflow Example

Here is a complete workflow for creating and using a panel:

# 1. Create spark groups first (using Sparks API)
# Assume you have created groups with IDs: group-genz, group-millennials

# 2. Create a panel with those groups
curl -X POST "https://getminds.ai/api/v1/panels" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Product Pricing Research",
    "groupIds": ["group-genz", "group-millennials"]
  }'

# Response: { "data": { "id": "panel-123", ... } }

# 3. Ask questions to the panel
curl -X POST "https://getminds.ai/api/v1/panels/panel-123/ask" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "What price point would you consider fair for this product?"
  }'

# 4. Ask another question
curl -X POST "https://getminds.ai/api/v1/panels/panel-123/ask" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "question": "How does this compare to competitor pricing?"
  }'

# 5. Export the results as a report
curl -X POST "https://getminds.ai/api/v1/panels/panel-123/export" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"format": "md"}'

# 6. Check export status (poll until completed)
curl -X GET "https://getminds.ai/api/v1/panels/panel-123/export-status" \
  -H "Authorization: Bearer minds_your_api_key"

# Response: { "data": { "status": "completed", "downloadUrl": "/api/v1/panels/panel-123/export-download?jobId=..." } }

# 7. Download the PDF
curl -X GET "https://getminds.ai/api/v1/panels/panel-123/export-download?jobId=job-123" \
  -H "Authorization: Bearer minds_your_api_key" \
  -o panel-report.pdf

Error Codes Summary

CodeDescription
400Bad Request - Missing required fields or invalid data
401Unauthorized - Invalid or missing API key
403Forbidden - Not authorized to access this panel
404Not Found - Panel does not exist
500Internal Server Error - Server-side error

Next Steps