Minds Team

Audiences API

Create, ground, validate, manage, and export reusable Audiences of Minds, then attach them to cohesive research Studies through the Minds v1 API.

An Audience is a reusable collection of Minds. Build it once, ground it with research sources when needed, and attach it to one or more Studies.

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

Create an Audience

curl -X POST "https://api.getminds.ai/v1/audiences" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "German SaaS buyers",
    "mindIds": ["mind-id-1", "mind-id-2"]
  }'

Audiences are private by default. Set isLinkSharingEnabled: true only when the user explicitly requests a public link.

Sharing and access

An Audience carries its own sharing settings, editable through PUT /audiences/{audienceId}:

FieldEffect
isSharedWithTeamEvery member of the owner's team can open the Audience and read and chat with every Mind in it, even when those Minds are not shared individually.
isPublicAnyone can open the Audience and its Minds (marketplace listing).
isLinkSharingEnabledAnyone with the link can open the Audience. Set at creation; not editable through PUT.

Explicit Audience members get the same read access as team members. Access gained through an Audience is read-and-chat only: it never grants edit or delete rights on the Minds inside. This is how curated Minds are typically delivered to a partner team — share one Audience with the team instead of sharing each Mind, and let the team discover the Minds through GET /minds/library.

Core endpoints

MethodPathPurpose
GET/audiencesList visible Audiences
POST/audiencesCreate an Audience from existing Mind IDs
GET/audiences/{audienceId}Read members, access, grounding, and Formations
PUT/audiences/{audienceId}Update supported fields and sharing settings
DELETE/audiences/{audienceId}Delete a confirmed Audience
POST/audiences/{audienceId}/membersAdd a Mind
DELETE/audiences/{audienceId}/members/{mindId}Remove a Mind
GET/audiences/{audienceId}/progressRead creation, training, and background research progress
POST/audiences/{audienceId}/recalibrateRefresh grounding and recalibrate the members; deepen researches what is still missing
GET/audiences/{audienceId}/recalibrations/{operationId}operation.statusUrl: status, result, error
POST/audiences/{audienceId}/duplicateCopy the Audience with new, independent copies of its Minds and research

Only the owner can add members with POST /audiences/{audienceId}/members. Send mindId or mindIds; if both are supplied, mindId wins. UUID case variants are deduplicated. The response data.added counts distinct requested IDs, including existing members. Ownership, Mind access, and capacity are checked in one transaction, so competing additions cannot both take the last slot. A capacity refusal (403) or inaccessible Mind (404) adds nothing. Responses are private and non-cacheable; unexpected storage or plan-resolution failures return a generic 500.

Member-add requests require a JSON object of at most 64 KiB, including ignored fields. When using mindIds, supply at most 1,000 IDs before deduplication; send larger additions in separate requests. Invalid JSON or too many IDs returns 400; an oversized body returns 413. These limits also apply to legacy Group URLs.

DELETE /audiences/{audienceId}/members/{mindId} is owner-only and returns an empty 204, including when membership is already absent. It atomically removes that membership and the Mind’s subgroup assignments on this Audience; it does not delete the Mind or affect other Audiences. Ownership is checked as part of the write, and a failed transaction preserves both membership and assignments. Missing or unowned Audiences return 404; unexpected storage failures return a generic 500. All responses are private and non-cacheable.

Create a grounded Audience from a brief

POST /audiences/from-brief accepts a research brief plus source files or URLs and creates a grounded synthetic Audience. PDF, DOCX, CSV, XLS, and XLSX inputs enter the same classification and extraction pipeline used by the webapp. The REST text field and MCP brief (or legacy text alias) accept up to 200,000 characters after trimming whitespace.

For respondent spreadsheets, preview segmentation first:

POST /audiences/from-brief/segmentation-preview

The preview distinguishes completed respondent data from screeners and questionnaire programming grids. It excludes identifiers, weights, free text, and derived statistics from representative cohort allocation by default, and preserves the valid base for conditional or multi-select questions.

For the complete profile review, send groundingPreview: true and cohortAllocation: { includeProfilesInResponse: true } to POST /audiences/from-brief. Inspect the proposed profiles, applied composition, source findings, and intended study use. To create that reviewed Audience, resend the same inputs and memberCount, omit groundingPreview, and return reviewedGroundingJson and reviewedGroundingSha256 exactly as received. An altered snapshot is rejected.

