MindTwinsDevelopers
Request access

Developers

Give any agent or app a mind to ask.

Connect once. Your software can ask a Mind Twin how a teammate will think, feel, say, and act, then keep that understanding current from the same workspace.

Start building
Hosted MCPPlain RESTStructured JSON
decision-roomconnected

YouAsk Maya's Mind Twin what would make her reject this rollout.

mind-twinchat_with_twin{ target: "Maya Chen" }
Mind TwinI would reject a company-wide rollout without a contained pilot.
ThinkThe upside is clear. The risk is not.FeelInterested, but exposed.SayShow me one region working first.ActApprove a 30-day pilot.
workspace / acmeBearer key scoped
Choose your path ↓

Start with what you are building

One Mind Twin. Two ways in.

Both paths upload, check readiness, and ask. Choose who should make the call.

01MCP

Let the agent do it.

Your assistant chooses the right tool from plain language. No integration backend to build.

  • Claude Desktop, Claude Code, Cursor
  • Upload, check, and ask
  • Readable answers by default
02REST

Make the call yourself.

Your server controls every request and receives structured JSON. No SDK required.

  • Node.js, Python, cURL, or any HTTP client
  • Plain HTTPS and JSON
  • Think, Feel, Say, Act fields

Before your first call

A workspace. A person. The right key.

Set up the Mind Twin in the app. Then connect your software.

1

Set up the workspace.

Use the MindTwins app to set up a shared team workspace and invite each person whose Mind Twin you need. Invitees receive their Mind Twin when they join. There is no public endpoint to create a Mind Twin.

2

Get the right key.

Open MCP Twin in the app. Use the provisioned twin:chat key for your own Mind Twin. For teammates, ask your workspace administrator to enable Mind Twin Teams and provide a key with twin:upload. Keep the key on your server.

3

Confirm who you can reach.

Call list_twins in MCP or GET /twins in REST. Use the returned display name as target, or the person's email if names collide. Listing is not an access guarantee. Check GET /me/status with the intended target before uploading.

The examples use a teammate named Maya Chen and require a Teams key. To work with your own Mind Twin, omit target.

Prepare the source

Give every speaker a name.

A Mind Twin needs to know which words belong to its person.

  • Label every speaker with their full name, matching the person's name in MindTwins. The Mind Twin identifies its person by name.
  • Send one meeting per transcript. Keep speaker labels attached to what each person said.
  • Use VTT, SRT, or plain text for a straightforward first upload. CSV is not supported.
  • Use the real meeting date. Never guess or default to today; confirm each transcript separately.
Correct · Full speaker names
WEBVTT

00:00:01.000 --> 00:00:05.000
<v Maya Chen>I want to test one region before we commit to a full rollout.</v>

00:00:05.000 --> 00:00:09.000
<v Jordan Lee>What would you need to see before expanding?</v>

00:00:09.000 --> 00:00:14.000
<v Maya Chen>Four weeks of steady adoption and a clear way to stop if it slips.</v>
Incorrect · Anonymous speakers
Speaker 1: I want to test one region first.
Meet participant 2: What would you need to see?

Recommended request budget: under 4,000,000 bytes for the complete UTF-8 JSON body. This is a conservative client budget, not an exact service maximum. Count the encoded body, including JSON escaping and metadata. Oversized requests can return a plain-text 413 FUNCTION_PAYLOAD_TOO_LARGE before the API runs. The MCP transcript schema limit does not override HTTP or downstream limits. REST has a larger application cap of 52,428,800 bytes for transcript plus segment text and 54,525,952 bytes for the raw JSON body; the public hosting limit applies first, so these are not usable upload sizes at this URL.

The complete integration

Feed it. Wait once. Ask anything.

Three actions take a Mind Twin from a meeting to a decision-ready answer.

1
Feed

Add the meeting.

Send a dated transcript. VTT, SRT, text, and agent JSON all work.

upload_transcript
2
Ready

Check, then move on.

Learning runs in the background. Poll periodically until the status is ready.

get_status
3
Ask

Put judgment to work.

Ask about a past decision or a new situation. Get the answer and the reasoning around it.

chat_with_twin

Built in Re-uploading a transcript already built returns 200. Queued duplicates can also return 200. A 409 ALREADY_PROCESSING means nothing more to do.

Path 01 · MCP

Your agent. One clear loop.

One hosted server gives an MCP-capable assistant everything it needs to keep a Mind Twin current and ask it questions.

Before you connect

Install Node.js once.

The command below runs through npx, which comes with Node.js.

MacHomebrew
brew install node
LinuxDebian / Ubuntu
sudo apt install nodejs
Verifynode --version npx --version
01

Copy your key.

Open MCP Twin in the app. Copy your provisioned twin:chat key. For teammates, follow Teams setup.

02

Run one command.

