openapi: 3.2.0 info: title: Minds Public Audiences API version: v1 description: 'OpenAPI 3.1.0 spec for the Minds public API (https://getminds.ai/api/v1 / https://api.getminds.ai/v1). Generate a typed TypeScript client by running an OpenAPI generator (e.g. `openapi-typescript`) against `/_openapi.json`. Auth: send `Authorization: Bearer minds_…_key`; create keys in Settings → API Keys.' servers: - url: https://api.getminds.ai description: Production (api subdomain) - url: https://getminds.ai description: Production (apex) security: - ApiKeyAuth: [] tags: - name: Audiences paths: /api/v1/audiences/{audienceId}: delete: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid responses: '204': description: The Audience and its orphan-only member Minds were deleted. '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Audience not found`: the Audience does not exist or the caller is not its owner.' operationId: deleteAudience summary: Delete an Audience description: Permanently deletes an Audience. Owner only; collaborators and viewers receive 404. The deletion cascades to member Minds that the caller owns and that belong to no other Audience, so those Minds (with their training data and Study links) are removed too. Minds owned by other users, and Minds that are also members of another Audience, are kept. Remove Minds you want to keep with `DELETE /audiences/{audienceId}/members/{mindId}` first, or add them to another Audience. tags: - Audiences security: - ApiKeyAuth: [] get: parameters: - in: query name: members description: Use preview for bounded display profiles without reviewed-field metadata; omitted preserves the complete legacy detail response. schema: type: string enum: - preview - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid responses: '200': description: The Audience detail. content: application/json: schema: type: object required: - data properties: data: $ref: '#/components/schemas/AudienceDetail' '400': description: '`Audience ID is required` or `Invalid audience ID format` (the path parameter is not a UUID).' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Audience not found`: the Audience does not exist or the caller cannot view it.' operationId: getAudience summary: Get an Audience description: 'Returns one Audience with its member Minds (each with its cohort profile), the caller''s role, the stored grounding, the source bundle (brief, adjustments, keywords, links, files), member-derived baseline distributions, and the transient recalibration state. Use it to inspect an Audience before attaching it to a Study, to poll `calibration.active` after `POST /audiences/{audienceId}/recalibrate`, or to watch member `profileImageUrl` values arrive after `regenerate-images`. Formations are not embedded; list them with `GET /audiences/{audienceId}/formations`. Readable by the owner, direct members, members of the owner''s team when the Audience is team-shared, any authenticated caller when the Audience is public, and members of a Study that contains the Audience. Setting `isSharedWithTeam: true` lets every member of the owner''s team open the Audience and read and chat with every Mind in it, even when those Minds are not shared individually; it grants no edit rights on the Minds. Explicit Audience members get the same read access. Only collaborators (owner, direct member, team member) receive the sharing fields `isSharedWithTeam`, `isLinkSharingEnabled` and `publicShareId`; public and Study-cascade viewers get `currentMemberRole: public_viewer`, and uploaded-file URLs in `sources` and `grounding.sources` are redacted for them.' tags: - Audiences security: - ApiKeyAuth: [] put: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid responses: '200': description: The updated Audience. content: application/json: schema: type: object required: - data properties: data: type: object required: - id - name - mindCount - minds - createdAt - updatedAt - isPublic - isSharedWithTeam - isLinkSharingEnabled - publicShareId - currentMemberRole properties: id: type: string format: uuid name: type: string mindCount: type: integer minimum: 0 minds: type: array items: $ref: '#/components/schemas/AudienceMindSummary' createdAt: type: string format: date-time updatedAt: type: string format: date-time isPublic: type: boolean isSharedWithTeam: type: boolean isLinkSharingEnabled: type: boolean publicShareId: type: - string - 'null' currentMemberRole: type: string enum: - owner - admin - member - team_member '400': description: '`name is required` (missing or blank name), `Audience ID is required`, or `Invalid audience ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Audience not found`: the Audience does not exist or the caller has no edit access (public and Study-link viewers included).' operationId: updateAudience summary: Update an Audience name and sharing settings description: 'Renames an Audience and optionally changes its visibility. `name` is required on every call; `isPublic` and `isSharedWithTeam` are applied only when sent as booleans and left unchanged otherwise. `isLinkSharingEnabled` cannot be changed here (it is echoed in the response). Allowed for collaborators: the owner, direct members, and members of the owner''s team when the Audience is team-shared. Public and Study-link viewers receive 404. Setting `isSharedWithTeam: true` lets every member of the owner''s team open the Audience and read and chat with every Mind in it, even when those Minds are not shared individually; it grants no edit rights on the Minds. Explicit Audience members get the same read access. Setting `isPublic: true` lists the Audience in the marketplace and queues a cover image for it.' tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string minLength: 1 description: New Audience name; surrounding whitespace is trimmed. Required even when only sharing flags change. isPublic: type: boolean description: List the Audience publicly. Anyone signed in can then open it and its Minds. isSharedWithTeam: type: boolean description: Share with every member of the owner's team. Grants read-and-chat access to all member Minds; no edit rights on the Minds. examples: rename: value: name: German SaaS buyers (2026) shareWithTeam: value: name: German SaaS buyers isSharedWithTeam: true /api/v1/audiences/{audienceId}/export-download: get: parameters: - in: path name: audienceId required: true schema: type: string format: uuid responses: '200': description: Audience export artifact. operationId: downloadAudienceExport summary: Download an Audience export tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/{audienceId}/export-status: get: parameters: - in: path name: audienceId required: true schema: type: string format: uuid responses: '200': description: Audience export status. operationId: getAudienceExportStatus summary: Get Audience export status tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/{audienceId}/export: post: parameters: - in: path name: audienceId required: true schema: type: string format: uuid responses: '200': description: Cached artifact or queued export job. operationId: exportAudienceBrief summary: Export an Audience brief tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/{audienceId}/follow: delete: parameters: - name: audienceId in: path required: true schema: type: string responses: '200': description: Audience unfollowed. '401': description: Unauthorized. operationId: unfollowAudience summary: Unfollow a public Audience tags: - Audiences security: - ApiKeyAuth: [] post: parameters: - name: audienceId in: path required: true schema: type: string responses: '200': description: Audience followed. '401': description: Unauthorized. '404': description: Public Audience not found. operationId: followAudience summary: Follow a public Audience tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/{audienceId}/formations/{formationId}: delete: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid - name: formationId in: path required: true description: Formation ID (UUID). schema: type: string format: uuid responses: '204': description: The Formation was deleted. '400': description: '`Audience ID is required`, `Invalid audience ID format`, `Formation ID is required`, or `Invalid formation ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Formation not found`: the Audience is not viewable, or the Formation does not exist, is already deleted, or is not mutable by the caller.' operationId: deleteFormation summary: Delete a Formation description: Soft-deletes a Formation so it disappears from listings while Study messages that referenced it keep rendering. Collaborators may delete shared Formations and their own private ones; other viewers may delete only Formations they created privately. A Formation the caller cannot mutate yields 404. tags: - Audiences security: - ApiKeyAuth: [] get: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid - name: formationId in: path required: true description: Formation ID (UUID). schema: type: string format: uuid responses: '200': description: The Formation detail. content: application/json: schema: type: object required: - data properties: data: $ref: '#/components/schemas/Formation' '400': description: '`Audience ID is required`, `Invalid audience ID format`, `Formation ID is required`, or `Invalid formation ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Formation not found`: the Audience is not viewable, or the Formation does not exist, was deleted, or is private to another viewer.' operationId: getFormation summary: Get a Formation with its subgroups and members description: 'Returns one Formation: build status, live build progress, the stored hypothesis, and the real subgroups with their member assignments and confidences. Poll this after `POST /formations`, `POST /formations/preview` acceptance, or `recompute` until `status` is `ready` or `failed`; while `building`, `subgroups` may be empty and `hypothesis.subgroups` describes the proposed buckets. Visible to any Audience viewer for shared Formations and to the creator for private ones.' tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/{audienceId}/formations/{formationId}/recompute: post: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid - name: formationId in: path required: true description: Formation ID (UUID). schema: type: string format: uuid responses: '200': description: The rebuild was queued. content: application/json: schema: type: object required: - data properties: data: type: object required: - id - status properties: id: type: string format: uuid status: type: string enum: - building - ready - failed description: Usually `building`; already terminal when the build ran inline. '400': description: '`Audience ID is required`, `Invalid audience ID format`, `Formation ID is required`, or `Invalid formation ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Formation not found`: the Audience is not viewable, or the Formation does not exist, is deleted, or is not mutable by the caller.' operationId: recomputeFormation summary: Re-sort the current members into an existing Formation description: 'Re-classifies the Audience''s current members against the Formation''s stored hypothesis and swaps the subgroups in place, without a new preview. Use it after members were added or recalibrated, or to recover a Formation stuck in `building` or `failed`. Flips `status` to `building` and returns immediately; poll `GET /audiences/{audienceId}/formations/{formationId}`. Same mutability rules as delete: collaborators for shared Formations, creators for private ones.' tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/{audienceId}/formations: get: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid responses: '200': description: Visible Formations. content: application/json: schema: type: object required: - data properties: data: type: array items: $ref: '#/components/schemas/FormationSummary' '400': description: '`Audience ID is required` or `Invalid audience ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Formation not found`: the Audience does not exist or the caller cannot view it (the message deliberately does not reveal which).' operationId: listFormations summary: List the Formations of an Audience description: 'Lists the Formations (persisted segmentations) visible to the caller on an Audience: shared Formations plus the caller''s own private ones, newest first, each with its subgroups and membership counts. Soft-deleted Formations are excluded. Anyone who can view the Audience may call this. Opening the list also seeds the canonical default and grounding-derived Formations for collaborators and re-queues stalled builds, so rows may come back with `status: building`; poll `GET /audiences/{audienceId}/formations/{formationId}` until they are `ready` or `failed`. Only one row per auto dimension is returned (ready preferred over building over failed).' tags: - Audiences security: - ApiKeyAuth: [] post: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid responses: '200': description: The Formation was created and its build queued. content: application/json: schema: type: object required: - data properties: data: type: object required: - id - name - status properties: id: type: string format: uuid name: type: string status: type: string enum: - building - ready - failed '400': description: '`Invalid hypothesis` (needs `intent` and 2 to 15 subgroups with `id`, `label`, `definition`), `Audience has no members to categorize`, `FORMATION_CAP` (more than 1000 members), `Audience ID is required`, or `Invalid audience ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Formation not found`: the Audience does not exist or the caller cannot view it.' operationId: createFormation summary: Create a Formation from an accepted hypothesis description: 'Creates a Formation from a hypothesis (the subgroup proposal returned by `POST /audiences/{audienceId}/formations/preview`, optionally edited) and starts sorting the Audience''s members into its subgroups. Returns immediately with `status: building`; poll `GET /audiences/{audienceId}/formations/{formationId}` until `ready` or `failed`. When the build runs inline the returned status may already be terminal. Any Audience viewer may create a Formation: collaborators create `shared` Formations, other viewers create ones private to themselves. The Audience must have at least one member and at most 1000.' tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: - hypothesis properties: hypothesis: $ref: '#/components/schemas/FormationHypothesis' name: type: string description: Optional display name. Defaults to a compact form of `hypothesis.intent`. examples: byGender: value: name: By gender hypothesis: intent: Audience by gender subgroups: - id: female label: Female definition: Members who identify as women. - id: male label: Male definition: Members who identify as men. /api/v1/audiences/{audienceId}/formations/preview: post: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid - name: Accept in: header required: false description: Include `application/json` to get a single JSON response instead of the NDJSON stream. schema: type: string enum: - application/json - application/x-ndjson responses: '200': description: The proposed hypothesis, either as one JSON document or as an NDJSON event stream. content: application/json: schema: type: object required: - success - data properties: success: type: boolean enum: - true data: type: object required: - memberCount - softWarn - hardCapExceeded - phase - hypothesis properties: memberCount: type: integer minimum: 0 softWarn: type: boolean description: 'True from 50 members: builds take noticeably longer.' hardCapExceeded: type: boolean description: 'True above 1000 members: `POST /formations` will refuse with `FORMATION_CAP`.' phase: type: string enum: - hypothesizing hypothesis: $ref: '#/components/schemas/FormationHypothesis' application/x-ndjson: schema: type: object description: One event per line. required: - type properties: type: type: string enum: - meta - status - subgroups - error - done data: description: '`meta`: `{ memberCount, softWarn, hardCapExceeded }`; `status`: `{ phase: "hypothesizing" }`; `subgroups`: a FormationHypothesis. Absent on `error` and `done`.' oneOf: - type: object required: - memberCount - softWarn - hardCapExceeded properties: memberCount: type: integer softWarn: type: boolean hardCapExceeded: type: boolean - type: object required: - phase properties: phase: type: string enum: - hypothesizing - $ref: '#/components/schemas/FormationHypothesis' error: type: string description: Failure message; only on `error` events. '400': description: '`Audience ID is required` or `Invalid audience ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Formation not found`: the Audience does not exist or the caller cannot view it.' '500': description: 'JSON mode only: the model could not propose subgroups (`Failed to propose subgroups` or the underlying error message). In NDJSON mode the same failure arrives as an in-band `error` event with HTTP 200.' operationId: previewFormation summary: Propose Formation subgroups without creating anything description: 'Asks the model to propose a subgroup hypothesis for this Audience from a free-text request (e.g. "split by purchase frequency"). Nothing is persisted; pass the returned hypothesis (edited if you like) to `POST /audiences/{audienceId}/formations` to build it, or re-post with `priorHypothesis` set to the previous proposal to request a rework. Any Audience viewer may call this. Send `Accept: application/json` to receive one JSON document; otherwise the response is a newline-delimited JSON stream (`application/x-ndjson`) of `{ type, data }` events in the order `meta`, `status`, `subgroups`, `done`, with failures reported in-band as `{ type: "error", error }` followed by `done`.' tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: false content: application/json: schema: type: object properties: userInput: type: string description: What to split by. Defaults to "Split this audience into meaningful subgroups." priorHypothesis: allOf: - $ref: '#/components/schemas/FormationHypothesis' description: The previous proposal when asking for a rework; invalid values are ignored. examples: first: value: userInput: Split by how often they buy online /api/v1/audiences/{audienceId}/members: post: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid responses: '200': description: The Minds were added (or were already members). content: application/json: schema: type: object required: - data properties: data: type: object required: - added properties: added: type: integer minimum: 1 description: Number of distinct Mind IDs in the request. '400': description: '`mindId or mindIds is required`, `At least one Mind ID is required` (empty array), a retired field name (rejected with a message naming its replacement), `Audience ID is required`, or `Invalid audience ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '403': description: Adding these Minds would exceed the plan's Audience member cap. `statusMessage` names the plan and the limit; `data` carries the plan-limit envelope. content: application/json: schema: $ref: '#/components/schemas/PlanLimitError' '404': description: '`Audience not found` (missing, or the caller is not the owner), or `One or more Minds not found or not accessible` (a Mind is neither owned by the caller nor public). Nothing is added in either case.' operationId: addAudienceMembers summary: Add Minds to an Audience description: Adds one Mind (`mindId`) or several Minds (`mindIds`) to an Audience. Owner only; collaborators and viewers receive 404. Every Mind must be owned by the caller or public, otherwise nothing is added. Minds that are already members are ignored, so the call is idempotent; `added` reports the number of distinct IDs in the request, not the number of new memberships. Newly added Minds are sorted into the Audience's ready Formations in the background, and default Formations are seeded if the Audience had none. Use `mindIds` rather than the retired `mindId`/`mindIds` fields. tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object description: Send either `mindId` or `mindIds`. When both are present `mindId` wins. properties: mindId: type: string format: uuid description: A single Mind to add. mindIds: type: array minItems: 1 items: type: string format: uuid description: Several Minds to add. Duplicate IDs are deduplicated. examples: single: value: mindId: 6f1d2c3a-1111-4222-8333-444455556666 bulk: value: mindIds: - 6f1d2c3a-1111-4222-8333-444455556666 - 0a9b8c7d-2222-4333-8444-555566667777 /api/v1/audiences/{audienceId}/members/{mindId}: delete: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid - name: mindId in: path required: true description: Mind ID (UUID). schema: type: string format: uuid responses: '204': description: The Mind is no longer a member of the Audience. '400': description: '`Audience ID is required`, `Invalid audience ID format`, `Mind ID is required`, or `Invalid mind ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Audience not found`: the Audience does not exist or the caller is not its owner.' operationId: removeAudienceMember summary: Remove a Mind from an Audience description: Removes one Mind from an Audience and from every Formation subgroup on that Audience. The Mind itself is not deleted. Owner only; collaborators and viewers receive 404. Removing a Mind that is not a member is a no-op that still returns 204. tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/{audienceId}/progress: get: parameters: - name: audienceId in: path required: true schema: type: string responses: '200': description: Current member progress snapshot. '401': description: Unauthorized. '404': description: Audience not found. operationId: getAudienceProgress summary: Get the current creation progress for an Audience tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/{audienceId}/recalibrate: post: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid responses: '200': description: Grounding and member profiles were updated. Member retraining and new-member training continue in the background. content: application/json: schema: type: object required: - data properties: data: type: object required: - grounding - refreshedMembers - evolvedMembers - retrainingMembers - addedMembers properties: grounding: type: object required: - distributions - sources - summary - confidence - appliedToPersonas - allocationConfig - allocationAudit properties: distributions: type: array items: $ref: '#/components/schemas/GroundingDistribution' reviewDistributions: type: array items: $ref: '#/components/schemas/GroundingDistribution' sources: type: array items: $ref: '#/components/schemas/GroundingSource' summary: type: - string - 'null' confidence: type: number minimum: 0 maximum: 1 suggestedMinAudienceSize: type: integer appliedToPersonas: type: boolean allocationConfig: type: - object - 'null' allocationAudit: type: - object - 'null' hardConstraints: oneOf: - $ref: '#/components/schemas/GroundingHardConstraints' - type: 'null' refreshedMembers: type: integer minimum: 0 description: Members rebuilt in place with a new persona and portrait because their new segment contradicted their identity. evolvedMembers: type: integer minimum: 0 description: Members that kept name and portrait but received a new role and description (non-visual axis change). retrainingMembers: type: integer minimum: 0 description: Rebuilt plus evolved members whose knowledge is being retrained in the background. addedMembers: type: integer minimum: 0 description: New members created by an additive instruction; their training is queued. '400': description: '`Invalid recalibrate payload` (schema violation), `Invalid distributions payload` (selection mode produced no usable distributions), `Audience ID is required`, or `Invalid audience ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '403': description: An additive instruction with an explicit count exceeds the plan's Audience member cap, the Audience is already at the cap, or the plan's overall Mind quota would be exceeded. `data` carries the plan-limit envelope. content: application/json: schema: $ref: '#/components/schemas/PlanLimitError' '404': description: '`Audience not found`: the Audience does not exist or the caller is not its owner.' '409': description: '`A recalibration is already running for this audience. Wait for it to finish and try again.`, or a refusal with `data.code: AUDIENCE_MINDS_SHARED` listing the members that also belong to other Audiences (retry with `allowSharedMinds: true` or remove them first).' content: application/json: schema: type: object properties: statusCode: type: integer enum: - 409 statusMessage: type: string data: type: object properties: code: type: string enum: - AUDIENCE_MINDS_SHARED sharedMinds: type: array items: type: object required: - mindId - mindName - otherAudiences properties: mindId: type: string format: uuid mindName: type: string otherAudiences: type: array items: type: object required: - id - name properties: id: type: string format: uuid name: type: string '422': description: 'Research mode: `Could not find sufficient scientific data to ground this audience. Try a more specific description.` or `The requested distribution could not be added.`; selection mode on an Audience without stored grounding: `This audience has no grounding to recalibrate. Run a research recalibration first.`' '500': description: The run failed after it started; the calibration marker is cleared so a retry is possible. operationId: recalibrateAudience summary: Recalibrate an Audience's grounding and members description: 'Refreshes the stored grounding of a saved Audience and re-allocates its members to the resulting distributions. Owner only. Two modes: research mode (default) re-runs deep research from the persisted brief, every earlier adjustment and the optional `instruction`, `sources` and `requestedDistribution`, or from `query` as a full override; selection mode (`distributions` present) skips research and only replaces the active distribution set, keeping the stored sources and review universe. In research mode the instruction is classified first: an adjustment ("make men 40%", "now they are all vegan", "only 50 to 60 years old") re-allocates the existing roster and rebuilds or evolves the members whose new segment contradicts who they are, while an additive instruction ("and now add 10 African consumers") keeps the existing members untouched and creates new ones within the plan''s member cap. The request is synchronous for the grounding and the roster change; member retraining continues in the background. Poll `GET /audiences/{audienceId}/progress` for per-member training and `GET /audiences/{audienceId}` for `calibration.active`. Only one recalibration may run per Audience at a time. Because recalibration rewrites the members'' profiles and knowledge globally, it is refused with 409 `AUDIENCE_MINDS_SHARED` when members also belong to other Audiences unless `allowSharedMinds: true` is sent (additive runs are exempt).' tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: false content: application/json: schema: type: object properties: query: type: string maxLength: 4000 description: Research mode. Full override of the research query; the persisted brief and adjustments are ignored and nothing is persisted for replay. instruction: type: string maxLength: 4000 description: Research mode. Adjustment appended to the replayed brief, e.g. "add an income distribution" or "skew younger". Persisted so later recalibrations replay it (additive instructions are stored declaratively). requestedDistribution: type: string minLength: 1 maxLength: 120 description: Research mode. Topic of exactly one distribution to add. Guaranteed to materialise (as an assumed-evidence axis when research finds no data); the existing axes and targets are preserved. sources: type: - object - 'null' description: Research mode. Extra user sources, persisted to the Audience's source bundle and cited by the research run. Each list holds at most 20 entries. properties: files: type: array maxItems: 20 items: type: object required: - name - url properties: name: type: string maxLength: 300 url: type: string maxLength: 2000 description: URL of an already uploaded file. links: type: array maxItems: 20 items: type: string maxLength: 2000 keywords: type: array maxItems: 20 items: type: string maxLength: 200 distributions: type: array description: Selection mode. The complete active distribution set after a select/deselect edit of the saved review universe. Presence of this field (even empty) selects selection mode. items: $ref: '#/components/schemas/GroundingDistribution' allowSharedMinds: type: boolean description: Accept that members shared with other Audiences are rewritten there too. Required to proceed when the 409 `AUDIENCE_MINDS_SHARED` refusal was returned. examples: adjust: value: instruction: Make it 60% women and skew younger addDistribution: value: requestedDistribution: Preferred furniture materials grow: value: instruction: And now add 10 consumers from Nigeria selection: value: distributions: - name: Gender distribution: - label: Female pct: 60 sourceIdx: 0 - label: Male pct: 40 sourceIdx: 0 /api/v1/audiences/{audienceId}/regenerate-images: post: parameters: - name: audienceId in: path required: true description: Audience ID (UUID). schema: type: string format: uuid responses: '200': description: Summary of what was queued. content: application/json: schema: type: object required: - data properties: data: type: object required: - audienceId - totalMembers - candidates - enqueued - skipped - errors - dry - sample properties: audienceId: type: string format: uuid totalMembers: type: integer minimum: 0 candidates: type: integer minimum: 0 description: Members matching the filter (missing portrait, or all when `force`), after `limit`. enqueued: type: integer minimum: 0 description: Jobs actually queued; 0 on a dry run. skipped: type: integer minimum: 0 description: Members left alone because they already have a portrait. errors: type: integer minimum: 0 description: Members whose job could not be queued. dry: type: boolean sample: type: array maxItems: 10 description: The first up to 10 queued (or, on a dry run, candidate) Minds. items: type: object required: - id - name properties: id: type: string format: uuid name: type: string '400': description: '`Audience ID is required` or `Invalid audience ID format`.' '401': description: Missing or invalid API key (`Unauthorized`). '404': description: '`Audience not found`: the Audience does not exist or the caller is not its owner.' operationId: regenerateAudienceImages summary: Queue profile-image generation for the Minds in an Audience description: 'Bulk-enqueues portrait generation for the member Minds of an Audience. Owner only. By default only members without a `profileImageUrl` are queued; `force: true` clears and regenerates existing portraits too. Fire-and-forget: the response returns as soon as the jobs are queued, and images arrive asynchronously; poll `GET /audiences/{audienceId}` (member `profileImageUrl`) or `GET /minds/{mindId}`. Use `dry: true` to see what would be queued without queuing anything.' tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: false content: application/json: schema: type: object properties: force: type: boolean default: false description: Regenerate even for Minds that already have a portrait (their current URL is cleared first). limit: type: integer minimum: 1 description: Cap the number of Minds queued in this call (oldest members first). No cap by default. dry: type: boolean default: false description: Report the candidates without enqueueing. examples: missingOnly: value: {} forceFirstTen: value: force: true limit: 10 /api/v1/audiences/active-progress: get: parameters: [] responses: '200': description: Active Audience progress snapshots. '401': description: Unauthorized. operationId: listActiveAudienceProgress summary: List active Audience creation progress tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/allocation-preview: post: parameters: [] responses: '200': description: Deterministic allocation preview. '400': description: Invalid count or distributions. '401': description: Missing or invalid API key. operationId: previewCohortAllocation summary: Preview deterministic cohort allocation description: Convert marginal distributions into exact integer quotas and deterministic member profiles without creating an Audience. This is the contract intended for API clients and future product UI controls. tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: - memberCount properties: memberCount: type: integer minimum: 1 maximum: 1000 seedBasis: type: string maxLength: 1000 distributions: type: array maxItems: 200 items: $ref: '#/components/schemas/GroundingDistribution' cohortAllocation: type: object reviewedGroundingJson: type: string description: Unchanged reviewed snapshot. Its rules and axis metadata are retained. reviewedGroundingSha256: type: string researchStudyAnalysis: type: object description: Questionnaire analysis including routing rules, when sending distributions directly. /api/v1/audiences/from-brief: post: parameters: - name: Idempotency-Key in: header required: false schema: type: string description: 'Retry-safety key, max 200 chars (also accepted as the `idempotencyKey` body field; the header wins). Creation can exceed typical client timeouts — retrying with the same key within 6 hours returns the audience the original request created (200, `replayed: true`) instead of creating a duplicate.' - name: Prefer in: header required: false schema: type: string enum: - respond-async description: Return 202 after durable admission and run the complete build on the processor. responses: '200': description: 'Either an idempotent replay (the supplied idempotency key already created an audience within the replay window; returns that audience with `replayed: true`, nothing new is created, no plan allowances are consumed, `datasetSegmentation` is not reconstructed) or a saved-snapshot/internal `groundingPreview` result containing reviewed grounding, checksum, effective cohortAllocation audit, flags, and size with no Audience or Minds created.' content: application/json: schema: type: object required: - data properties: data: $ref: '#/components/schemas/AudienceFromBriefResult' '201': description: Grounded audience created. content: application/json: schema: type: object required: - data properties: data: $ref: '#/components/schemas/AudienceFromBriefResult' '202': description: Creation or a fresh public grounding preview accepted by the processor, including when async is omitted or false. Saved-snapshot previews also return 202 when explicitly requested asynchronously. Poll `data.statusUrl` until completed or failed; `data.result` contains the same completed response as a synchronous request. content: application/json: schema: type: object required: - data properties: data: type: object required: - jobId - status - progress - statusUrl properties: jobId: type: string format: uuid status: type: string enum: - queued - processing - completed progress: type: integer minimum: 0 maximum: 100 statusUrl: type: string '400': description: Missing `text`, text too long, or invalid input. '401': description: Missing or invalid API key. '403': description: 'Plan limit reached (`code: PLAN_LIMIT`), or an explicit count above the 20-Mind balanced-mode ceiling (`code: MODE_CAP` — use `segment_coverage` or `benchmark_depth`).' '409': description: An idempotency key is already in progress or was reused with a different explicit member count, or the reviewed grounding checksum does not match. '422': description: No personas could be derived from the brief. '500': description: Internal server error. operationId: createAudienceFromBrief summary: Create a grounded audience from a brief description: Create one Audience from a free-text brief. Attached research files use the same extended screener/questionnaire analysis as the in-app New Audience flow, including Study roles, screening and quota rules, review distributions, and grounding provenance. Public bearer-authenticated V1 requests return `202 Accepted`; poll the returned status URL until the durable processor operation completes. tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: - text properties: text: type: string minLength: 1 maxLength: 200000 description: Free-text brief describing the audience or population to represent. name: type: string description: Optional audience name override. When omitted, the server names the audience from the brief or detected personas. files: type: array description: Already-uploaded research files analyzed through the same extended Audience study-ingestion path as the in-app New Audience uploader. items: type: object required: - name - url properties: name: type: string url: type: string links: type: array description: URLs to scrape for additional context. items: type: string keywords: type: array description: Search keywords used as extra context and research seeds. items: type: string includeWebSearch: type: boolean default: true description: When false, skips Exa search/extraction completely and grounds only on the supplied brief, files, links, keywords, and structurally parsed respondent data. isLinkSharingEnabled: type: boolean description: Enable public link sharing for the created audience. generateImages: type: boolean default: true description: Generate AI profile images and an audience cover asynchronously. Pass false to keep fallback visuals and avoid all image-model calls for this creation. trainMembers: type: boolean default: true deprecated: true description: 'Deprecated; omit it. Every member of every Audience is individually trained in the background, including large reviewed-dataset cohorts (> 40 Minds), through the same per-member pipeline the in-app flow uses, keeping each Mind''s deterministic cohort profile and the request locale. `true` is accepted as a no-op; `false` is rejected with 400 `TRAIN_MEMBERS_OPT_OUT_REMOVED` (it used to create untrained Minds with an empty system prompt that reported ready). Cost and time: each member consumes one Mind training (research, knowledge and prompt generation); a 100-Mind cohort typically finishes over tens of minutes to a few hours, staggered per Audience. The response returns as soon as the Audience exists; poll GET /api/v1/minds/{mindId}/training per member (or the Audience progress endpoint) and wait for every member to report readyToChat before running a Study — Study runs refuse Audiences with untrained members.' idempotencyKey: type: string maxLength: 200 description: Retry-safety key (same semantics as the `Idempotency-Key` header, which wins when both are sent). Reusing the key within 6 hours replays the audience it created instead of duplicating it. async: type: boolean description: Optional async hint for internal cookie-authenticated callers. Public bearer-authenticated V1 requests are always enqueued and return a pollable 202 operation. groundingPreview: type: boolean default: false description: 'Review the quota axes before any Mind exists. When true the request runs research grounding plus a deterministic allocation preview and returns the reviewed grounding, checksum, effective cohortAllocation audit, flags, and size without creating an Audience or Minds or consuming generation allowance. Fresh public previews always return a durable 202 operation, including when `async` is omitted or false. Saved-snapshot previews may return inline; send `async: true` or `Prefer: respond-async` to queue those too. Poll its status URL for the same preview result. Explicit allocation targets that cannot match the grounded axes fail closed with 422, just like creation. Axes that measure the Study outcome itself are demoted to supplementary context and listed in `flaggedDistributions`.' reviewedGroundingJson: type: string description: Exact reviewed grounding snapshot returned by a prior preview. Send it unchanged with reviewedGroundingSha256 to re-preview revised exclusions/allocation options against the same evidence, or to create from the latest accepted preview without rerunning grounding research. reviewedGroundingSha256: type: string pattern: ^[0-9a-fA-F]{64}$ description: SHA-256 returned with reviewedGroundingJson. Both fields are required together; creation fails before materialisation when the checksum does not match. excludeDistributions: type: array maxItems: 200 items: type: string description: Exact axis names whose composition quotas should be removed. Age remains as one eligibility range without within-range shares; explicit gender membership remains enforced. Include required eligibility axes in cohortAllocation.distributionNames. Original evidence stays in reviewDistributions. memberCount: type: integer minimum: 1 maximum: 1000 description: Exact number of Minds to create. Wins over any count parsed from `text` and over grounding suggestions, while remaining subject to the effective plan and creation-mode caps. audienceCreationMode: type: string enum: - balanced - segment_coverage - benchmark_depth deprecated: true description: Deprecated alias for `audienceCreationMode`. If both fields are supplied, their values must match. datasetSegmentation: type: object description: 'Reviewed research-variable roles, distributions, privacy-safe pairwise relationships, and deterministic dependencies (recodes and questionnaire routing filters) returned by the segmentation-preview endpoint. Pass `functionalDependencies` and `dependencyDiscovery` through unchanged: the first are hard constraints, so a synthetic respondent never breaks a recode and a filtered question stays unanswered at the source rate; the second reports which discovery bounds applied and is echoed into `cohortAllocation.audit.jointConsistency`. Omitting it does not disable enforcement, but the audit will say the bounds are unknown. Requires Team plus `benchmark_depth`. Structural variables shape a representative cohort; outcomes remain held out and observed joint combinations remain audit evidence rather than respondent-like Minds.' cohortAllocation: type: object description: Deterministic allocation controls. Grounded marginals are converted into exact integer quotas server-side; the LLM does not decide proportions. Omit for deterministic defaults. properties: enabled: type: boolean default: true seed: type: string maxLength: 200 distributionNames: type: array maxItems: 500 items: type: string maxDistributions: type: integer minimum: 1 maximum: 500 default: 500 minSegmentCount: type: integer minimum: 0 maximum: 20 default: 0 targetOverrides: type: array maxItems: 500 description: Partial or full target-percentage overrides. Unspecified segments keep their source percentages; the audit preserves sourcePct and normalizedTargetPct separately. items: type: object required: - distribution - segments properties: distribution: type: string segments: type: array items: type: object required: - label - pct properties: label: type: string pct: type: number minimum: 0 maximum: 100 jointStrategy: type: string enum: - independent - aligned - observed default: independent includeProfilesInResponse: type: boolean default: false examples: demographicAudience: summary: Create an Audience value: text: Berlin Spati customers who buy late-night snacks name: Berlin Spati Customers links: - https://example.com/customer-research keywords: - Berlin convenience store demographics /api/v1/audiences/from-brief/jobs/{jobId}: get: parameters: - name: jobId in: path required: true schema: type: string responses: '200': description: Current operation state and, when terminal, its result or error. '401': description: Missing or invalid API key. '404': description: Operation not found or not owned by the caller. operationId: getAudienceFromBriefCreationJob summary: Get a from-brief Audience preview or creation operation description: Poll the durable operation returned by an asynchronous from-brief preview or creation request. A completed preview returns its reviewed grounding and checksum without creating an Audience or Minds. tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/from-brief/segmentation-preview: post: parameters: [] responses: '200': description: Complete variable distribution review. '400': description: Unsupported, empty, or invalid spreadsheet. '401': description: Missing or invalid authentication. '403': description: Enterprise dataset segmentation review requires Team. '413': description: Dataset exceeds the explicit review limit; no partial preview is returned. operationId: previewAudienceDatasetSegmentation summary: Preview spreadsheet segmentation distributions description: Enterprise review step for grounded audience creation. Classifies respondent-level XLS/XLSX/CSV fields by research role, selects population and segmentation variables while holding outcomes and drivers out, and discovers privacy-safe pairwise relationships. Questionnaire/programming grids are rejected as design evidence instead of being misrepresented as completed respondents. Joint profiles are counted for audit only; rows are never silently sampled. tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: - file properties: file: type: object required: - name - url properties: name: type: string url: type: string segmentationColumns: type: array items: type: string description: Column keys returned by an earlier preview. Omit to select every non-identifier column. /api/v1/audiences: get: parameters: - name: limit in: query schema: type: integer minimum: 1 maximum: 100 default: 100 - name: offset in: query schema: type: integer minimum: 0 default: 0 responses: '200': description: Visible Audiences with member readiness and pagination. content: application/json: schema: type: object required: - data - pagination properties: data: type: array items: type: object required: - id - name - mindCount - minds - currentMemberRole properties: id: type: string name: type: string mindCount: type: integer minimum: 0 minds: type: array items: type: object currentMemberRole: type: string enum: - owner - admin - member - team_member - public_viewer pagination: type: object required: - total - limit - offset properties: total: type: integer minimum: 0 limit: type: integer minimum: 1 maximum: 100 offset: type: integer minimum: 0 '401': description: Authentication required. operationId: listAudiences summary: List visible Audiences description: Lists owned, public, directly shared, and team-shared Audiences. Sharing fields are returned only when the caller has collaborator access. tags: - Audiences security: - ApiKeyAuth: [] post: parameters: - name: x-minds-idempotency-key in: header required: false description: Reuse for retries of the same creation. Blank keys and keys longer than 128 characters are ignored. schema: type: string maxLength: 128 responses: '200': description: Idempotent replay of the saved Audience. content: application/json: schema: $ref: '#/components/schemas/SavedAudienceResponse' '201': description: The newly created saved Audience. content: application/json: schema: $ref: '#/components/schemas/SavedAudienceResponse' '400': description: Invalid name or retired request fields. '401': description: Authentication required. '403': description: The account cannot create this Audience under its current plan or access permissions. '404': description: One or more requested Minds are missing or inaccessible. operationId: createAudience summary: Create an Audience from existing Minds description: Creates a private saved Audience by default. An optional per-creation idempotency key replays the same Audience with status 200; a new Audience returns 201. tags: - Audiences security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string minLength: 1 description: Non-blank Audience name; surrounding whitespace is trimmed. mindIds: type: array items: type: string default: [] description: Accessible existing Mind IDs. Duplicate IDs are deduplicated. Use mindIds, not the retired mindIds field. isLinkSharingEnabled: type: boolean default: false description: Enable only after explicit approval to share a public link. /api/v1/audiences/library: get: parameters: - in: query name: mode description: Opt into bounded pages; omitted preserves the legacy projection. schema: type: string enum: - summary - in: query name: limit schema: type: integer minimum: 1 maximum: 100 default: 60 - in: query name: after description: Opaque nextCursor from the previous page with the same search and sort. schema: type: string - in: query name: sort schema: type: string enum: - name - createdAt - updatedAt default: updatedAt - in: query name: direction schema: type: string enum: - asc - desc default: desc - in: query name: search description: Search all visible records, including unloaded pages. schema: type: string maxLength: 200 - in: query name: ids description: Comma-separated UUIDs; at most 100. schema: type: string - in: query name: fresh required: false description: Set to 1 after an access change to bypass the short-lived library cache. schema: type: string enum: - '1' responses: '200': description: Summary mode returns data with mindCount and membersLoaded=false, plus pageInfo.nextCursor. Membership arrays are partial. '401': description: Missing or invalid authentication. operationId: listAudienceLibrary summary: List the first-party Audience library projection description: Returns owned, followed, directly shared, and team-shared Audiences with caller-specific access fields. tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/lifecycle/stream: get: parameters: [] responses: '200': description: Server-sent connected, invalidation, and heartbeat events. content: text/event-stream: schema: type: string description: SSE frames whose invalidation payload includes durable-state domains to re-read. operationId: streamAudienceLifecycle summary: Stream Audience lifecycle invalidations description: User-scoped SSE wakeups for Audience draft, Audience, and Mind revalidation. Events are hints; clients must re-read durable state. tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/limits: get: parameters: [] responses: '200': description: Effective Audience creation limits. content: application/json: schema: type: object required: - data properties: data: type: object '401': description: Missing or invalid authentication. operationId: getAudienceLimits summary: Audience creation limits for the authenticated account description: 'Return the Audience size ceilings that apply to this account: the per-Audience plan cap (including a configured team override), the absolute system limit, the custom-size maximum, and per-creation-mode ceilings. scope identifies the authenticated user and entitlement team; allowance identifies the plan default, team override or legacy unlimited conversion; checkedAt is the observation time. These are per-Audience sizes, not a total workspace allowance or remaining credits. Match scope to the intended account before attributing these limits to it. Call this before creating an Audience to learn the real limits rather than discovering them from a 403. Mode ceilings come in two kinds and they are not interchangeable: `automaticSizingCeiling` bounds the size the server picks when no memberCount is given, while `explicitCountCeiling` bounds a size you state — only "balanced" enforces one, as 403 MODE_CAP.' tags: - Audiences security: - ApiKeyAuth: [] /api/v1/audiences/source-import: post: parameters: [] responses: '200': description: Imported files and optional reviewed grounding snapshot. content: application/json: schema: type: object required: - data properties: data: type: object '400': description: Invalid text, grounding, source reference or foreign file. '401': description: Authentication required. '413': description: Import is too large. '502': description: Source storage unavailable; retrying the same import is safe. operationId: importAudienceSources summary: Import supplied UTF-8 audience research sources tags: - Audiences description: Store up to 20 caller-supplied text, Markdown, CSV or JSON files (5 MB each, 12 MB total) as durable account-owned uploads. Optional groundingJson binds explicit supplied chart percentages to these files and returns a normalized snapshot/checksum for groundingPreview and creation. No research, Minds, or Audience is created. Identical file imports replay the same content-addressed URLs. security: - ApiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object properties: files: type: array maxItems: 20 items: type: object required: - name - content properties: name: type: string maxLength: 200 content: type: string maxLength: 5242880 existingFiles: type: array maxItems: 20 items: type: object required: - name - url properties: name: type: string url: type: string groundingJson: type: string maxLength: 2000000 components: schemas: AudienceCalibrationState: type: object required: - active - startedAt properties: active: type: boolean description: True while a recalibration run is in flight for this Audience. startedAt: type: - string - 'null' format: date-time AudienceSourceRecord: type: object required: - id - kind - text - url - filename - createdAt properties: id: type: string format: uuid kind: type: string enum: - brief - adjustment - keyword - link - file text: type: - string - 'null' description: Brief, adjustment or keyword text. Null for link and file rows. url: type: - string - 'null' description: Link URL or uploaded-file URL. Null for text rows; redacted for viewers without collaborator access. filename: type: - string - 'null' description: Original file name for file rows. createdAt: type: string format: date-time FormationSummary: type: object required: - id - name - status - source - dimensionKey - visibility - createdAt - updatedAt - createdByUserId - subgroups - canMutate properties: id: type: string format: uuid name: type: string status: type: string enum: - building - ready - failed description: Build state. Subgroup memberships are only populated once `ready`. source: type: string enum: - auto - manual dimensionKey: type: - string - 'null' description: Set on auto-seeded Formations (e.g. `age`, `gender`, or `grounding:` for grounding-derived splits); null for user-created ones. visibility: type: string enum: - shared - viewer_private description: '`shared` Formations are visible to every Audience viewer; `viewer_private` ones only to their creator.' createdAt: type: string format: date-time updatedAt: type: string format: date-time createdByUserId: type: string format: uuid canMutate: type: boolean description: Whether the caller may recompute or delete this Formation. subgroups: type: array items: type: object required: - id - label - isAuxiliary - position - _count properties: id: type: string format: uuid label: type: string isAuxiliary: type: boolean description: True for the catch-all bucket (e.g. Other or Unanswered). position: type: integer minimum: 0 _count: type: object required: - memberships properties: memberships: type: integer minimum: 0 description: Number of Minds in this subgroup. CohortMemberProfile: type: object required: - memberIndex - assignments properties: memberIndex: type: integer minimum: 0 assignments: type: array items: type: object required: - distribution - segment - sourceIdx properties: distribution: type: string description: Name of the grounded distribution. segment: type: string description: Label of the assigned segment. sourceIdx: type: integer description: Index into the grounding sources; -1 for assumed or derived segments. dimension: type: string enum: - age - gender - income - life_stage - representation - education - employment_status - geography - none canonical: type: string description: Language-independent segment concept, e.g. `feminine` or an age band such as `65+`. PlanLimitEnvelope: type: object required: - code - limitType - currentPlan - limit properties: code: type: string enum: - PLAN_LIMIT limitType: type: string description: Which cap was hit, e.g. `audienceMembers` or `minds` (legacy responses may say `audienceMembers`). currentPlan: type: string limit: type: integer current: type: integer description: Consumption against the cap. requested: type: integer description: How many units this request asked for. itemsToCreate: type: integer description: Bulk-create size that pushed the request over the cap. periodEnd: type: string format: date-time description: End of the metering window when the cap is periodic. context: type: string reason: type: string audienceId: type: string format: uuid isTrialing: type: boolean AudienceDetailMember: type: object required: - id - name - discipline - profileImageUrl - createdAt - cohortProfile properties: id: type: string format: uuid name: type: string discipline: type: - string - 'null' profileImageUrl: type: - string - 'null' format: uri description: Absolute avatar URL, or null while the portrait is still being generated. createdAt: type: string format: date-time cohortProfile: oneOf: - $ref: '#/components/schemas/CohortMemberProfile' - type: 'null' description: The segment of every grounded distribution this member represents. Null for Minds that were never allocated. AudienceDetail: type: object required: - id - name - mindCount - minds - createdAt - updatedAt - isPublic - currentMemberRole - sources - calibration properties: id: type: string format: uuid name: type: string marketplaceSubtitle: type: - string - 'null' description: Short subtitle shown in the public marketplace listing. marketplaceDescription: type: - string - 'null' description: Longer description shown in the public marketplace listing. mindCount: type: integer minimum: 0 membersLoaded: type: boolean description: Present in preview mode. False means the member array is incomplete; mindCount remains authoritative. minds: type: array description: Member Minds ordered by name. items: $ref: '#/components/schemas/AudienceDetailMember' createdAt: type: string format: date-time updatedAt: type: string format: date-time isPublic: type: boolean description: Anyone signed in can open the Audience and its Minds (marketplace listing). currentMemberRole: type: string enum: - owner - admin - member - team_member - public_viewer description: The caller's relationship to this Audience. `public_viewer` also covers read-only access inherited from a containing Study. isSharedWithTeam: type: boolean description: Collaborators only. Every member of the owner's team can open the Audience and read and chat with every Mind in it; no edit rights on the Minds. isLinkSharingEnabled: type: boolean description: Collaborators only. Anyone with the public link can open the Audience. publicShareId: type: - string - 'null' description: Collaborators only. Token of the public share link, when link sharing has been enabled. grounding: allOf: - $ref: '#/components/schemas/AudienceDetailGrounding' description: Stored research grounding. Absent when the Audience was never grounded. sources: type: array description: 'The Audience''s source bundle in creation order: the original brief, later recalibration adjustments, keywords, links and uploaded files. Uploaded-file URLs are signed and are redacted for public and Study-cascade viewers.' items: $ref: '#/components/schemas/AudienceSourceRecord' derivedDistributions: type: array description: Baseline demographics derived from what the members actually are, for dimensions the research did not cover. Present only when the member count is within the derivation cap and at least one dimension could be derived. Not research evidence and never used for cohort allocation. items: $ref: '#/components/schemas/GroundingDistribution' calibration: $ref: '#/components/schemas/AudienceCalibrationState' FormationHypothesis: type: object description: A proposed split of the Audience into 2 to 15 subgroups. required: - intent - subgroups properties: intent: type: string minLength: 1 description: One line restating the split, e.g. "Audience by gender". subgroups: type: array minItems: 2 maxItems: 15 items: type: object required: - id - label - definition properties: id: type: string minLength: 1 description: Stable lowercase slug, e.g. `female` or `age-25-34`. label: type: string minLength: 1 description: Short human-facing name. definition: type: string minLength: 1 description: One-sentence decision rule for membership in this subgroup. GroundingDistribution: type: object required: - name - distribution properties: name: type: string distribution: type: array items: type: object required: - label - pct - sourceIdx properties: label: type: string pct: type: number minimum: 0 maximum: 100 sourceIdx: type: integer minimum: 0 review: type: object properties: status: type: string enum: - included - excluded_by_source - conditional - unweighted evidence: type: string enum: - target - observed - candidate reason: type: string sourceFile: type: string tier: type: string enum: - target - broader - general - global segmentRelations: type: array nullable: true description: 'Evidence-backed relations from one of this distribution''s segments to segments of another distribution of the same audience. subset: every member in segment is in one of targetSegments. excludes: no member in segment is in any of targetSegments. Enforced by cohort allocation and reported in allocationAudit.segmentRelations.' items: type: object required: - type - segment - targetDistribution - targetSegments - evidence properties: type: type: string enum: - subset - excludes segment: type: string targetDistribution: type: string targetSegments: type: array items: type: string evidence: type: object required: - kind properties: kind: type: string enum: - source - definitional sourceIdx: type: integer minimum: 0 quote: type: string justification: type: string FormationBuildProgress: type: object required: - phase - done - total properties: phase: type: string enum: - classify - reconcile - ask done: type: integer minimum: 0 total: type: integer minimum: 0 failureReason: type: string description: Present when the build failed. AudienceMindSummary: type: object required: - id - name properties: id: type: string format: uuid name: type: string discipline: type: - string - 'null' profileImageUrl: type: - string - 'null' SavedAudienceResponse: type: object required: - data properties: data: type: object required: - id - name - mindCount - mindIds - minds - isLinkSharingEnabled - currentMemberRole properties: id: type: string name: type: string mindCount: type: integer minimum: 0 mindIds: type: array items: type: string minds: type: array items: type: object createdAt: type: string format: date-time updatedAt: type: string format: date-time isPublic: type: boolean isSharedWithTeam: type: boolean isLinkSharingEnabled: type: boolean publicShareId: type: - string - 'null' currentMemberRole: type: string enum: - owner PlanLimitError: type: object description: Error body of a plan-limit refusal (HTTP 403). properties: statusCode: type: integer enum: - 403 statusMessage: type: string description: Human-readable message naming the plan and the limit. data: $ref: '#/components/schemas/PlanLimitEnvelope' AudienceFromBriefResult: type: object required: - id - name - mindCount - minds - createdAt - updatedAt - isPublic - isSharedWithTeam - isLinkSharingEnabled - currentMemberRole - grounding - audienceCreationMode properties: id: type: string format: uuid name: type: string mindCount: type: integer minds: type: array items: $ref: '#/components/schemas/AudienceMindSummary' createdAt: type: string format: date-time updatedAt: type: string format: date-time isPublic: type: boolean isSharedWithTeam: type: boolean isLinkSharingEnabled: type: boolean publicShareId: type: - string - 'null' currentMemberRole: type: string enum: - owner grounding: oneOf: - $ref: '#/components/schemas/AudienceGrounding' - type: 'null' audienceCreationMode: type: string enum: - balanced - segment_coverage - benchmark_depth description: The EFFECTIVE creation mode applied by the server (after the plan gate — may differ from the requested mode on non-Team plans). replayed: type: boolean description: 'Present and true only on an idempotent replay (200): the audience was created by an earlier request with the same idempotency key.' datasetSegmentation: oneOf: - type: object properties: selectedVariableCount: type: integer observedProfileCount: type: integer recommendedMindCount: type: integer createdMindCount: type: integer - type: 'null' memberTraining: oneOf: - type: object required: - enqueued - queuedMemberCount - pollUrlTemplate description: Per-Mind background training enqueued for this creation. Every creation path trains every member; `queuedMemberCount` reports what actually reached the queue, so a value below `mindCount` means some members were not queued and must be retrained. Null on idempotent replays (training bookkeeping is not persisted). properties: enqueued: type: boolean queuedMemberCount: type: integer pollUrlTemplate: type: - string - 'null' description: Substitute each member id to poll its training progress, e.g. /api/v1/minds/{mindId}/training. - type: 'null' cohortAllocation: oneOf: - type: object required: - config - audit properties: config: type: object audit: type: object profiles: type: array items: type: object - type: 'null' cohortAllocationCoverage: type: object description: Which members the deterministic cohort allocation actually covered. Members flagged as real people are excluded individually (they cannot be given an invented demographic profile); `skipReason` explains a null `cohortAllocation`. required: - memberCount - allocatedMemberCount - excludedRealPersonCount - skipReason properties: memberCount: type: integer allocatedMemberCount: type: integer excludedRealPersonCount: type: integer excludedRealPersonNames: type: array items: type: string skipReason: type: - string - 'null' enum: - no_grounded_distributions - all_members_flagged_real_person AudienceGrounding: type: object required: - distributions - sources - summary - confidence properties: distributions: type: array items: $ref: '#/components/schemas/GroundingDistribution' reviewDistributions: type: array description: Complete source-identified distribution universe, including screener-excluded, conditional, and unweighted options that were not allocated. items: $ref: '#/components/schemas/GroundingDistribution' researchStudyAnalysis: type: - object - 'null' description: Canonical content-based classification of uploaded research files and their audience, quota, routing, and evidence contracts. research: type: - object - 'null' description: 'Research coverage and axisReconciliation audit. An unavailable or budget_exceeded axis review is not a successful semantic validation; failureReason explains unusable model output or infrastructure failure. `dimensionCoverage.dimensions` lists the standard dimensions covered for this population — the fixed core pool every audience of people carries (age, gender identity, representation, geography, education, employment status, income, household size) plus any the planner judged relevant — each with a reason and a status: `sourced`, `proxy` (wider area or population), `assumed` (model-proposed shares, never used for sizing) or `missing`.' sources: type: array items: $ref: '#/components/schemas/GroundingSource' summary: type: string confidence: type: number minimum: 0 maximum: 1 suggestedMinAudienceSize: type: integer minimum: 3 maximum: 50 flaggedDistributions: type: array description: Axes demoted to supplementary context because they measure the Study outcome itself (`audienceContext.reason = study_outcome`). Never used for cohort allocation. items: type: object required: - name - reason properties: name: type: string reason: type: string enum: - study_outcome category: type: string enum: - demographic - geographic - psychographic - behavioral - firmographic tier: type: string enum: - target - broader - general - global GroundingHardConstraints: type: object description: Inclusion rules resolved from the Audience specification. Values outside these bounds are excluded from allocation. required: - gender - age - country - categoricalMemberships properties: gender: type: - string - 'null' enum: - feminine - masculine - androgynous age: oneOf: - type: object required: - min - max properties: min: type: integer max: type: integer - type: 'null' country: type: - string - 'null' categoricalMemberships: type: array items: type: object required: - axisTerms - allowedValueTerms properties: axisTerms: type: array items: type: string allowedValueTerms: type: array items: type: string AudienceDetailGrounding: type: object required: - snapshotId - distributions - reviewDistributions - sources - summary - confidence - appliedToPersonas - createdAt properties: snapshotId: type: - string - 'null' description: Identifier of the grounding snapshot currently applied. distributions: type: array description: Active distributions that drive cohort allocation, bounded to the Audience definition. items: $ref: '#/components/schemas/GroundingDistribution' reviewDistributions: type: array description: Complete source-identified distribution universe, including options that are not allocated. items: $ref: '#/components/schemas/GroundingDistribution' studyUse: type: object description: Collaborators only. Disclosed new-research or reconstruction mode, matching the reviewed preview. sourceFindings: type: array items: type: object description: Collaborators only. Original observed and historical findings retained separately from the active composition. researchStudyAnalysis: type: - object - 'null' description: Classification of uploaded research files and their audience, quota, routing and evidence contracts. sources: type: array items: $ref: '#/components/schemas/GroundingSource' summary: type: - string - 'null' confidence: type: number minimum: 0 maximum: 1 appliedToPersonas: type: boolean description: True when deterministic cohort allocation assigned the members to the distributions. allocationConfig: type: - object - 'null' description: Deterministic cohort allocation controls used for the current member profiles. hardConstraints: oneOf: - $ref: '#/components/schemas/GroundingHardConstraints' - type: 'null' allocationAudit: type: - object - 'null' description: Per-distribution audit of target versus achieved segment counts. createdAt: type: string format: date-time FormationSubgroup: type: object required: - id - label - definition - isAuxiliary - position - memberships properties: id: type: string format: uuid label: type: string definition: type: - string - 'null' description: Natural-language membership rule. isAuxiliary: type: boolean description: True for the catch-all bucket (e.g. Other or Unanswered). position: type: integer minimum: 0 memberships: type: array description: Minds assigned to this subgroup. A Mind may appear in several subgroups when overlap is allowed. items: type: object required: - mindId - confidence properties: mindId: type: string format: uuid confidence: type: - number - 'null' minimum: 0 maximum: 1 Formation: type: object description: A persisted segmentation of one Audience into subgroups. required: - id - name - status - source - visibility - canMutate - createdAt - updatedAt - createdByUserId - subgroups - hypothesis - progress properties: id: type: string format: uuid name: type: string status: type: string enum: - building - ready - failed source: type: string enum: - auto - manual visibility: type: string enum: - shared - viewer_private canMutate: type: boolean description: Whether the caller may recompute or delete this Formation. createdAt: type: string format: date-time updatedAt: type: string format: date-time createdByUserId: type: string format: uuid subgroups: type: array description: Materialised subgroups in display order. Empty until the build is `ready`. items: $ref: '#/components/schemas/FormationSubgroup' hypothesis: allOf: - $ref: '#/components/schemas/FormationHypothesis' description: The stored proposal the Formation was built from. May be an empty object for legacy auto-seeded rows. progress: oneOf: - $ref: '#/components/schemas/FormationBuildProgress' - type: 'null' description: Live build progress while `building`, the failure reason when `failed`, null once `ready`. GroundingSource: type: object required: - url - title - snippet - domain - confidence properties: url: type: string title: type: string snippet: type: string domain: type: string publishedDate: type: string confidence: type: number minimum: 0 maximum: 1 tier: type: string enum: - target - broader - general - global isUserProvided: type: boolean securitySchemes: ApiKeyAuth: type: http scheme: bearer bearerFormat: API Key description: 'Personal API key. Format: `Bearer minds_…_key`. Create one at https://getminds.ai/settings/api-keys.'