Fresh public API previews and creation return HTTP 202 with data.jobId and a status URL. This also applies when async is omitted or false: research runs in a durable job rather than holding the request open through the edge timeout. Poll GET /audiences/from-brief/jobs/{jobId} until status is completed or failed; a completed preview contains the same reviewed grounding and allocation result. The MCP tool uses the same durable operations. If it returns a pending operation, call it again with operationId to retrieve the result without starting another preview.

To change existing targets without researching again, send the unchanged reviewedGroundingJson and reviewedGroundingSha256, groundingPreview: true, and revised cohortAllocation.targetOverrides or excludeDistributions. This saved-snapshot preview can return HTTP 200 directly. Set async: true or Prefer: respond-async to queue it. Handle both 200 and 202; do not treat a 202 response as a completed preview.

Named multi-select options remain independent incidences. Supplied percentages retain their provenance; any modelled shares are labelled assumptions. An applicable questionnaire rule such as “channel A or channel B” is checked against each allocated profile, not just a separate 100% eligibility card. Unresolved rules or quotas that cannot be reconciled with every required rule return 422 before creation. Review the reported rule and rework the preview. A zero marginal allocation error alone does not prove eligibility.

Requested research categories are searched alongside population evidence. A broader consumer source remains a proxy when the audience is a particular profession; requesting a category does not make that source an observation of the profession.

Two-phase creation

A new Audience is usable within seconds. Its first phase stands on what is already known: verified surveys of these people from the evidence pool, the requester's own files, and a stated assumption for every standard dimension that nothing covers yet. Age and gender are never assumed; they stay missing until evidence exists.

Web research continues in the background and is applied automatically. Sourced evidence replaces assumptions, earlier charts are kept, and the Minds are recalibrated between runs, never during a running Study run or validation. A run keeps the Minds it started with, and each run records which evidence version it answered from. Automatic validation waits until the background research is done. Background research is never a reason to wait before running a Study.

The POST /audiences/from-brief result includes research, with phase: "researching" when background research was started. GET /audiences/{audienceId} returns research and grounding.coverage. GET /audiences/{audienceId}/progress returns research and coverage; readiness is unchanged. All three fields are additive.

Research state

FieldContent
phaseresearching: usable now, background research running or waiting for a run to finish before updating the Minds. researched: done, also for Audiences whose research finished at creation. usable: background research failed and the Audience stays on its first phase
statusqueued, running, completed, failed, or null
stageresearching, waiting_for_runs, recalibrating, done, or null
progress0 to 100
startedAt, completedAtWhen the background research started and finished
outcomenull until the research ends; then chartsAdded, sourcesAdded, dimensionsImproved ([{ dimension, from, to }]), membersRecalibrated, coverage counts, applied, and skippedReason when nothing was applied

Coverage

coverage is { dimensions: [{ dimension, status, distribution? }], counts: { sourced, proxy, assumed, missing } }, or null. Each dimension has one status:

statusMeaning
sourcedPublished evidence about these people
proxyEvidence about a wider or related population
assumedThe model's stated assumption, until research finds evidence
missingNot covered

Recalibrate and go deeper

POST /audiences/{audienceId}/recalibrate refreshes the stored grounding and recalibrates the members. To go deeper, send deepen:

Without deepen, the request returns 202 with data.operation immediately. Research and roster changes run in the background. Poll GET /audiences/{audienceId}/recalibrations/{operationId} at operation.statusUrl, or read calibration.operation on the Audience. Its status is queued, running, completed, or failed; result retains the grounding and member counts, and error retains a safe terminal error or refusal. Member training continues separately after the roster update. Send a stable requestKey (1–128 characters) or Idempotency-Key header for retries: identical input replays the same operation even after completion, with 200 for terminal receipts; changed input with that key returns 409.

{ "deepen": { "topics": ["streaming subscriptions", "price sensitivity"] } }