The installer connects every supported MCP client it detects.

03

Open and verify.

If the tools do not appear, quit and reopen the client. Then ask which mind-twin tools it sees.

Terminal
npx -y add-mcp mcp-remote --name mind-twin \
  --args=https://mcp.mindtwins.com/mcp \
  --args=--header --args="Authorization: Bearer dev_YOUR_TWIN_CHAT_KEY" \
  --all -g -y
Claude Code only: use its direct command.
Claude Code · optional
claude mcp add --transport http mind-twin https://mcp.mindtwins.com/mcp \
  --header "Authorization: Bearer dev_YOUR_TWIN_CHAT_KEY"
After install
Restart if the tools do not appear.

Some clients load new servers only when they open. If the mind-twin tools do not appear, fully quit and reopen the client, then ask which mind-twin tools it can see.

Serverhttps://mcp.mindtwins.com/mcp
Client namemind-twin
TransportStreamable HTTP
HostingManaged for you
PrerequisiteNode.js for npx

Agent integrations

Bring the same mind into the tools you already use.

C
Claude DesktopDesktop assistant
Ready
⌘
Claude CodeTerminal agent
Ready
↗
CursorAI code editor
Ready
+
Any MCP clientStreamable HTTP
Ready

The universal installer is the supported fast path. It detects compatible clients, adds the hosted server, and includes your Bearer header.

Call in. Result out.

Put judgment to work.

Ask one consequential question and request JSON when your agent needs structure.

chat_with_twin · call
{
  "name": "chat_with_twin",
  "arguments": {
    "message": "What would make you reject this rollout?",
    "target": "Maya Chen",
    "format": "json"
  }
}
Example result
{
  "content": [
    {
      "type": "text",
      "text": "{\n  \"answer\": \"I would reject a company-wide rollout without a contained pilot.\",\n  \"think\": \"The upside is clear. The implementation risk is not.\",\n  \"feel\": \"Interested, but exposed if adoption fails.\",\n  \"say\": \"Show me one region working first.\",\n  \"act\": \"Approve a 30-day pilot with a stop point.\"\n}"
    }
  ]
}

Good to knowformat defaults to text. Pass json for the structured answer, think, feel, say, and act object inside content[0].text. Missing TFSA fields may be omitted. MCP chat does not remember earlier messages. Include the relevant conversation context in each message.

MCP tool results use a content array containing text. Upload and status return readable text. Chat with format: json puts a JSON string inside content[0].text; parse that string to read the answer fields. These examples show the tool result, without the outer JSON-RPC envelope. Tool failures normally set isError: true; inspect it before reading content as success.

OpenAPI 3.1 reference. Response examples use illustrative values.

MCPupload_transcriptUpload field reference

Limits below are validated by the MCP tool. REST names show what the MCP client sends.

MCP fieldREST fieldType and limitMeaning
transcripttranscriptstring · required · 1 to 10,000,000 charactersOne meeting in VTT, SRT, plain text, or agent JSON. The character limit is the MCP schema limit; the encoded request budget still applies.
datedateISO-8601 string · requiredThe real meeting start time with its UTC offset, or YYYY-MM-DD when the time zone is unknown. Use the recording app's meeting time or a date supplied in the transcript or by the user. Never use file timestamps. Preserve the exact string on retries.
titletitlestring · optional · 1 to 500 charactersThe meeting's actual title, when known.
formatformatenum · optionalvtt, srt, text, or agent-json. Omit to pass VTT or plain text through; set srt or agent-json explicitly. There is no auto or json format value.
targettargetstring · optional · up to 200 charactersA teammate's name or email; requires twin:upload. Whitespace is trimmed. Omit or leave blank for your own Mind Twin.
participantsparticipantsstring[] · optional · up to 100 namesEach name is trimmed and limited to 200 characters. Blank names are dropped. Keep the same order on retries.
sourcesourceenum · optionalThe recording app: fathom, zoom, gong, google_meet, fireflies, microsoft_teams, manual, sybill, affinity_notetaker, granola, raw_import. Omit or use manual for pasted text; use raw_import for another app or an export. Never guess.
durationdurationnumber · optional · zero or greaterMeeting duration in seconds, not minutes or milliseconds. Helps space lines when the transcript has no timestamps.
self_speakerselfSpeakerstring · optional · up to 200 charactersThe exact speaker label for the Mind Twin's owner, or the teammate named by target. With VTT, text, or omitted format, also include it in participants. With SRT or agent-json, it is checked against transcript speakers and participants. A mismatch returns SELF_NOT_A_SPEAKER and saves nothing. Omit it to match by name.

