{"openapi":"3.1.0","info":{"title":"Tough Customer workspace API","version":"1.0.0","description":"Every tool the workspace MCP connector exposes, callable over HTTPS with a workspace API key. Mint a key at Integrations → REST API (workspace admins only). A key acts as the admin who minted it — including their Salesforce connection — and reaches exactly the tools that admin sees. Send it as `Authorization: Bearer <key>`; never in a URL. Every response is `Cache-Control: no-store`; every authenticated response carries `X-RateLimit-Limit` / `X-RateLimit-Remaining` and `X-Request-Id`.","termsOfService":"https://sandbox.toughcustomer.ai/terms","contact":{"name":"Tough Customer support","email":"support@toughcustomer.ai","url":"https://sandbox.toughcustomer.ai/docs/api"}},"externalDocs":{"description":"Workspace API documentation","url":"https://sandbox.toughcustomer.ai/docs/api"},"servers":[{"url":"https://sandbox.toughcustomer.ai"}],"security":[{"workspaceApiKey":[]}],"tags":[{"name":"catalog","description":"What a key may call."},{"name":"member","description":"Available to every key."},{"name":"admin","description":"Available while the key's owner is a workspace admin."}],"paths":{"/api/v1/{orgId}/tools":{"get":{"operationId":"listTools","summary":"The tools this key may call","description":"The catalog for the key's owner: every member tool, the admin tools while the owner is a workspace admin, and the workspace's enabled custom tools (org_tool) — each with the same JSON schema MCP clients see in tools/list. Custom tools are per-workspace and appear ONLY here; they are called by name like any other tool.","tags":["catalog"],"parameters":[{"$ref":"#/components/parameters/orgId"}],"responses":{"200":{"description":"The catalog.","content":{"application/json":{"schema":{"type":"object","required":["workspace","tools","rateLimit"],"properties":{"workspace":{"type":"object","properties":{"orgId":{"type":"string"}}},"tools":{"type":"array","items":{"type":"object","required":["name","description","kind","gate","annotations","inputSchema"],"properties":{"name":{"type":"string"},"title":{"type":["string","null"]},"description":{"type":"string"},"kind":{"type":"string","enum":["builtin","workspace"]},"gate":{"type":"string","enum":["always","salesforce","admin"]},"annotations":{"type":"object"},"inputSchema":{"type":"object"}}}},"rateLimit":{"type":"object","properties":{"limit":{"type":"integer"},"windowSeconds":{"type":"integer"}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/list_simulations":{"post":{"operationId":"list_simulations","summary":"List AI-buyer simulations","description":"List the AI-buyer simulations in your organization (id, target URL, status, business + buyer name, and the scenarioId of each buyer's catalog row — use scenarioId with list_scenarios / journeys / canonical launch URLs). Behavior: read-only.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"list_simulations"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/create_simulation":{"post":{"operationId":"create_simulation","summary":"Create AI buyer from URL","description":"Generate a new AI buyer from a company URL: scrapes the site and drafts buyer + seller personas (Gemini). Returns the simulation id, status, and a launch URL. Behavior: write.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":true},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri","description":"Company URL to base the AI buyer on, e.g. https://acme.com"}},"required":["url"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"create_simulation"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/create_roleplay_session":{"post":{"operationId":"create_roleplay_session","summary":"Start roleplay session","description":"Start a roleplay session for a simulation. Returns a session id and a launch URL to run the voice roleplay in the browser. role 'reverse' = you play the buyer. Behavior: write.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"simulationId":{"type":"string","format":"uuid","description":"ai_simulation id from list_simulations / create_simulation"},"role":{"type":"string","enum":["forward","reverse"],"description":"forward = you sell (default); reverse = you play the buyer"}},"required":["simulationId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"create_roleplay_session"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/get_session_score":{"post":{"operationId":"get_session_score","summary":"Get session score","description":"Get the MEDDPICC score + coaching for a roleplay session. Returns scored=false if the session hasn't been scored yet (run the roleplay in the browser first). Behavior: read-only.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string","format":"uuid","description":"roleplay_session id from create_roleplay_session"}},"required":["sessionId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"get_session_score"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/list_scenarios":{"post":{"operationId":"list_scenarios","summary":"List scenarios","description":"List the coaching scenarios configured in your organization. Behavior: read-only.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"list_scenarios"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/list_voices":{"post":{"operationId":"list_voices","summary":"List AI voices","description":"List the AI voices available for roleplay sessions. Behavior: read-only.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"list_voices"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/tough_learning":{"post":{"operationId":"tough_learning","summary":"My assigned learning","description":"List YOUR assigned learning — the journey steps waiting on you — with launch URLs. The /learning page as a tool (T43); same rows as Slack /tough_learning. Behavior: read-only.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"tough_learning"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/connect_salesforce":{"post":{"operationId":"connect_salesforce","summary":"Connect Salesforce","description":"Get a link to connect your Salesforce account (per-user OAuth). Returns a URL only — open it in your browser to authorize; no token is ever shown here. Behavior: read-only.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":true,"openWorldHint":true},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"connect_salesforce"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/disconnect_salesforce":{"post":{"operationId":"disconnect_salesforce","summary":"Disconnect Salesforce","description":"Disconnect your Salesforce account from this workspace (revokes + deletes your stored token). Behavior: write (destructive).","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":true},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"disconnect_salesforce"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/list_opportunities":{"post":{"operationId":"list_opportunities","summary":"List Salesforce opportunities","description":"List your Salesforce opportunities (filtered by your own SF permissions). Optional query filters by name. Behavior: read-only. Runs on the key owner's Salesforce connection (connect_salesforce first).","tags":["member"],"x-gate":"salesforce","x-annotations":{"readOnlyHint":true,"openWorldHint":true},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"query":{"type":"string","description":"Filter opportunities by name substring"}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"list_opportunities"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/get_opportunity_contacts":{"post":{"operationId":"get_opportunity_contacts","summary":"Get opportunity contacts","description":"List the contacts + roles on a Salesforce opportunity (as visible to you). Behavior: read-only. Runs on the key owner's Salesforce connection (connect_salesforce first).","tags":["member"],"x-gate":"salesforce","x-annotations":{"readOnlyHint":true,"openWorldHint":true},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"opportunityId":{"type":"string","description":"Salesforce Opportunity Id from list_opportunities"}},"required":["opportunityId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"get_opportunity_contacts"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/get_coach_context":{"post":{"operationId":"get_coach_context","summary":"Get deal-coaching context","description":"Build a coaching brief for a Salesforce opportunity — deal details, products, and contacts — to ground a roleplay or coaching conversation. Behavior: read-only. Runs on the key owner's Salesforce connection (connect_salesforce first).","tags":["member"],"x-gate":"salesforce","x-annotations":{"readOnlyHint":true,"openWorldHint":true},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"opportunityId":{"type":"string","description":"Salesforce Opportunity Id from list_opportunities"}},"required":["opportunityId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"get_coach_context"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/create_roleplay":{"post":{"operationId":"create_roleplay","summary":"Save roleplay scenario","description":"Author a PERMANENT, org-wide roleplay scenario that ALL teammates can see in the catalog and run (e.g. a buyer persona composed from opp_coach / Salesforce data). This SAVES a reusable scenario and returns its launch URL — it does NOT start a session; to start a one-off run of an existing simulation use create_roleplay_session instead. The roleplay has EXACTLY ONE AI buyer (single voice) talking to the human rep — author a single-persona scenario, never a multi-stakeholder scene. Behavior: write.","tags":["member"],"x-gate":"always","x-annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Short scenario title, e.g. 'Acme renewal — CFO price objections'"},"instructions":{"type":"string","minLength":1,"maxLength":8000,"description":"The buyer-persona system prompt (the scenario body) for EXACTLY ONE buyer: who the AI buyer is (name, title, company), what they're evaluating/buying (products, quantities, prices, total deal value), their objections, the competitor they're considering, and optionally personality traits. Write it addressed to the AI buyer ('Your name is …'). If the deal has several contacts, pick ONE — default the primary/decision-maker — and write only that person; reference any others as absent stakeholders the buyer mentions ('my CFO will need ROI proof'), NOT as additional speakers. Never author a two-person/panel scene — the runtime drives a single voice."},"caseInfo":{"type":"string","maxLength":4000,"description":"Rep-facing case briefing shown before launch (situation, goal). Optional."},"competencyCategory":{"type":"string","description":"Scoring competency category label. Optional."},"voiceName":{"type":"string","description":"AI voice for the buyer — a name from list_voices. Optional."},"passThreshold":{"type":"number","minimum":0,"maximum":100,"description":"Pass score 0–100 (default 70). Optional."},"sourceOppId":{"type":"string","description":"Salesforce Opportunity Id this persona was built from (provenance). Optional."}},"required":["name","instructions"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"create_roleplay"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/export_session_analytics":{"post":{"operationId":"export_session_analytics","summary":"Export session analytics","description":"ADMIN ONLY. Export org-wide roleplay/quiz/coaching session analytics across ALL members for LLM analysis: PLG rows (learner, scenario, scores, duration) + a computed summary (totals, leaderboard, per-category, per-competency, monthly time series, % attempted, % passed). Filterable + paged; large orgs are capped — check `truncated` and page with `offset`. Behavior: read-only. Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string","description":"ISO date — sessions created on/after"},"to":{"type":"string","description":"ISO date — sessions created on/before"},"sessionType":{"type":"string","description":"e.g. \"Roleplay\", \"Quiz\", \"Coaching\""},"scenarioCategory":{"type":"string","description":"Filter by scenario category"},"userId":{"type":"string","format":"uuid","description":"Single learner (app_user id) drill-down"},"limit":{"type":"integer","minimum":1,"maximum":5000,"description":"Returned-row cap (default 1000)"},"offset":{"type":"integer","minimum":0,"description":"Returned-row pagination offset (default 0)"},"includeRows":{"type":"boolean","description":"false → summary only (smallest payload). Default true."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"export_session_analytics"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/analytics_report_html":{"post":{"operationId":"analytics_report_html","summary":"Analytics HTML report","description":"ADMIN ONLY. Generate a self-contained HTML analytics dashboard (the dashboard-as-a-file) for this org — metric cards, leaderboard, category + monthly charts, raw table. Returns { filename, html }; save `html` to that .html file and open it. Same filters as export_session_analytics; embedded rows are capped (check `truncated`). Behavior: read-only. Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"from":{"type":"string"},"to":{"type":"string"},"sessionType":{"type":"string"},"scenarioCategory":{"type":"string"},"userId":{"type":"string","format":"uuid"},"limit":{"type":"integer","minimum":1,"maximum":2000,"description":"Rows embedded in the file (default 500)"}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"analytics_report_html"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/create_scenario":{"post":{"operationId":"create_scenario","summary":"Create scenario","description":"ADMIN ONLY. Create a scenario in the org catalog — Roleplay, Message, Demo, Screenshare, or Coach — with the full editable field set (the admin console's create form as a tool). Quiz/Instructor are authored in the web console (question bank / indexed lesson deck). Returns { scenarioId, launchUrl }. Behavior: write. Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Scenario title."},"category":{"type":"string","enum":["Roleplay","Message","Demo","Instructor","Screenshare","Coach","Quiz"],"description":"Roleplay | Message | Demo | Screenshare | Coach. (Quiz and Instructor are refused — their dependent resources are authored in the web console.)"},"body":{"type":"string","minLength":1,"maxLength":20000,"description":"The scenario body / system prompt — buyer persona (Roleplay), presenter brief (Message), tutor instructions (Screenshare), coach persona (Coach). Required for those categories; not applicable to Demo."},"caseInfo":{"type":"string","maxLength":4000,"description":"Rep-facing case briefing shown before launch. Defaults to 'Authored by an AI agent.' Not applicable to Coach."},"competencyCategory":{"type":"string","minLength":1,"maxLength":200,"description":"Scoring rubric category — must match competencies.category (see list_competencies) to score. Roleplay/Message/Demo only."},"fileLink":{"type":"string","format":"uri","maxLength":2000,"description":"Deck/file URL. Message/Demo/Instructor/Screenshare only."},"coach":{"type":"integer","exclusiveMinimum":0,"description":"Companion coach: an in-org scenario id of category Coach. Roleplay/Message/Demo only."},"voiceName":{"type":"string","minLength":1,"maxLength":100,"description":"AI voice — a value from list_voices. Not applicable to Demo."},"passThreshold":{"type":"integer","minimum":0,"maximum":100,"description":"Pass mark 0–100 (default 70)."},"scoringPrompt":{"type":"string","minLength":1,"maxLength":8000,"description":"Custom scoring prompt (partial-credit scale recommended). Roleplay/Message/Demo only."},"sendEmail":{"type":"boolean","description":"Email the score report after each session. Roleplay only."}},"required":["name","category"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"create_scenario"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/get_scenario":{"post":{"operationId":"get_scenario","summary":"Get scenario","description":"ADMIN ONLY. Read one scenario's full EDITABLE field set (any category) — the fields update_scenario accepts. Internal columns are never returned. Behavior: read-only. Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"scenarioId":{"type":"integer","exclusiveMinimum":0,"description":"Scenario id from list_scenarios."}},"required":["scenarioId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"get_scenario"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/update_scenario":{"post":{"operationId":"update_scenario","summary":"Update scenario","description":"ADMIN ONLY. Partially update a scenario — body, scoring prompt, any editable field; omitted fields are untouched. Roleplay body/scoring edits propagate to the launch copies exactly like the web edit form (one shared writer). Untouched Quiz settings are preserved verbatim. Behavior: write (destructive). Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"scenarioId":{"type":"integer","exclusiveMinimum":0,"description":"Scenario id from list_scenarios / get_scenario."},"name":{"type":"string","minLength":1,"maxLength":120},"category":{"type":"string","enum":["Roleplay","Message","Demo","Instructor","Screenshare","Coach","Quiz"],"description":"Change the category. Converting INTO Quiz/Instructor is refused (dependent resources); restating the current category is a no-op."},"body":{"type":"string","minLength":1,"maxLength":20000,"description":"The scenario body / system prompt — buyer persona (Roleplay), presenter brief (Message), tutor instructions (Screenshare), coach persona (Coach). Required for those categories; not applicable to Demo."},"caseInfo":{"type":"string","maxLength":4000,"description":"Rep-facing case briefing shown before launch. Defaults to 'Authored by an AI agent.' Not applicable to Coach."},"competencyCategory":{"type":"string","minLength":1,"maxLength":200,"description":"Scoring rubric category — must match competencies.category (see list_competencies) to score. Roleplay/Message/Demo only."},"fileLink":{"type":"string","format":"uri","maxLength":2000,"description":"Deck/file URL. Message/Demo/Instructor/Screenshare only."},"coach":{"type":"integer","exclusiveMinimum":0,"description":"Companion coach: an in-org scenario id of category Coach. Roleplay/Message/Demo only."},"voiceName":{"type":"string","minLength":1,"maxLength":100,"description":"AI voice — a value from list_voices. Not applicable to Demo."},"passThreshold":{"type":"integer","minimum":0,"maximum":100,"description":"Pass mark 0–100 (default 70)."},"scoringPrompt":{"type":"string","minLength":1,"maxLength":8000,"description":"Custom scoring prompt (partial-credit scale recommended). Roleplay/Message/Demo only."},"sendEmail":{"type":"boolean","description":"Email the score report after each session. Roleplay only."},"scoringMode":{"type":"string","enum":["first_attempt","highest_attempt","reduced_credit","mastery"],"description":"Quiz only. Untouched Quiz settings are preserved on partial updates."},"voiceCoachingEnabled":{"type":"boolean","description":"Quiz only."}},"required":["scenarioId"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"update_scenario"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/delete_scenario":{"post":{"operationId":"delete_scenario","summary":"Delete scenario","description":"ADMIN ONLY. Permanently delete a scenario from the org catalog. Requires confirm: true — this cannot be undone. Behavior: write (destructive). Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"scenarioId":{"type":"integer","exclusiveMinimum":0},"confirm":{"type":"boolean","description":"Must be true — deletion is permanent and cannot be undone."}},"required":["scenarioId","confirm"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"delete_scenario"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/create_competencies":{"post":{"operationId":"create_competencies","summary":"Create competencies","description":"ADMIN ONLY. Bulk-insert a competency RECORD SET under ONE category — many { subcategory, name, body } items (subcategories become radar-chart axes). Idempotent: duplicates on (category, subcategory, name) are skipped by a DB unique index, so re-runs and retries are safe. The \"insert multiple competencies with the same category\" tool. Behavior: write. Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"category":{"type":"string","minLength":1,"maxLength":200,"description":"The record set's category — every item lands under it (a radar chart's identity)."},"competencies":{"type":"array","items":{"type":"object","properties":{"subcategory":{"type":"string","minLength":1,"maxLength":200,"description":"Radar-chart axis — items sharing a subcategory average into one axis."},"name":{"type":"string","minLength":1,"maxLength":2000,"description":"Short competency label."},"body":{"type":"string","minLength":1,"maxLength":4000,"description":"The scoring criterion text — STRONGLY recommended (the AI scores against it; without body the axis scores 0)."}},"required":["subcategory","name"],"additionalProperties":false},"minItems":1,"maxItems":200}},"required":["category","competencies"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"create_competencies"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/update_competencies":{"post":{"operationId":"update_competencies","summary":"Update competencies","description":"ADMIN ONLY. Edit one (category, subcategory) group of the rubric in a SINGLE transaction: rows with id are edited, rows without id are added, deletedIds are removed. Ids outside this org+group are skipped (skippedForeign), never moved. At least one edit or delete is required. Behavior: write (destructive). Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":false,"destructiveHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"category":{"type":"string","minLength":1,"maxLength":200},"subcategory":{"type":"string","minLength":1,"maxLength":200},"competencies":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","description":"Existing row id from list_competencies — omit to ADD a new item to the group."},"name":{"type":"string","minLength":1,"maxLength":2000},"body":{"type":"string","maxLength":4000,"description":"Include to set the criterion ('' clears it); omit to leave unchanged."}},"required":["name"],"additionalProperties":false},"maxItems":200},"deletedIds":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":200}},"required":["category","subcategory"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"update_competencies"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/list_competencies":{"post":{"operationId":"list_competencies","summary":"List competencies","description":"ADMIN ONLY. The org's scoring rubric grouped category → subcategory → items ({ id, name, body }). The ids are the handles for update_competencies. Paginated: check truncated. Behavior: read-only. Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":true,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"category":{"type":"string","minLength":1,"description":"Filter to one category."},"limit":{"type":"integer","minimum":1,"maximum":2000,"description":"Max rows before grouping (default 500). truncated:true means more exist — raise limit or filter by category."}},"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"list_competencies"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}},"/api/v1/{orgId}/tools/invite_user":{"post":{"operationId":"invite_user","summary":"Invite teammate","description":"ADMIN ONLY. Invite one teammate into this workspace by email, with a workspace permission (admin|member, default member) and optional profile fields (name, job role, geo, business unit, manager) that land on their member record when they accept. Loop this tool for a list — each call stands alone. If an error starts with `seat_cap_reached` or `rate_limited`, STOP looping: further invites will also fail. Returns { invited, invitationId, email, permission, status }. Behavior: write. Admin-only: the key's owner must be a workspace admin.","tags":["admin"],"x-gate":"admin","x-annotations":{"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false},"parameters":[{"$ref":"#/components/parameters/orgId"}],"requestBody":{"required":false,"description":"The tool's arguments. An empty body is allowed for tools without required arguments.","content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","format":"email","maxLength":320,"description":"Email address to invite."},"permission":{"type":"string","enum":["admin","member"],"description":"Workspace permission — NOT the job role. Default 'member'; 'admin' can manage scenarios, members, and billing."},"firstName":{"type":"string","maxLength":200,"description":"Invitee first name (pre-fills their profile on accept)."},"lastName":{"$ref":"#/properties/firstName","description":"Invitee last name."},"jobRole":{"$ref":"#/properties/firstName","description":"Job role (AE/SDR/Manager…) — the analytics attribute, not the permission."},"geo":{"$ref":"#/properties/firstName","description":"Geo attribute."},"bu":{"$ref":"#/properties/firstName","description":"Business-unit attribute."},"manager":{"$ref":"#/properties/firstName","description":"Manager attribute."}},"required":["email"],"additionalProperties":false,"$schema":"http://json-schema.org/draft-07/schema#"}}}},"responses":{"200":{"description":"The tool ran; `result` is its output decoded as JSON.","content":{"application/json":{"schema":{"type":"object","required":["ok","tool","result"],"properties":{"ok":{"type":"boolean","const":true},"tool":{"type":"string","const":"invite_user"},"result":{}}}}}},"400":{"$ref":"#/components/responses/InvalidArguments"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"413":{"$ref":"#/components/responses/PayloadTooLarge"},"415":{"$ref":"#/components/responses/UnsupportedMediaType"},"422":{"$ref":"#/components/responses/ToolError"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/Internal"}}}}},"components":{"securitySchemes":{"workspaceApiKey":{"type":"http","scheme":"bearer","bearerFormat":"tc_… (46 characters; minted at Integrations → REST API)","description":"A workspace API key. It belongs to ONE workspace — the {orgId} in the path must be that workspace's id (the same id as the MCP URL)."}},"parameters":{"orgId":{"name":"orgId","in":"path","required":true,"description":"The workspace id (Clerk organization id, `org_…`) — shown with the endpoint on Integrations → REST API.","schema":{"type":"string","pattern":"^org_[A-Za-z0-9]{1,64}$"}}},"schemas":{"Error":{"type":"object","required":["ok","error"],"properties":{"ok":{"type":"boolean","const":false},"error":{"type":"string","enum":["unauthorized","not_found","forbidden","conflict","invalid_json","invalid_arguments","unsupported_media_type","payload_too_large","tool_error","rate_limited","internal"]},"message":{"type":"string"},"code":{"type":"string","description":"The tool's own error code, when it set one."},"issues":{"type":"array","description":"invalid_arguments only — one entry per schema violation.","items":{"type":"object","properties":{"path":{"type":"array","items":{"type":["string","integer"]}},"message":{"type":"string"}}}},"retryAfterSeconds":{"type":"integer","description":"rate_limited only."}}}},"responses":{"Unauthorized":{"description":"Missing, malformed, unknown, revoked or expired key, or a key whose owner left the workspace. Carries `WWW-Authenticate: Bearer`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"WWW-Authenticate":{"schema":{"type":"string"}}}},"Forbidden":{"description":"An admin-only tool called with a key whose owner is not (or no longer) a workspace admin.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"The key does not belong to the workspace in the path, the workspace id is unknown, or the tool does not exist — one constant body for all three.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"InvalidArguments":{"description":"`invalid_json` (the body is not a JSON object) or `invalid_arguments` (the body does not match the tool's schema; see `issues`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PayloadTooLarge":{"description":"The body is over 2 MiB.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"UnsupportedMediaType":{"description":"A body without `Content-Type: application/json`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"ToolError":{"description":"The tool refused the call (`tool_error`, message verbatim — e.g. a foreign session id, or a Salesforce tool without a connection).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"The key's per-minute limit is exceeded. Carries `Retry-After` and `X-RateLimit-Remaining: 0`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"}},"X-RateLimit-Limit":{"schema":{"type":"integer"}},"X-RateLimit-Remaining":{"schema":{"type":"integer"}}}},"Internal":{"description":"An unexpected failure — the message carries a reference id for support; internal details never leave the server.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}