Go deeper researches what the Audience still lacks, every standard dimension its coverage reports as missing or assumed, plus the given topics (optional, at most 8, each up to 120 characters). The findings are added to the saved grounding: stronger evidence replaces weaker evidence for the same dimension, and every other chart stays. The members are then recalibrated like in any recalibration.

deepen cannot be combined with distributions, query, or requestedDistribution (400). While the Audience's background research is still running, the request is refused with 409 and AUDIENCE_RESEARCH_RUNNING.

Duplicate an Audience

POST /audiences/{audienceId}/duplicate creates a private copy of an Audience you can edit. Every member Mind is copied as a new, independent Mind with its profile, knowledge items, patterns and embeddings, together with the Audience's grounding and snapshot history, sources, ready Formations and finished validations. Sharing, public links, the marketplace listing and running jobs are not copied, and changing or deleting the copy never affects the original.

The optional body { "name": "…" } names the copy (default <name> (copy)). Send x-minds-idempotency-key to make retries safe: a repeated key returns the same copy with 200; a new copy returns 201 with the SavedAudienceResponse shape. The copied Minds count toward your plan's Mind allowance (403 with PLAN_LIMIT when they do not fit). Callers who can view but not edit the Audience get 403. While its Minds are still training or its research is still running, the request returns 409 with AUDIENCE_BUILD_IN_PROGRESS; retry once the Audience is ready.

Formations

On the first page (offset: 0), recovery checks at most 100 pending builds, oldest first. One failed attempt does not stop attempts for the other selected builds or prevent the list from being returned. Check build status and reopen the first page to retry pending work.

Formation lists accept limit (default and maximum 100) and offset (default 0). The response includes pagination: { total, limit, offset, hasMore, nextOffset }; request nextOffset while hasMore is true. Auto-dimension winners are selected before paging, so totals count the visible de-duplicated list. Ordering is newest first, with ID breaking timestamp ties. Each page uses one database snapshot, but changes between requests can shift offsets; restart from 0 if the list changes. Only offset 0 seeds defaults and checks stalled builds.

A Formation is a persisted segmentation inside one Audience. Use /audiences/{audienceId}/formations to list, create, preview, recompute, or delete Formations without creating another Audience.

For previews, Accept selects UTF-8 JSON or NDJSON using quality weights, wildcards and media parameters. q=0 rejects a format, and an explicit media range overrides a wildcard. Missing Accept defaults to NDJSON. If neither representation is acceptable, the endpoint returns a private 406 before generation. MCP requests application/json explicitly.

Before saving a successful build, the worker verifies the complete Audience membership against the population it classified. A changed population requests a retry instead of publishing an incomplete split. The final save briefly serializes member insertion; model generation runs outside that transaction. Empty-population and unsplittable-population failures require the same snapshot check; over-cap failures recheck whether the current population still exceeds the limit.

Queued builds stay building after an execution error while configured attempts remain; exhausted attempts record a safe failed status. Without Redis, the synchronous fallback makes one attempt and records a safe failure if it cannot finish.

A successful incremental classification replaces that Mind’s previous assignments within the same Formation, including previous overlap. A classifier outage preserves existing assignments. Numeric-balanced splits still require an explicit recompute to include added Minds.

Preview accepts an optional JSON body of at most 64 KiB. userInput is optional and limited to 2000 characters after trimming; omitted or blank input uses the default split request. Omit priorHypothesis or use null for a new proposal; supplied proposals must satisfy the creation contract. Invalid input returns 400, oversized bodies 413, and storage failures a generic 500 before streaming starts. Both JSON and NDJSON responses are private and non-cacheable. Model failures or invalid generated proposals return 500 in JSON mode, or an error event followed by done once NDJSON starts. Successful hypotheses contain only creation-compatible fields and fit the creation request limit. Disconnecting or cancelling the stream signals cancellation to model generation.

Formation detail reads are private and non-cacheable. They expose only documented proposal, progress, subgroup, and membership fields; stored diagnostics are omitted. Unknown failure text becomes a safe retry message. Invalid legacy proposals appear as {}, malformed building progress as null, and ready Formations always have progress: null. Invalid persisted detail metadata or storage failures return a generic 500. During recompute, subgroups can still show the previous completed buckets until replacement succeeds; their presence does not mean the rebuild is ready.