For a retry, resend the same transcript, exact date string, title, format, target, source, duration, and participants in the same order. Changing meeting details can save a second copy. Deduplication compares generated transcript content within the selected Mind Twin. A completed duplicate returns 200; queued or processing duplicates can also return 200 in workspaces with a build queue. ALREADY_PROCESSING means the same transcript is in progress: check status instead of uploading again. BUILD_IN_PROGRESS means this upload was not saved: wait for the current build, then retry. If an upload reply is lost, check status first and preserve the original payload for any retry.

ToolWhat it doesInputs
whoamiShows your identity and an early readiness signal. Use get_status for build readiness.None.
list_twinsLists workspace Mind Twins by display name. Use get_status with the intended target to verify access and build readiness.None.
chat_with_twinAsks a Mind Twin. Include conversation context in each message; prior messages are not remembered.message (required, 1 to 800,000 characters), target, format (text by default or json).
upload_transcriptFeeds a Mind Twin a dated transcript.transcript (required, up to 10,000,000 characters), date (required, real ISO-8601 meeting date), title (up to 500 characters), format (vtt, srt, text, or agent-json; omit for VTT/text passthrough), target, participants, source, duration (seconds), self_speaker. See the field reference below.
get_statusChecks whether a Mind Twin is ready.target (optional).
list_snapshotsLists a Mind Twin's snapshots with id, name, status, and counts. Results are paginated.target (up to 200 characters), cursor (1 to 500 characters), limit (integer 1 to 100; default 25).
snapshot_detailShows one snapshot's summaries and counts. Raw psychometric records are withheld; the profile can include derived scores and confidence labels.snapshot_id (required, 1 to 200 characters), target, detail (concise or detailed; default detailed).
delete_rawPermanently removes one transcript from recall while keeping the snapshot counts and Mind Twin; no rebuild. Preview without confirm, then confirm with the expected_count. Irreversible.snapshot_id (required, 1 to 200 characters), confirm (omit for preview; true to delete), expected_count (nonnegative integer, required with confirm), idempotency_key (1 to 200 characters), target.

Path 02 · REST API

Your product gets the same mind, as JSON.

Use ordinary HTTPS from any server language. Every authenticated request carries the same Bearer key.

200 · application/json

One answer. The full human read.

answer is the complete response. say is the short spoken line. Any empty Think, Feel, Say, or Act field is omitted.

Node.js · POST /chat
// npm install undici
import { request } from "undici";

