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
Developers
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.
YouAsk Maya's Mind Twin what would make her reject this rollout.
{ target: "Maya Chen" }Start with what you are building
Both paths upload, check readiness, and ask. Choose who should make the call.
Your assistant chooses the right tool from plain language. No integration backend to build.
Your server controls every request and receives structured JSON. No SDK required.
Before your first call
Set up the Mind Twin in the app. Then connect your software.
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.
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.
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
A Mind Twin needs to know which words belong to its person.
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>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
Three actions take a Mind Twin from a meeting to a decision-ready answer.
Send a dated transcript. VTT, SRT, text, and agent JSON all work.
upload_transcriptLearning runs in the background. Poll periodically until the status is ready.
get_statusAsk about a past decision or a new situation. Get the answer and the reasoning around it.
chat_with_twinBuilt 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
One hosted server gives an MCP-capable assistant everything it needs to keep a Mind Twin current and ask it questions.
The command below runs through npx, which comes with Node.js.
brew install nodenodejs.orgDownload sudo apt install nodejsnode --version
npx --versionOpen MCP Twin in the app. Copy your provisioned twin:chat key. For teammates, follow Teams setup.
The installer connects every supported MCP client it detects.
If the tools do not appear, quit and reopen the client. Then ask which mind-twin tools it sees.
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 -yclaude mcp add --transport http mind-twin https://mcp.mindtwins.com/mcp \
--header "Authorization: Bearer dev_YOUR_TWIN_CHAT_KEY"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.
https://mcp.mindtwins.com/mcpmind-twinAgent integrations
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.
Ask one consequential question and request JSON when your agent needs structure.
{
"name": "chat_with_twin",
"arguments": {
"message": "What would make you reject this rollout?",
"target": "Maya Chen",
"format": "json"
}
}{
"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.
upload_transcriptUpload field referenceLimits below are validated by the MCP tool. REST names show what the MCP client sends.
| MCP field | REST field | Type and limit | Meaning |
|---|---|---|---|
transcript | transcript | string · required · 1 to 10,000,000 characters | One meeting in VTT, SRT, plain text, or agent JSON. The character limit is the MCP schema limit; the encoded request budget still applies. |
date | date | ISO-8601 string · required | The 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. |
title | title | string · optional · 1 to 500 characters | The meeting's actual title, when known. |
format | format | enum · optional | vtt, 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. |
target | target | string · optional · up to 200 characters | A teammate's name or email; requires twin:upload. Whitespace is trimmed. Omit or leave blank for your own Mind Twin. |
participants | participants | string[] · optional · up to 100 names | Each name is trimmed and limited to 200 characters. Blank names are dropped. Keep the same order on retries. |
source | source | enum · optional | The 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. |
duration | duration | number · optional · zero or greater | Meeting duration in seconds, not minutes or milliseconds. Helps space lines when the transcript has no timestamps. |
self_speaker | selfSpeaker | string · optional · up to 200 characters | The 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.
| Tool | What it does | Inputs |
|---|---|---|
whoami | Shows your identity and an early readiness signal. Use get_status for build readiness. | None. |
list_twins | Lists workspace Mind Twins by display name. Use get_status with the intended target to verify access and build readiness. | None. |
chat_with_twin | Asks 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_transcript | Feeds 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_status | Checks whether a Mind Twin is ready. | target (optional). |
list_snapshots | Lists 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_detail | Shows 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_raw | Permanently 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
Use ordinary HTTPS from any server language. Every authenticated request carries the same Bearer key.
200 · application/json
answer is the complete response. say is the short spoken line. Any empty Think, Feel, Say, or Act field is omitted.
// 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();{
"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."
}https://app.mindtwins.com/api/twin-mcpMind Twin Teams
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.
{ "target": "Maya Chen" }Complete reference
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.
chat_with_twinmessage required, 1 to 800,000 characters · target optional · format defaults to text; pass json for structured TFSA
upload_transcripttranscript 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
get_statusNo fields for your own Mind Twin · target optional · needs_upload and ready + ingesting are expected conditions
| Intent | MCP tool | REST endpoint | Returns |
|---|---|---|---|
| Ask a Mind Twin | chat_with_twin | POST/chat | Answer + TFSA |
| Add a meeting | upload_transcript | POST/upload | Processing state |
| Check readiness | get_status | GET/me/status | Status + progress |
| Check service | Not exposed | GET/health | Service status |
| Identify yourself | whoami | GET/me | Identity + own Mind Twin readiness |
| Find a Mind Twin | list_twins | GET/twins | Mind Twins with name, email, ownership, ready, status |
| Browse snapshots | list_snapshots | GET/snapshots | snapshots, next_cursor, total |
| Inspect a snapshot | snapshot_detail | GET/snapshots/{id} | Snapshot summaries and counts |
| Remove raw material | delete_raw | DELETE/snapshots/{id}/raw | Dry run or confirmed deletion |
OpenAPI 3.1 reference. Response examples use illustrative values.
/chatAsk a Mind TwinSend 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 charactersThe question to answer.
targetstring · optional · 1 to 200 charactersa teammate's display name (see list_twins) or email. Requires twin:upload for a teammate.
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"
}{
"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."
}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.
{
"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."
}
]
}/uploadAdd a meetingRecommended 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 · requiredVTT, SRT, plain text, or agent JSON.
dateISO-8601 · requiredThe real meeting date or timestamp. Invalid dates return 400 INVALID_DATE. Use the real meeting date; confirm each transcript separately.
titlestring · optional · max 500A human-readable meeting name.
formatenum · optionalvtt, srt, text, or agent-json. Omit for VTT/text passthrough; set srt or agent-json explicitly.
targetstring · optional · 1 to 200 charactersa teammate's display name (see list_twins) or email. Requires twin:upload for a teammate.
participantsstring[] · optional · up to 100 namesMeeting speaker names. Preserve their order on retry.
durationnumber · optional · zero or greaterMeeting duration in seconds.
sourceenum · optionalfathom, zoom, gong, google_meet, fireflies, microsoft_teams, manual, sybill, affinity_notetaker, granola, raw_import. Omit for manual.
selfSpeakerstring · optional · max 200 charactersExact 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.
{
"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.
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"
}{
"success": true,
"data": {
"status": "processing"
}
}/me/statusCheck readinessUse ?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.
GET https://app.mindtwins.com/api/twin-mcp/me/status?target=Maya%20Chen
Authorization: Bearer $MINDTWINS_KEY{
"status": "building",
"progress": 42,
"ingesting": false
}/healthCheck service livenessNo key required. Use it for a simple service liveness check.
GET https://app.mindtwins.com/api/twin-mcp/health{
"status": "ok",
"service": "twin-mcp",
"timestamp": "2026-10-08T14:35:56.581Z"
}/meIdentify yourselfIdentify 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.
{
"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"
}/twinsFind a Mind TwinList 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.
{
"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"
}
]
}/snapshotsBrowse snapshotsBrowse 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.
{
"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
}/snapshots/{id}Inspect a snapshotRead 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.
{
"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": []
}
}/snapshots/{id}/rawRemove raw materialPreview 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.
{
"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
Every authenticated request is tied to one caller and one workspace. The request never supplies a workspace id.
twin:chatEveryoneEvery action on the key owner's Mind Twin, including snapshot browsing and delete_raw.
twin:uploadMind Twin TeamsA 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
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 environment | Per minute | Per hour | Per day |
|---|---|---|---|
| Development | 60 | 1,000 | 10,000 |
| Production | 300 | 10,000 | 100,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.
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.
MCP chat does not remember earlier messages. Include the relevant conversation context in each message.
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
Application errors return JSON with error; code and message are usually present. Check Content-Type first: hosting-layer errors can be plain text.
{
"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.
| Status | Code | Meaning | Your next move |
|---|---|---|---|
400 | BAD_REQUEST | Invalid snapshot ID or deletion confirmation | Copy the ID from the list and use the latest dry-run expected_count. |
500 | none | Authentication or rate-limit service failed | Retry with bounded backoff; contact support if it persists. |
502 | UPSTREAM | Snapshot browse or raw deletion failed | Back off; reconcile a deletion with a fresh dry run before retrying confirmation. |
400 | none ("error": "Validation error") | Missing or invalid field | Fix the request; message or details identifies the invalid field. |
400 | INVALID_DATE | The server rejected the upload date | Send the real meeting date. |
400 | INVALID_TRANSCRIPT | Empty or unrecognized transcript | Send a supported format and match format to the content. |
400 | NO_ORG | The Mind Twin is not fully provisioned for uploads | Contact support to complete setup. |
400 | SELF_NOT_A_SPEAKER | The owner label does not match a speaker | Correct self_speaker (MCP) or selfSpeaker (REST); for VTT/text, include it in participants. Nothing was saved. |
400 | INVALID_CURSOR | The snapshot page cursor is invalid | Restart browsing without cursor. |
401 | none | Missing, malformed, or revoked key | Re-copy or regenerate the key. |
403 | none ("Insufficient scope") or INSUFFICIENT_SCOPE | The key lacks the scope; a teammate target needs twin:upload | Omit target, or use a Mind Twin Teams key. |
403 | NO_CALLER | The key is not tied to a user | Check the key owner in the app. |
403 | IP_BLOCKED | Too many failed key attempts from your IP | Wait for the Retry-After header (seconds), then fix the key. |
404 | NOT_FOUND | No Mind Twin for your account in this workspace | Set one up in the MindTwins app. |
404 | NO_TWIN | GET /me found no Mind Twin for your account | Set one up in the MindTwins app. |
404 | TARGET_NOT_FOUND | target does not match a reachable team Mind Twin | Check the name or email with GET /twins. |
404 | MIND_NOT_FOUND | Upload target has no mind to feed yet | Set it up in the app first. |
409 | ALREADY_PROCESSING | Same transcript is already processing | Nothing to do. Do not upload it again. |
409 | BUILD_IN_PROGRESS | Mind Twin is busy with another build | Retry after it finishes. |
409 | ORPHANED_ARTIFACT | A previous upload did not finish building; this upload was not saved | Retry the same upload; contact support if it repeats. |
409 | PRECONDITION_FAILED | Raw deletion count changed since the dry run | Run the dry run again before confirming. |
413 | CONTENT_TOO_LARGE / FUNCTION_PAYLOAD_TOO_LARGE | Message, transcript, or encoded request body too large | Chat: 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. |
422 | AMBIGUOUS_TARGET | Name matches more than one person | Use their email. |
422 | LOW_QUALITY_CONTENT | Not enough meaningful conversation to learn from | Use a longer, substantive transcript. Aim for a few hundred words; this is guidance, not a fixed minimum. |
423 | TWIN_PAUSED | The owner paused the Mind Twin | Resume your Mind Twin in the app, or wait for the teammate to resume theirs. |
429 | none | Rate limit | Wait until the retryAfter body field (an ISO timestamp), then back off. |
502 / 503 / 504 | INTERNAL / UNAVAILABLE / TIMEOUT | Transient service or upstream failure | Back off for read requests. For an upload or deletion with a lost response, reconcile the outcome before retrying. |
Run the copied install command again, confirm the Bearer key is present, then restart the MCP client.
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.
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.
Keep chatting. The Mind Twin remains ready while the new transcript lands; recall of it sharpens shortly.
Ask for the real meeting date. Never guess or default to today. Confirm each transcript separately.
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.
A valid provisioned key starts with dev_ and is 41 characters in total, including dev_. Re-copy it from MCP Twin.
Documentation
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.
One key. One workspace.
Open MCP Twin, copy your provisioned key, and choose the path your software needs.