Creating a Formation accepts a JSON body of at most 64 KiB. Supply a non-empty intent and 2–15 subgroups, each with non-empty id, label, and definition. Text is trimmed; subgroup IDs and labels must be unique after trimming. The IDs unanswered, __unanswered, and __other are reserved. Optional name must be a string; an empty name uses the intent. Invalid input returns 400, oversized bodies return 413, and unexpected storage failures return a generic 500. Creation responses are private and non-cacheable. User-created splits need at least two populated primary buckets to become ready; otherwise they become failed. A Formation deleted before acknowledgement returns 404.

Deletion and recomputation use private, non-cacheable responses. Missing or non-mutable Formations return 404; unexpected storage or queue failures return a generic 500. If a recompute response is uncertain, check the saved status before retrying.

Validate an Audience against real surveys

Audience Validation checks an Audience against real, published surveys. It finds surveys whose respondents best match the Audience, asks the Audience's Minds the same questions, and scores how close their answers are to the published answers. The same check runs from the Audience's Validation tab in the app and through the MCP tools validate_audience and get_audience_validation. The endpoints below use the same authentication as the rest of the API.

One validation is a batch: a single run that can ask several surveys at once.

Validation endpoints

MethodPathPurpose
POST/audiences/{audienceId}/validationsStart a validation
GET/audiences/{audienceId}/validationsList the Audience's validations with its overall validity, included validations, responses, and Mind readiness
GET/audiences/{audienceId}/validations/batches/{batchId}Read one validation: status, progress, survey scores, question selection, and failure
GET/audiences/{audienceId}/validations/{validationId}Read one survey's scoring, with every KPI and question
POST/audiences/{audienceId}/validations/batches/{batchId}/cancelStop a validation while canCancel is true
GET/audiences/validation-benchmarks?audienceId={audienceId}Preview the surveys that would be used and how they fit the Audience

Start a validation

You can validate any Audience you can edit, at any time and as often as you like. The Audience needs at least 10 ready Minds.

curl -X POST "https://api.getminds.ai/v1/audiences/{audienceId}/validations" \
  -H "Authorization: Bearer minds_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "findSurveys": true,
    "requestKey": "3f6c1e0a-6c1b-4a53-9a3e-2d1f0b7c9e11"
  }'

Choose what to validate against with one of these body fields:

FieldValidates against
findSurveys: trueThe published surveys that best fit the Audience, found by Minds
benchmarkIds1 to 5 listed surveys: curated ids, discovered:<id>, or saved:<validationId>
filesYour own survey files: the questionnaire and its results as PDF, XLS/XLSX/CSV, DOCX, or TXT
datasetA respondent-level dataset (Pro plan)
run: { studyId, runId }A Study run you already did. Scoring it is free and asks nothing new

Send an optional requestKey, or an Idempotency-Key header, so that a retried request returns the same batch instead of starting another one.

A successful start returns HTTP 202 with:

  • data: the validation batch
  • included: your included validations, as perMonth, used, remaining, renewsAt, and thisRun
  • responses: the synthetic responses a validation beyond the included ones spends

An Audience with fewer than 10 ready Minds is refused with 422 and AUDIENCE_TOO_SMALL. An Audience larger than your plan allows in a Study is refused with the standard plan-limit error.

Follow a validation

All chosen surveys are asked in one run, in one Study named Validation run: <Audience name>. That Study is the platform's working copy: it does not appear in your Study list and does not count toward Study limits. Validation runs queue behind Studies that people start, so they never slow your own research. A run usually takes 10 to 60 minutes.

Poll GET /audiences/{audienceId}/validations/batches/{batchId} until status is completed, failed, or cancelled. The statuses are queued, preparing, running, completed, failed, and cancelled; while the batch is running, progress reports how far it has got.

A validation can be cancelled before any survey is asked. Call POST /audiences/{audienceId}/validations/batches/{batchId}/cancel while the batch reports canCancel: true.

Read the results

A batch contains:

FieldContent
surveysEach survey with its score, its 95% range when available, its relation to the Audience, its sourceUrl, and its question counts
notComparableSurveys that could not be compared with the Audience
combinedThe run's combined score, with its basis: whose answers it compares the Audience with
outcomeDetails of the run, including questionSelection: the questions judged, kept, and left out, each left-out question with its reason
failureThe failure code when the batch ends without a result