const { statusCode, headers, body } = await request(
  "https://app.mindtwins.com/api/twin-mcp/chat",
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.MINDTWINS_KEY}`,
      "Content-Type": "application/json",
    },
    headersTimeout: 600_000,
    bodyTimeout: 600_000,
    signal: AbortSignal.timeout(600_000),
    body: JSON.stringify({
      message: "What would make you reject this rollout?",
      target: "Maya Chen",
    }),
  },
);

if (statusCode < 200 || statusCode >= 300) {
  await body.dump();
  throw new Error(`MindTwins request failed: ${statusCode}`);
}
if (!String(headers["content-type"]).includes("application/json")) {
  await body.dump();
  throw new Error("Expected a JSON response");
}
const mindTwin = await body.json();
200 · Response
{
  "answer": "I would reject a company-wide rollout without a contained pilot.",
  "think": "The upside is clear. The implementation risk is not.",
  "feel": "Interested, but exposed if adoption fails.",
  "say": "Show me one region working first.",
  "act": "Approve a 30-day pilot with a stop point."
}
Base URLhttps://app.mindtwins.com/api/twin-mcp

Mind Twin Teams

One workspace. Every teammate's judgment.

Add a teammate's display name (see list_twins) or email. as target. Every action goes to their team Mind Twin. Omit target to use your own Mind Twin. MCP also accepts a blank target; REST chat and upload reject an empty string. If a name matches more than one person, the API returns 422 AMBIGUOUS_TARGET; use their email. list_twins shows name (email) when names collide.

YouBearer keyIdentifies the caller
target
Workspace gateacme.comNever crosses workspaces
Team Mind TwinMayaOwner boundaries stay on
Ask Maya{ "target": "Maya Chen" }
  • Workspace-scoped. A target can never resolve outside the key's workspace.
  • Team-only. Private Mind Twins cannot be reached through target.
  • Owner-controlled. Off-limits topics and private material stay withheld.
  • Team trust model. A teammate target requires twin:upload, team visibility in the same workspace, and permission under any target allowlist attached to the key. The directory can show members that this key cannot target. A directory entry is not proof of access; verify the intended target with GET /me/status before uploading.

Complete reference

Every action, in one view.

Scan the map first. Open an endpoint only when you need the exact fields. This reference covers integration actions; automated installer checks are outside this workflow.

Askchat_with_twin

message required, 1 to 800,000 characters · target optional · format defaults to text; pass json for structured TFSA

Feedupload_transcript

transcript and the real meeting date required · title, format, and target optional · limit 10,000,000 characters at the schema level; request-body limits still apply

Checkget_status

No fields for your own Mind Twin · target optional · needs_upload and ready + ingesting are expected conditions

IntentMCP toolREST endpointReturns
Ask a Mind Twinchat_with_twinPOST/chatAnswer + TFSA
Add a meetingupload_transcriptPOST/uploadProcessing state
Check readinessget_statusGET/me/statusStatus + progress
Check serviceNot exposedGET/healthService status
Identify yourselfwhoamiGET/meIdentity + own Mind Twin readiness
Find a Mind Twinlist_twinsGET/twinsMind Twins with name, email, ownership, ready, status
Browse snapshotslist_snapshotsGET/snapshotssnapshots, next_cursor, total
Inspect a snapshotsnapshot_detailGET/snapshots/{id}Snapshot summaries and counts
Remove raw materialdelete_rawDELETE/snapshots/{id}/rawDry run or confirmed deletion

OpenAPI 3.1 reference. Response examples use illustrative values.

POST/chatAsk a Mind Twin

Send one question. Omit target to use your own Mind Twin. MCP also accepts a blank target; REST chat and upload reject an empty string. If a name matches more than one person, the API returns 422 AMBIGUOUS_TARGET; use their email. list_twins shows name (email) when names collide. The REST response is the bare answer, think, feel, say, act object; empty parts are omitted. format is MCP-only.

messagestring · required · 1 to 800,000 characters

The question to answer.

targetstring · optional · 1 to 200 characters

a teammate's display name (see list_twins) or email. Requires twin:upload for a teammate.

HTTP request
POST https://app.mindtwins.com/api/twin-mcp/chat
Authorization: Bearer $MINDTWINS_KEY
Content-Type: application/json

{
  "message": "What would make you reject this rollout?",
  "target": "Maya Chen"
}
200 · Response
{
  "answer": "I would reject a company-wide rollout without a contained pilot.",
  "think": "The upside is clear. The implementation risk is not.",
  "feel": "Interested, but exposed if adoption fails.",
  "say": "Show me one region working first.",
  "act": "Approve a 30-day pilot with a stop point."
}

Continue a conversation and attach text

REST chat accepts history: up to 20 earlier turns, each with role (user or assistant) and content. User content allows 800,000 UTF-16 code units; assistant content allows 100,000. Send the turns you want considered on each request. There is no conversation ID that restores earlier turns.

Use context for attached text: one string or up to 10 strings. Each item allows 100,000 UTF-16 code units and, after trimming and normalization, at most 51,200 UTF-8 bytes. Context is allowed on the current question and earlier user turns, never assistant turns. Extract text from PDFs or documents before sending it. The prepared current message plus context must fit 1,470,000 characters after escaping; a punctuation-heavy message can hit this limit before 800,000 input characters. The complete JSON body must also fit the hosting limit.

Requests accept Unicode text and have no language selector or published per-language guarantee. Test representative transcripts and questions in the languages your integration needs before rollout.

JSON request with history and context
{
  "message": "How should we respond?",
  "context": [
    "Jordan Lee: Can we expand the pilot next week?"
  ],
  "history": [
    {
      "role": "user",
      "content": "What matters most for this launch?"
    },
    {
      "role": "assistant",
      "content": "A clear rollback plan."
    }
  ]
}
POST/uploadAdd a meeting

Recommended request budget: under 4,000,000 bytes for the complete UTF-8 JSON body. This is a conservative client budget, not an exact service maximum. Count the encoded body, including JSON escaping and metadata. Oversized requests can return a plain-text 413 FUNCTION_PAYLOAD_TOO_LARGE before the API runs. The MCP transcript schema limit does not override HTTP or downstream limits. REST has a larger application cap of 52,428,800 bytes for transcript plus segment text and 54,525,952 bytes for the raw JSON body; the public hosting limit applies first, so these are not usable upload sizes at this URL.

The MCP transcript limit is 10,000,000 characters at the schema level; request-body limits still apply.

transcriptstring · required

VTT, SRT, plain text, or agent JSON.

dateISO-8601 · required

The real meeting date or timestamp. Invalid dates return 400 INVALID_DATE. Use the real meeting date; confirm each transcript separately.

titlestring · optional · max 500

A human-readable meeting name.

formatenum · optional

vtt, srt, text, or agent-json. Omit for VTT/text passthrough; set srt or agent-json explicitly.

targetstring · optional · 1 to 200 characters

a teammate's display name (see list_twins) or email. Requires twin:upload for a teammate.

participantsstring[] · optional · up to 100 names

Meeting speaker names. Preserve their order on retry.

durationnumber · optional · zero or greater

Meeting duration in seconds.

sourceenum · optional

fathom, zoom, gong, google_meet, fireflies, microsoft_teams, manual, sybill, affinity_notetaker, granola, raw_import. Omit for manual.

selfSpeakerstring · optional · max 200 characters

Exact owner speaker label. MCP spells this self_speaker. With VTT/text, also include it in participants. See the upload field reference.

Use the real meeting date in ISO 8601, from January 1, 2000 through 24 hours ahead of server time. Confirm the date for every transcript.

REST-only segments accepts up to 10,000 objects: text (required string), speaker (optional full name), startTime and endTime (optional nonnegative seconds). transcript and date remain required. When segments is supplied, it takes precedence over format normalization. Keep transcript and segments consistent; their combined text contributes to the size limit.

For format: agent-json, transcript is a string containing JSON, not a nested object. Serialize either an array of segments or an object with a segments array. Each segment uses text, speaker, startTime, and endTime; times are nonnegative seconds. Blank or non-string text is skipped, invalid timestamps are ignored, and only the first 10,000 usable segments are retained. Malformed JSON or no usable text returns 400 INVALID_TRANSCRIPT.

Agent JSON request
{
  "date": "2026-10-07",
  "format": "agent-json",
  "transcript": "{\"segments\":[{\"speaker\":\"Maya Chen\",\"text\":\"Start with a small pilot.\",\"startTime\":0,\"endTime\":4},{\"speaker\":\"Jordan Lee\",\"text\":\"We will review the results first.\",\"startTime\":4,\"endTime\":8}]}"
}

For a retry, resend the same transcript, exact date string, title, format, target, source, duration, and participants in the same order. Changing meeting details can save a second copy. Deduplication compares generated transcript content within the selected Mind Twin. A completed duplicate returns 200; queued or processing duplicates can also return 200 in workspaces with a build queue. ALREADY_PROCESSING means the same transcript is in progress: check status instead of uploading again. BUILD_IN_PROGRESS means this upload was not saved: wait for the current build, then retry. If an upload reply is lost, check status first and preserve the original payload for any retry.

HTTP request
POST https://app.mindtwins.com/api/twin-mcp/upload
Authorization: Bearer $MINDTWINS_KEY
Content-Type: application/json

{
  "date": "2026-10-07",
  "title": "Rollout planning",
  "format": "vtt",
  "transcript": "WEBVTT\n\n00:00:01.000 --> 00:00:05.000\n<v Maya Chen>I want to test one region before we commit to a full rollout.</v>\n\n00:00:05.000 --> 00:00:09.000\n<v Jordan Lee>What would you need to see before expanding?</v>\n\n00:00:09.000 --> 00:00:14.000\n<v Maya Chen>Four weeks of steady adoption and a clear way to stop if it slips.</v>",
  "target": "Maya Chen"
}
200 · Response
{
  "success": true,
  "data": {
    "status": "processing"
  }
}
GET/me/statusCheck readiness

Use ?target=Maya%20Chen for a teammate. Recommended client strategy: check status every 15 seconds, then every 30 to 60 seconds for longer builds. These intervals are guidance, not server requirements. Build time varies; use status rather than a fixed delay. No completion webhooks are available. Read ready, building, or failed together with the optional flags. needs_upload: true means upload a transcript instead of polling an empty Mind Twin. ready + hydrating: true means it can answer from previously learned material, but the latest upload is not available yet. ready + ingesting: true means a transcript is being folded in. Treat absent flags as false; low or zero early progress alone does not mean failure.

needs_uploadA Mind Twin with no transcripts returns 200 building, progress 0, and needs_upload: true. Upload a transcript to begin.no Mind Twin in workspaceREST returns 404 NOT_FOUND when your account has no Mind Twin in this workspace. Set one up in the MindTwins app.buildingLearning is in progress. Check every 15 seconds, then back off for longer builds.readyThe Mind Twin is ready to answer.ready + ingestingIt stays chattable while a new transcript is folded in.ready + hydratingIt can answer from previously learned material. The latest upload is not available until its build finishes.failedThe build needs attention.
HTTP request
GET https://app.mindtwins.com/api/twin-mcp/me/status?target=Maya%20Chen
Authorization: Bearer $MINDTWINS_KEY
200 · Response
{
  "status": "building",
  "progress": 42,
  "ingesting": false
}
GET/healthCheck service liveness

No key required. Use it for a simple service liveness check.

HTTP request
GET https://app.mindtwins.com/api/twin-mcp/health
200 · Response
{
  "status": "ok",
  "service": "twin-mcp",
  "timestamp": "2026-10-08T14:35:56.581Z"
}
GET/meIdentify yourself

Identify yourself. Use GET /me/status to check build readiness; the identity readiness flag is a lighter signal. Returns 404 NO_TWIN if you have no Mind Twin.

None.

All of these endpoints require the same Bearer key.

200 · Example response
{
  "twin_id": "example-twin_id",
  "mind_id": "example-mind_id",
  "workspace_id": "example-workspace_id",
  "user_id": "example-user_id",
  "name": "Maya Chen",
  "email": "maya\u0040example.com",
  "handle": "maya",
  "ready": true,
  "status": "ready"
}
GET/twinsFind a Mind Twin

List the workspace directory with name, email, ownership (self or team), ready, and status. Listing does not guarantee target permission; use GET /me/status to check access and build readiness.

None. The response contains twins: [...].

All of these endpoints require the same Bearer key.

200 · Example response
{
  "twins": [
    {
      "twin_id": "example-twin_id",
      "mind_id": "example-mind_id",
      "name": "Maya Chen",
      "email": "maya\u0040example.com",
      "handle": "maya",
      "ready": true,
      "status": "ready",
      "ownership": "self"
    }
  ]
}
GET/snapshotsBrowse snapshots

Browse a Mind Twin's snapshots. The response contains snapshots, next_cursor, and total.

Query: target, cursor, limit (1 to 100; default 25).

All of these endpoints require the same Bearer key.

200 · Example response
{
  "snapshots": [
    {
      "snapshot_id": "example-snapshot",
      "date": "2026-10-07",
      "filename": "Rollout planning",
      "status": "completed",
      "counts": {
        "data_points": 120,
        "key_topics": 4,
        "findings": 8
      }
    }
  ],
  "next_cursor": null,
  "total": 1
}
GET/snapshots/{id}Inspect a snapshot

Read one snapshot's summaries and counts. Raw psychometric records are withheld; the profile can include derived scores and confidence labels.

Path: id. Query: detail (concise or detailed), target.

Findings and Mindsets are learned outputs associated with a snapshot. Browse snapshots, then inspect a snapshot by its ID. The API does not provide a combined per-person Findings or Mindsets view.

All of these endpoints require the same Bearer key.

200 · Example response
{
  "ready": true,
  "snapshot_id": "example-snapshot",
  "date": "2026-10-07",
  "filename": "Rollout planning",
  "status": "completed",
  "counts": {
    "data_points": 120,
    "key_topics": 4,
    "findings": 8
  },
  "summary": {
    "disposition": null,
    "synthesis": [
      {
        "ticker": "SYN-01",
        "label": "Decision style",
        "value": "Prefers evidence before expanding a rollout."
      }
    ],
    "categories": [
      {
        "index": "01",
        "title": "Decision-making",
        "items": [
          {
            "subIndex": "01.1",
            "label": "Trade-offs",
            "value": "Balances speed with a clear rollback plan."
          }
        ]
      }
    ]
  },
  "profile": {
    "twin": "Maya Chen",
    "proceedings": 1,
    "findings": 8,
    "points": 120,
    "domainSummary": null,
    "coreProfile": null,
    "buckets": []
  }
}
DELETE/snapshots/{id}/rawRemove raw material

Preview removal without confirm, then permanently remove raw material with confirm: true and the dry run's expected_count. A stale count returns 409 PRECONDITION_FAILED. The snapshot counts and Mind Twin remain; no rebuild.

Path: id. JSON body: confirm, dry_run, expected_count, idempotency_key, target. dry_run: true overrides confirm. Confirmation requires the latest expected_count. The idempotency cache lasts 10 minutes per server instance; do not rely on it across retries to a different instance. Reconcile a lost response with a fresh dry run.

delete_raw removes one transcript from the Mind Twin's recall store and browse list. It does not delete the snapshot or Mind Twin, erase learned outputs, or trigger a rebuild. The public integration API has no Mind Twin deletion, snapshot deletion, or export endpoint.

All of these endpoints require the same Bearer key.

200 · Example response
{
  "dry_run": true,
  "snapshot_id": "example-snapshot",
  "found": true,
  "would_delete": {
    "mind_sync_rows": 1
  },
  "expected_count": 1,
  "message": "This is a dry run. No data has been removed."
}

Authentication and boundaries

The key decides who you can ask.

Every authenticated request is tied to one caller and one workspace. The request never supplies a workspace id.

twin:chatEveryone

Your own Mind Twin.

Every action on the key owner's Mind Twin, including snapshot browsing and delete_raw.

twin:uploadMind Twin Teams

Add the target field.

A teammate target requires twin:upload, team visibility in the same workspace, and permission under any target allowlist attached to the key. The directory can show members that this key cannot target. A directory entry is not proof of access; verify the intended target with GET /me/status before uploading.

Provisioned for you Keys are created in the app. There is no public create-key endpoint.

Keep it server-side. Never ship a dev_ key in browser or mobile code.

Rotate on exposure. Regenerate in MCP Twin. The old key stops working immediately.

Use the narrow path. Drop target when you only need the key owner's Mind Twin.

A valid key starts with dev_ and is 41 characters in total, including dev_.

Limits and timing

Build for the whole response.

Direct REST chat can take up to 9 minutes; allow 10 minutes in your HTTP client and proxy. MCP has a separate 290-second downstream request budget and a 300-second hosting limit. A longer MCP client timeout cannot extend that server budget. After a timeout, the server may still be working; avoid an immediate retry loop.

Key environmentPer minutePer hourPer day
Development601,00010,000
Production30010,000100,000

Limits apply per key. A 429 response does not include a Retry-After header; read the retryAfter ISO timestamp in its JSON body. If it is absent or invalid, use bounded exponential backoff with jitter. Do not immediately retry. A 403 IP_BLOCKED response has separate Retry-After handling.

On a 429, X-RateLimit-Limit-Minute, X-RateLimit-Remaining-Minute, X-RateLimit-Limit-Hour, X-RateLimit-Remaining-Hour, X-RateLimit-Limit-Day, and X-RateLimit-Remaining-Day contain request counts. X-RateLimit-Reset-Minute is an ISO timestamp. Hour and day reset headers are not returned. Successful integration responses do not guarantee these headers. Use retryAfter in the body for the window that actually blocked the request.

Check readiness, then ask.

Recommended client strategy: check status every 15 seconds, then every 30 to 60 seconds for longer builds. These intervals are guidance, not server requirements. Build time varies; use status rather than a fixed delay. No completion webhooks are available.

Carry the conversation forward.

MCP chat does not remember earlier messages. Include the relevant conversation context in each message.

Snapshot outputs and data controls

Findings and Mindsets are learned outputs associated with a snapshot. Browse snapshots, then inspect a snapshot by its ID. The API does not provide a combined per-person Findings or Mindsets view.

Snapshot lists use snapshot_id, date, filename, status, and counts; counts can be null while processing or when a recall entry has no linked engine snapshot. In concise detail, summary and profile are null; they can also be null for an unlinked recall entry. Pass snapshot_id unchanged to detail or deletion, including an rc: prefix if present. next_cursor is opaque; stop when it is absent or null. In detail, ready: false means the snapshot is still processing. Findings appear in summary.categories and Mindsets in profile.buckets. MCP renders readable Markdown, limited to 9 finding categories, 6 items per category, and 12 mindset attributes; use REST detail when you need the structured sections.

delete_raw removes one transcript from the Mind Twin's recall store and browse list. It does not delete the snapshot or Mind Twin, erase learned outputs, or trigger a rebuild. The public integration API has no Mind Twin deletion, snapshot deletion, or export endpoint.

Errors and retries

Know what failed. Know what to do.

Application errors return JSON with error; code and message are usually present. Check Content-Type first: hosting-layer errors can be plain text.

401 · Missing Authorization header
{
  "error": "Missing or invalid Authorization header",
  "message": "Provide a developer API key: Authorization: Bearer dev_xxx"
}

MCP may refuse a call before REST runs: INVALID_SNAPSHOT_ID means the snapshot ID is invalid; copy it unchanged from list_snapshots. KEY_FORMAT means an invalid key shape; KEY_RECENTLY_REJECTED means the key was recently refused; KEY_CHECKS_PAUSED means new key checks are briefly paused. Fix the key or wait as directed instead of looping. OUTCOME_UNKNOWN means an upload or deletion may have completed despite a lost reply. For upload, preserve the exact payload. For deletion, run a fresh dry run without confirm to check whether the transcript remains. These are MCP-side conditions, not additional REST response codes.

StatusCodeMeaningYour next move
400BAD_REQUESTInvalid snapshot ID or deletion confirmationCopy the ID from the list and use the latest dry-run expected_count.
500noneAuthentication or rate-limit service failedRetry with bounded backoff; contact support if it persists.
502UPSTREAMSnapshot browse or raw deletion failedBack off; reconcile a deletion with a fresh dry run before retrying confirmation.
400none ("error": "Validation error")Missing or invalid fieldFix the request; message or details identifies the invalid field.
400INVALID_DATEThe server rejected the upload dateSend the real meeting date.
400INVALID_TRANSCRIPTEmpty or unrecognized transcriptSend a supported format and match format to the content.
400NO_ORGThe Mind Twin is not fully provisioned for uploadsContact support to complete setup.
400SELF_NOT_A_SPEAKERThe owner label does not match a speakerCorrect self_speaker (MCP) or selfSpeaker (REST); for VTT/text, include it in participants. Nothing was saved.
400INVALID_CURSORThe snapshot page cursor is invalidRestart browsing without cursor.
401noneMissing, malformed, or revoked keyRe-copy or regenerate the key.
403none ("Insufficient scope") or INSUFFICIENT_SCOPEThe key lacks the scope; a teammate target needs twin:uploadOmit target, or use a Mind Twin Teams key.
403NO_CALLERThe key is not tied to a userCheck the key owner in the app.
403IP_BLOCKEDToo many failed key attempts from your IPWait for the Retry-After header (seconds), then fix the key.
404NOT_FOUNDNo Mind Twin for your account in this workspaceSet one up in the MindTwins app.
404NO_TWINGET /me found no Mind Twin for your accountSet one up in the MindTwins app.
404TARGET_NOT_FOUNDtarget does not match a reachable team Mind TwinCheck the name or email with GET /twins.
404MIND_NOT_FOUNDUpload target has no mind to feed yetSet it up in the app first.
409ALREADY_PROCESSINGSame transcript is already processingNothing to do. Do not upload it again.
409BUILD_IN_PROGRESSMind Twin is busy with another buildRetry after it finishes.
409ORPHANED_ARTIFACTA previous upload did not finish building; this upload was not savedRetry the same upload; contact support if it repeats.
409PRECONDITION_FAILEDRaw deletion count changed since the dry runRun the dry run again before confirming.
413CONTENT_TOO_LARGE / FUNCTION_PAYLOAD_TOO_LARGEMessage, transcript, or encoded request body too largeChat: up to 800,000 characters. Keep the complete upload request under the recommended 4,000,000-byte budget. Hosting-layer errors may be plain text.
422AMBIGUOUS_TARGETName matches more than one personUse their email.
422LOW_QUALITY_CONTENTNot enough meaningful conversation to learn fromUse a longer, substantive transcript. Aim for a few hundred words; this is guidance, not a fixed minimum.
423TWIN_PAUSEDThe owner paused the Mind TwinResume your Mind Twin in the app, or wait for the teammate to resume theirs.
429noneRate limitWait until the retryAfter body field (an ISO timestamp), then back off.
502 / 503 / 504INTERNAL / UNAVAILABLE / TIMEOUTTransient service or upstream failureBack off for read requests. For an upload or deletion with a lost response, reconcile the outcome before retrying.

Fast diagnosis

The client sees no tools.

Run the copied install command again, confirm the Bearer key is present, then restart the MCP client.

Status is building with little visible progress.

That is expected for a fresh Mind Twin. In MCP, a blank or zero learned-transcript count is not a live meter. Check periodically. A Mind Twin with nothing uploaded returns 200 building with progress 0 and needs_upload: true. Investigate failed builds and requests that exceed your integration's waiting budget.

Status says needs_upload.

A Mind Twin with nothing uploaded returns 200 building, progress 0, and needs_upload: true. Upload a transcript to start building. A 404 NOT_FOUND means this account has no Mind Twin in the workspace; set one up in the MindTwins app.

Status says ready and ingesting.

Keep chatting. The Mind Twin remains ready while the new transcript lands; recall of it sharpens shortly.

The transcript date is unknown.

Ask for the real meeting date. Never guess or default to today. Confirm each transcript separately.

The API says the transcript already exists.

For a retry, resend the same transcript, exact date string, title, format, target, source, duration, and participants in the same order. Changing meeting details can save a second copy. Deduplication compares generated transcript content within the selected Mind Twin. A completed duplicate returns 200; queued or processing duplicates can also return 200 in workspaces with a build queue. ALREADY_PROCESSING means the same transcript is in progress: check status instead of uploading again. BUILD_IN_PROGRESS means this upload was not saved: wait for the current build, then retry. If an upload reply is lost, check status first and preserve the original payload for any retry.

The key format is rejected.

A valid provisioned key starts with dev_ and is 41 characters in total, including dev_. Re-copy it from MCP Twin.

Documentation

Ready for your editor. And your agent.

Open the Markdown reference or download OpenAPI. Copy docs uses the same content.

Use mcp.mindtwins.com/mcp for MCP clients and app.mindtwins.com/api/twin-mcp for REST requests. These are different transports for the same Mind Twin integration; keep the hostname and path together.

Documentation revision: . This date versions the guide, not the API. REST paths are currently unversioned.

What changed · 2026-10-08
  • Added source-verified REST history, attached text, agent JSON, response examples, rate headers, and an OpenAPI reference.
  • Added workspace setup, named-speaker transcript examples, and per-key rate limits.
  • Aligned chat limits, corrected the live health response, and replaced the 50 MB upload claim with a conservative request budget.
  • Explained stateless MCP chat, long requests, polling, snapshot outputs, and current data controls.
  • Made examples readable without email decoding and linked the Markdown reference directly.
  • Verified MCP upload fields, source values, tool result envelopes, readiness flags, and retry behavior against the current server source.

One key. One workspace.

Your first answer is one request away.

Open MCP Twin, copy your provisioned key, and choose the path your software needs.

Open the app Request access

MindTwins

Request your invite.

Get early access to MindTwins.
We’ll email you when your invite is ready.

No password. Just your email.

Privacy Policy