The score is 100 minus the mean absolute difference, in percentage points, between the Minds' answers and the published answer shares; 100 means identical answers. When available, the reported 95% range is calculated from the modelled sampling of Minds and survey respondents, widened by the measured population adjustment. It does not establish representativeness or account for every survey-design effect.

When a scored question has no stated respondent count (baseSource: "assumed"), its point comparison and existing half weight remain usable, but its range and noise-floor estimate are null. The headline range, band bounds and confidence level, and affected KPI intervals are also null. A combined or overall score retains all eligible point comparisons, but its range is null if any contributing survey lacks a range. Known-base questions and KPI families with no unknown-base contributor can still carry ranges.

This rule applies when reading older saved results as well as newly scored results. A legacy placeholder such as n: 100 on an assumed-base question is not an observed respondent count and must not be used to reconstruct uncertainty. Display the point score with an unavailable-uncertainty explanation; never turn a missing range into a zero-width range or average only the ranges that are present.

relation states who the survey asked relative to the people who define the Audience: the Audience's own people (same), a part of them, a neighbouring population (including the same kind of people surveyed in another country), or the wider population they belong to.

Each left-out question carries one of these reasons:

  • not_applicable: the Audience's people cannot answer the question, for example because it presupposes something they don't have.
  • answer_differs: the published answers are not a fair target for this Audience, because the survey's respondents differ in a way that would change the answer.
  • asked_in_another_study: the same question is already asked from a better-fitting survey.

GET /audiences/{audienceId}/validations returns every validation of the Audience in batches, newest first, together with overall, included, responses, and minds (ready and minimum). overall is the Audience's validity across whole-Audience surveys it was checked against: each survey counts once, by its latest check, weighted by the number of questions scored. overall carries the same basis as combined. For one survey's full scoring, with every KPI and question, read GET /audiences/{audienceId}/validations/{validationId}.

How surveys and questions are chosen

Surveys are ranked by who answered them relative to the people who define the Audience. Surveys of the Audience's own people come first; evidence about the wider population supports a result but never outweighs more specific surveys.

What a score is compared with

combined and overall carry basis, which says whose answers the score compares the Audience with:

basis.kindWhenHow to read it
audienceAt least 8 of the questions asked came from surveys of the Audience's own people or a part of themA comparison with these people. Wider-population surveys may add questions, never more than the specific surveys hold
wider_populationFewer did, but together with surveys of the wider population they belong to (or of the same kind of people in another place) at least 8 questions were askedA comparison with that wider population, not with the Audience's own people. confidence is lower: these comparisons have tended to score higher than comparisons with an Audience's own people

audienceQuestions counts the questions from surveys of the Audience's own people (0 means none was found), widerPopulationQuestions the questions from wider-population surveys, and comparedWith names who those surveys asked. The two kinds are never mixed in overall: while any validation of the Audience's own people exists, overall rests on those alone. Upload a survey of the Audience's own people to turn a wider-population comparison into a direct one.

Surveys of a neighbouring population never carry a score. A validation that would rest on them fails with NOT_ENOUGH_SPECIFIC_EVIDENCE before anything is asked or spent.

Every question is then checked for this Audience, one by one, before any Mind answers. A question is left out if the Audience's people cannot answer it, if the published answers are not a fair target for this Audience, or if the same question is already asked from a better-fitting survey. Where a survey publishes a question's answers by age or region, the target is narrowed to the Audience's own mix. Every left-out question is recorded with its reason.

One validation asks at most 60 questions, from at most 12 published studies, and at most 30,000 answers in total. It needs at least 8 fitting questions; below that, nothing is asked and nothing is spent.

Included validations and costs

Pay as you go includes no free validation runs. A validation consumes responses like a Study: one response per Mind per question. Existing paid subscriptions and Enterprise contracts may include validation runs under their own terms; read the authenticated allowance instead of assuming a quota from a plan name. An included run counts once, however many surveys it asks. A run that ends without a score and without spending any included answers gives its slot back.

Without an included run, automatically chosen surveys are fitted to the responses you have left. Scoring an existing Study run asks no new questions and is free.

A new private Audience is validated automatically, once, as soon as all of its Minds have finished training, if it has at least 10 Minds and its owner has an included validation left that month. Automatic validations never spend synthetic responses and send no email. Audiences that existed before automatic validation shipped are validated only when someone asks.

A validation that someone started and that runs longer than a few minutes sends that person an email when it finishes. Its View the validation button opens the Audience on its Validation tab.

Validation failure codes

A batch that ends without a result names the reason in failure, for example NOT_ENOUGH_QUESTIONS when fewer than 8 questions fit the Audience, NO_FITTING_SURVEY, or SURVEY_FILES_UNREADABLE. Audience validation failures lists all twelve codes and what each one means.

Exports

Start a branded Audience brief with POST /audiences/{audienceId}/export, poll /export-status, then download from /export-download when complete.

Compatibility

The former /groups routes remain callable during the migration window. They return Deprecation: true and a Link header naming the canonical /audiences successor. New integrations should use Audience paths and terminology exclusively.

See the exhaustive v1 endpoint reference and the live OpenAPI document.

Validate a subset of an Audience

When a survey applies to only part of an Audience, validation selects eligible Minds before asking any questions. The model considers the survey population, Audience distributions and cohort profiles, and each Mind’s profile. Missing cohort attributes are not automatic exclusions: clear individual profile evidence can support inclusion. Confirmed and supported Minds are selected; unknown or mismatching Minds are left out. At least 10 eligible, ready Minds are required; otherwise that survey is not asked.

Each survey’s respondentScope reports its population, selected and total Audience counts, and counts of confirmed, supported, unknown and excluded Minds. The match percentage compares only selected Minds’ answers with the survey results using the existing numeric scoring formula. It is not a model-assigned score or an estimate of how many people qualify. Subset scores remain attached to the Audience and are excluded from its overall and batch combined scores. Response costs use the selected Minds per question. A Mind shared by several Audiences is evaluated within each Audience’s validation context.

Customer-authorized support

Owners authorize a verified Minds staff member to amend one Audience’s composition for a limited time. Access can be revoked, and the actual staff actor, requested change and outcome remain available in the support history.

Only the current Audience owner can grant or revoke access. Choose a different, confirmed getminds.ai staff account, a reason and an expiry within 30 days. Reuse the same UUID requestKey and identical grant inputs after a timeout; a replay does not renew expired or revoked access. Staff cannot issue their own grants.

Support permits composition amendments only, through the existing recalibration endpoint. It grants no workspace membership, deletion, ownership transfer, member growth, source upload, Go deeper, shared-Mind waiver or billing change. Existing member-ownership, shared-Mind and active-Study safeguards still apply. The customer remains the resource owner; the actual staff actor and requested instruction or selected percentages are recorded.

Revocation, expiry, ownership transfer or loss of verified staff status prevents subsequent work at checkpoints. An in-flight atomic step may finish; completed changes are retained. A 202 response accepts an operation and does not mean the amendment is complete. Poll its status URL until completed or failed; a failed status read must not trigger another amendment.

POST   /audiences/{audienceId}/support
GET    /audiences/{audienceId}/support
DELETE /audiences/{audienceId}/support/{grantId}
GET    /audiences/{audienceId}/support/activity
GET    /support/audiences
{
  "staffEmail": "[email protected]",
  "reason": "Requested composition amendment",
  "expiresAt": "2026-10-20T12:00:00Z",
  "requestKey": "f5d4d4ca-52c7-4b4b-bb8f-15c05d35d231"
}

GET → { "data": { "grants": [], "nextCursor": null } }

activity → { "data": { "operations": [], "nextCursor": null } }

nextCursor → ?cursor={nextCursor} (50 grants / 10 operations).

Minds© 2026 Minds. جمهورك المستهدف. مدعوم بالذكاء الاصطناعي ومستند إلى أدلة شفافة. جاهز في دقائق.
Minds جزء من
ESOMARGreenBookInsight PlatformsCapterraG2CSSDA Best UX Design AwardCSSDA Best Innovation AwardCSSDA Best UI Design Award