mirror of
https://github.com/simstudioai/sim.git
synced 2026-08-30 17:05:18 +08:00
0a5b3801ea
* feat(secrets): let workspace secrets opt out of redaction * fix(secrets): certify no sandbox exemptions once the registry is incomplete * feat(secrets): carry visible secret values on the v2 list and document visibility * fix(secrets): read visible values by own property so prototype-named secrets cannot poison the list
5891 lines
212 KiB
JSON
5891 lines
212 KiB
JSON
{
|
||
"openapi": "3.1.0",
|
||
"info": {
|
||
"title": "Sim API v2 — Workspace Resources",
|
||
"description": "Version 2 of the Sim REST API for workspace metadata, members, MCP servers, skills, custom tools, credentials, and write-only secrets.",
|
||
"version": "2.0.0",
|
||
"contact": {
|
||
"name": "Sim Support",
|
||
"email": "help@sim.ai",
|
||
"url": "https://www.sim.ai"
|
||
},
|
||
"license": {
|
||
"name": "Apache 2.0",
|
||
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
|
||
}
|
||
},
|
||
"servers": [
|
||
{
|
||
"url": "https://www.sim.ai",
|
||
"description": "Production"
|
||
}
|
||
],
|
||
"tags": [
|
||
{
|
||
"name": "Workspaces",
|
||
"description": "Read workspace metadata and its effective member roster."
|
||
},
|
||
{
|
||
"name": "MCP Servers",
|
||
"description": "Register and manage Model Context Protocol servers."
|
||
},
|
||
{
|
||
"name": "Skills",
|
||
"description": "Create and manage reusable instruction documents for agents."
|
||
},
|
||
{
|
||
"name": "Custom Tools",
|
||
"description": "Create and manage code-backed tools that agents can call."
|
||
},
|
||
{
|
||
"name": "Credentials",
|
||
"description": "Discover providers, create service-account credentials, connect or reconnect OAuth accounts, disconnect credentials, and list connections without secret material."
|
||
},
|
||
{
|
||
"name": "Secrets",
|
||
"description": "Set and manage write-only workspace and personal secret values."
|
||
}
|
||
],
|
||
"security": [
|
||
{
|
||
"apiKey": []
|
||
}
|
||
],
|
||
"paths": {
|
||
"/api/v2/workspaces": {
|
||
"get": {
|
||
"operationId": "listWorkspaces",
|
||
"summary": "List Workspaces",
|
||
"description": "List active workspaces available to the API key with opaque cursor pagination. A personal API key sees every accessible workspace that permits personal API keys; a workspace API key sees only its bound workspace.",
|
||
"tags": ["Workspaces"],
|
||
"parameters": [
|
||
{
|
||
"name": "sortBy",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"schema": {
|
||
"default": "createdAt",
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"type": "string",
|
||
"enum": ["name", "createdAt", "updatedAt"]
|
||
}
|
||
},
|
||
{
|
||
"name": "sortOrder",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Sort direction.",
|
||
"schema": {
|
||
"default": "desc",
|
||
"description": "Sort direction.",
|
||
"type": "string",
|
||
"enum": ["asc", "desc"]
|
||
}
|
||
},
|
||
{
|
||
"name": "limit",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Maximum workspaces to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"schema": {
|
||
"default": 50,
|
||
"description": "Maximum workspaces to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"maximum": 100
|
||
}
|
||
},
|
||
{
|
||
"name": "cursor",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"schema": {
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Public metadata for workspaces available to the API key.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListWorkspacesResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/workspaces/{workspaceId}": {
|
||
"get": {
|
||
"operationId": "getWorkspace",
|
||
"summary": "Get Workspace",
|
||
"description": "Return public metadata for one accessible workspace. Governance identities, billing identities, and internal membership identifiers are intentionally omitted.",
|
||
"tags": ["Workspaces"],
|
||
"parameters": [
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Workspace to retrieve.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace to retrieve."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Public workspace metadata.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/GetWorkspaceResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/workspaces/{workspaceId}/members": {
|
||
"get": {
|
||
"operationId": "listWorkspaceMembers",
|
||
"summary": "List Workspace Members",
|
||
"description": "List the workspace's effective members ordered by email. Explicit workspace grants and inherited organization-administrator grants are merged; internal membership and billing identities are omitted.",
|
||
"tags": ["Workspaces"],
|
||
"parameters": [
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Workspace to retrieve.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace to retrieve."
|
||
}
|
||
},
|
||
{
|
||
"name": "limit",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Maximum members to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"schema": {
|
||
"default": 50,
|
||
"description": "Maximum members to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"maximum": 100
|
||
}
|
||
},
|
||
{
|
||
"name": "cursor",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"schema": {
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "An email-ordered page of effective workspace members.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListWorkspaceMembersResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/mcp-servers": {
|
||
"get": {
|
||
"operationId": "listMcpServers",
|
||
"summary": "List MCP Servers",
|
||
"description": "List MCP servers registered in a workspace. Request-header values and OAuth client secrets are never returned. The discovery fields stay at their registration defaults until `GET /api/v2/mcp-servers/{id}/tools` runs a discovery.",
|
||
"tags": ["MCP Servers"],
|
||
"parameters": [
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the MCP server.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the MCP server."
|
||
}
|
||
},
|
||
{
|
||
"name": "search",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Case-insensitive substring match against the server name.",
|
||
"schema": {
|
||
"description": "Case-insensitive substring match against the server name.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 200
|
||
}
|
||
},
|
||
{
|
||
"name": "sortBy",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"schema": {
|
||
"default": "createdAt",
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"type": "string",
|
||
"enum": ["name", "createdAt", "updatedAt"]
|
||
}
|
||
},
|
||
{
|
||
"name": "sortOrder",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Sort direction.",
|
||
"schema": {
|
||
"default": "desc",
|
||
"description": "Sort direction.",
|
||
"type": "string",
|
||
"enum": ["asc", "desc"]
|
||
}
|
||
},
|
||
{
|
||
"name": "limit",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Maximum MCP servers to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"schema": {
|
||
"default": 50,
|
||
"description": "Maximum MCP servers to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"maximum": 100
|
||
}
|
||
},
|
||
{
|
||
"name": "cursor",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"schema": {
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "MCP servers registered in the workspace.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListMcpServersResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"post": {
|
||
"operationId": "createMcpServer",
|
||
"summary": "Create MCP Server",
|
||
"description": "Register an MCP server in a workspace. The endpoint URL is the server identity, so a URL already registered here is a `409` — reconfigure that server with `PATCH /api/v2/mcp-servers/{id}` instead. Registration never connects to the endpoint: the server comes back `disconnected` and stays unavailable until `GET /api/v2/mcp-servers/{id}/tools` succeeds.",
|
||
"tags": ["MCP Servers"],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "Configuration for a new MCP server.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateMcpServerRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"201": {
|
||
"description": "The MCP server was registered.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateMcpServerResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"409": {
|
||
"$ref": "#/components/responses/Conflict"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/mcp-servers/{id}": {
|
||
"get": {
|
||
"operationId": "getMcpServer",
|
||
"summary": "Get MCP Server",
|
||
"description": "Fetch one MCP server by identifier. Request-header values and OAuth client secrets are never returned.",
|
||
"tags": ["MCP Servers"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique MCP server identifier.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique MCP server identifier."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the MCP server.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the MCP server."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The MCP server.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/GetMcpServerResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"patch": {
|
||
"operationId": "updateMcpServer",
|
||
"summary": "Update MCP Server",
|
||
"description": "Update the supplied MCP server fields. Omitted fields are retained, except where a field says otherwise. Any change that invalidates authentication revokes the stored OAuth grant, resets `connectionStatus` to `disconnected`, and clears `lastConnected` and `lastError`, so the server must be rediscovered.",
|
||
"tags": ["MCP Servers"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique MCP server identifier.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique MCP server identifier."
|
||
}
|
||
}
|
||
],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "MCP server fields to change; omitted fields retain their stored values.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/UpdateMcpServerRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"200": {
|
||
"description": "The updated MCP server.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/UpdateMcpServerResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"delete": {
|
||
"operationId": "deleteMcpServer",
|
||
"summary": "Delete MCP Server",
|
||
"description": "Remove an MCP server and revoke its OAuth tokens. Workflows retain blocks that referenced the server's tools, but those tools can no longer be called.",
|
||
"tags": ["MCP Servers"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique MCP server identifier.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique MCP server identifier."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the MCP server.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the MCP server."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The MCP server was deleted.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/DeleteMcpServerResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/mcp-servers/{id}/tools": {
|
||
"get": {
|
||
"operationId": "listMcpServerTools",
|
||
"summary": "List MCP Server Tools",
|
||
"description": "Connect to a registered MCP server and return the tools it exposes. This read has side effects: it opens a live connection to the third-party server and writes `connectionStatus`, `toolCount`, `lastError`, and `lastToolsRefresh`. A `HEAD` skips the effect but is authorized exactly as the `GET` is, so it answers `400`, `401`, `403`, or `404` wherever the `GET` would and an empty `200` otherwise. Skipping the effect means skipping the read that produces the payload, so that `200` carries none of the response headers documented below — it answers whether the `GET` would be allowed, not what the `GET` would return. Discovery is bounded at 1,000 tools and 5 MB of tool payload per server. The bounded set is returned in one page; `nextCursor` is always null. An unreachable, slow, or cooling-down server is a `503`; a stored OAuth grant that no longer works is a `409` with `error.details.code` `MCP_SERVER_REAUTHORIZATION_REQUIRED`, which only a human reauthorizing in Sim can clear. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["MCP Servers"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique MCP server identifier.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique MCP server identifier."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the MCP server.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the MCP server."
|
||
}
|
||
},
|
||
{
|
||
"name": "refresh",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Bypass the short-lived per-workspace tool cache and reconnect under your own credentials. A cached result reflects whichever workspace member last ran discovery, so this is the only way to pick up a tool added since then; it costs a live round trip.",
|
||
"schema": {
|
||
"description": "Bypass the short-lived per-workspace tool cache and reconnect under your own credentials. A cached result reflects whichever workspace member last ran discovery, so this is the only way to pick up a tool added since then; it costs a live round trip.",
|
||
"type": "boolean"
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Tools exposed by the MCP server.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListMcpServerToolsResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"409": {
|
||
"$ref": "#/components/responses/Conflict"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/skills": {
|
||
"get": {
|
||
"operationId": "listSkills",
|
||
"summary": "List Skills",
|
||
"description": "List workspace and built-in skills with opaque cursor pagination. Built-ins are marked read-only. The list omits skill bodies; fetch one skill to read its content.",
|
||
"tags": ["Skills"],
|
||
"parameters": [
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the skill.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the skill."
|
||
}
|
||
},
|
||
{
|
||
"name": "search",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Case-insensitive substring match against the skill name.",
|
||
"schema": {
|
||
"description": "Case-insensitive substring match against the skill name.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 200
|
||
}
|
||
},
|
||
{
|
||
"name": "sortBy",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"schema": {
|
||
"default": "createdAt",
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"type": "string",
|
||
"enum": ["name", "createdAt", "updatedAt"]
|
||
}
|
||
},
|
||
{
|
||
"name": "sortOrder",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Sort direction.",
|
||
"schema": {
|
||
"default": "desc",
|
||
"description": "Sort direction.",
|
||
"type": "string",
|
||
"enum": ["asc", "desc"]
|
||
}
|
||
},
|
||
{
|
||
"name": "limit",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Maximum skills to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"schema": {
|
||
"default": 50,
|
||
"description": "Maximum skills to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"maximum": 100
|
||
}
|
||
},
|
||
{
|
||
"name": "cursor",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"schema": {
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Skills available in the workspace.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListSkillsResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"post": {
|
||
"operationId": "createSkill",
|
||
"summary": "Create Skill",
|
||
"description": "Create one skill in a workspace. Its kebab-case name must be unique and cannot be reserved by a built-in skill. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Skills"],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "Definition of a new skill.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateSkillRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"201": {
|
||
"description": "The skill was created.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateSkillResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"409": {
|
||
"$ref": "#/components/responses/Conflict"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/skills/{id}": {
|
||
"get": {
|
||
"operationId": "getSkill",
|
||
"summary": "Get Skill",
|
||
"description": "Fetch one workspace or built-in skill, including its full content. Built-in skills are marked read-only.",
|
||
"tags": ["Skills"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the skill.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the skill."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The skill.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/GetSkillResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"patch": {
|
||
"operationId": "updateSkill",
|
||
"summary": "Update Skill",
|
||
"description": "Update the supplied fields on a workspace skill. Omitted fields retain their stored values. Built-in skills are read-only. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Skills"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`."
|
||
}
|
||
}
|
||
],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "Skill fields to change; at least one editable field is required.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/UpdateSkillRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"200": {
|
||
"description": "The updated skill.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/UpdateSkillResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"409": {
|
||
"$ref": "#/components/responses/Conflict"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"delete": {
|
||
"operationId": "deleteSkill",
|
||
"summary": "Delete Skill",
|
||
"description": "Delete a workspace skill. Built-in skills are read-only and cannot be deleted. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Skills"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the skill.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the skill."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The skill was deleted.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/DeleteSkillResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/skills/{id}/editors": {
|
||
"get": {
|
||
"operationId": "listSkillEditors",
|
||
"summary": "List Skill Editors",
|
||
"description": "List explicit skill editors and workspace administrators with opaque cursor pagination. Internal user and membership identifiers are never returned.",
|
||
"tags": ["Skills"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the skill.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the skill."
|
||
}
|
||
},
|
||
{
|
||
"name": "sortBy",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"schema": {
|
||
"default": "email",
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"type": "string",
|
||
"enum": ["email", "name"]
|
||
}
|
||
},
|
||
{
|
||
"name": "sortOrder",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Sort direction.",
|
||
"schema": {
|
||
"default": "asc",
|
||
"description": "Sort direction.",
|
||
"type": "string",
|
||
"enum": ["asc", "desc"]
|
||
}
|
||
},
|
||
{
|
||
"name": "limit",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Maximum skill editors to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"schema": {
|
||
"default": 50,
|
||
"description": "Maximum skill editors to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"maximum": 100
|
||
}
|
||
},
|
||
{
|
||
"name": "cursor",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"schema": {
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Users who can edit the skill.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListSkillEditorsResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"post": {
|
||
"operationId": "grantSkillEditor",
|
||
"summary": "Grant Skill Editor",
|
||
"description": "Grant editor access to a current workspace member by email. The caller must already be a skill editor or workspace administrator. Workspace administrators already have derived editor access and cannot receive an explicit grant. A retried existing grant returns 200; a newly created grant returns 201. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Skills"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`."
|
||
}
|
||
}
|
||
],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "Workspace scope and email of the member to grant.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/GrantSkillEditorRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"200": {
|
||
"description": "The workspace member was already a skill editor.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/GrantSkillEditorResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"201": {
|
||
"description": "The skill editor grant was created.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/GrantSkillEditorResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"delete": {
|
||
"operationId": "revokeSkillEditor",
|
||
"summary": "Revoke Skill Editor",
|
||
"description": "Revoke an explicit editor grant by email. The caller must already be a skill editor or workspace administrator. Workspace administrators have derived access that cannot be revoked. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Skills"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the skill.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the skill."
|
||
}
|
||
},
|
||
{
|
||
"name": "email",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Email address of a current workspace member.",
|
||
"schema": {
|
||
"type": "string",
|
||
"format": "email",
|
||
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
|
||
"description": "Email address of a current workspace member."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The explicit editor grant was revoked.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/RevokeSkillEditorResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/custom-tools": {
|
||
"get": {
|
||
"operationId": "listCustomTools",
|
||
"summary": "List Custom Tools",
|
||
"description": "List code-backed custom tools defined in a workspace, with opaque cursor pagination. Legacy personal tools are excluded.",
|
||
"tags": ["Custom Tools"],
|
||
"parameters": [
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the custom tool.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the custom tool."
|
||
}
|
||
},
|
||
{
|
||
"name": "search",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Case-insensitive substring match against the tool title.",
|
||
"schema": {
|
||
"description": "Case-insensitive substring match against the tool title.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 200
|
||
}
|
||
},
|
||
{
|
||
"name": "sortBy",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Field used to sort the result.",
|
||
"schema": {
|
||
"default": "createdAt",
|
||
"description": "Field used to sort the result.",
|
||
"type": "string",
|
||
"enum": ["title", "createdAt", "updatedAt"]
|
||
}
|
||
},
|
||
{
|
||
"name": "sortOrder",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Sort direction.",
|
||
"schema": {
|
||
"default": "desc",
|
||
"description": "Sort direction.",
|
||
"type": "string",
|
||
"enum": ["asc", "desc"]
|
||
}
|
||
},
|
||
{
|
||
"name": "limit",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Maximum custom tools to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"schema": {
|
||
"default": 50,
|
||
"description": "Maximum custom tools to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"maximum": 100
|
||
}
|
||
},
|
||
{
|
||
"name": "cursor",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"schema": {
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Custom tools defined in the workspace.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListCustomToolsResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"post": {
|
||
"operationId": "createCustomTool",
|
||
"summary": "Create Custom Tool",
|
||
"description": "Create a code-backed custom tool in a workspace. Its title must be unique because tools resolve by title at call time.",
|
||
"tags": ["Custom Tools"],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "Definition and implementation of a new custom tool.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateCustomToolRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"201": {
|
||
"description": "The custom tool was created.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateCustomToolResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"409": {
|
||
"$ref": "#/components/responses/Conflict"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/custom-tools/{id}": {
|
||
"get": {
|
||
"operationId": "getCustomTool",
|
||
"summary": "Get Custom Tool",
|
||
"description": "Fetch one custom tool by identifier, scoped to its workspace.",
|
||
"tags": ["Custom Tools"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique custom tool identifier.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique custom tool identifier."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the custom tool.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the custom tool."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The custom tool.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/GetCustomToolResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"patch": {
|
||
"operationId": "updateCustomTool",
|
||
"summary": "Update Custom Tool",
|
||
"description": "Update the supplied custom tool fields. Omitted fields retain their stored values, and titles must remain unique within the workspace.",
|
||
"tags": ["Custom Tools"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique custom tool identifier.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique custom tool identifier."
|
||
}
|
||
}
|
||
],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "Custom tool fields to change; at least one editable field is required.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/UpdateCustomToolRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"200": {
|
||
"description": "The updated custom tool.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/UpdateCustomToolResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"409": {
|
||
"$ref": "#/components/responses/Conflict"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"delete": {
|
||
"operationId": "deleteCustomTool",
|
||
"summary": "Delete Custom Tool",
|
||
"description": "Delete a custom tool. Agent blocks retain their configuration but can no longer call the deleted tool.",
|
||
"tags": ["Custom Tools"],
|
||
"parameters": [
|
||
{
|
||
"name": "id",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Unique custom tool identifier.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Unique custom tool identifier."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace that owns the custom tool.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the custom tool."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The custom tool was deleted.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/DeleteCustomToolResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/credentials": {
|
||
"get": {
|
||
"operationId": "listCredentials",
|
||
"summary": "List Credentials",
|
||
"description": "List OAuth and service-account connections visible to the caller. Secret material is never returned.",
|
||
"tags": ["Credentials"],
|
||
"parameters": [
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace whose credentials should be listed.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace whose credentials should be listed."
|
||
}
|
||
},
|
||
{
|
||
"name": "type",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Restrict results to this credential type.",
|
||
"schema": {
|
||
"description": "Restrict results to this credential type.",
|
||
"type": "string",
|
||
"enum": ["oauth", "service_account"]
|
||
}
|
||
},
|
||
{
|
||
"name": "providerId",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Restrict results to credentials for this integration provider.",
|
||
"schema": {
|
||
"description": "Restrict results to credentials for this integration provider.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
},
|
||
{
|
||
"name": "search",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Case-insensitive substring match against the credential display name.",
|
||
"schema": {
|
||
"description": "Case-insensitive substring match against the credential display name.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 200
|
||
}
|
||
},
|
||
{
|
||
"name": "sortBy",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Field used to sort the result.",
|
||
"schema": {
|
||
"default": "createdAt",
|
||
"description": "Field used to sort the result.",
|
||
"type": "string",
|
||
"enum": ["displayName", "createdAt", "updatedAt"]
|
||
}
|
||
},
|
||
{
|
||
"name": "sortOrder",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Sort direction.",
|
||
"schema": {
|
||
"default": "desc",
|
||
"description": "Sort direction.",
|
||
"type": "string",
|
||
"enum": ["asc", "desc"]
|
||
}
|
||
},
|
||
{
|
||
"name": "limit",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Maximum credentials to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"schema": {
|
||
"default": 50,
|
||
"description": "Maximum credentials to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"maximum": 100
|
||
}
|
||
},
|
||
{
|
||
"name": "cursor",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"schema": {
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Credentials visible to the caller.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListCredentialsResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"post": {
|
||
"operationId": "createServiceAccountCredential",
|
||
"summary": "Create Service-Account Credential",
|
||
"description": "Verify and store one service-account credential. Use provider discovery to select a service-account provider, then encode its required fields as the JSON object string in credentials. The credentials string is write-only and is never returned. A retried source match returns the existing credential with 200; a newly created credential returns 201. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Credentials"],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "Provider identifier, optional display metadata, and a write-only JSON object string containing the fields declared by provider discovery.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateServiceAccountCredentialRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"200": {
|
||
"description": "An existing credential matched the verified source.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateServiceAccountCredentialResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"201": {
|
||
"description": "The service-account credential was created.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateServiceAccountCredentialResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"409": {
|
||
"$ref": "#/components/responses/Conflict"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/credentials/providers": {
|
||
"get": {
|
||
"operationId": "listCredentialProviders",
|
||
"summary": "List Credential Providers",
|
||
"description": "List catalogued OAuth and service-account connection methods and whether each is available to the caller in this workspace and deployment. Optionally search provider names with a case-insensitive substring match. OAuth authorization options contain the exact provider IDs accepted by the browser connection endpoint; service-account methods list the exact create-body fields and mark secret fields write-only. The bounded set is returned in one page; `nextCursor` is always null.",
|
||
"tags": ["Credentials"],
|
||
"parameters": [
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace used to evaluate credential-provider availability and integration policy.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace used to evaluate credential-provider availability and integration policy."
|
||
}
|
||
},
|
||
{
|
||
"name": "search",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Case-insensitive substring match against the credential provider name.",
|
||
"schema": {
|
||
"description": "Case-insensitive substring match against the credential provider name.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 200
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Credential provider catalog with caller-specific availability.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListCredentialProvidersResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/credentials/connections": {
|
||
"post": {
|
||
"operationId": "createCredentialConnection",
|
||
"summary": "Create Credential Connection",
|
||
"description": "Create a short-lived browser URL for connecting an OAuth provider or reconnecting an existing OAuth credential. Open the URL in a browser, sign in as the personal API-key owner, complete provider authorization, then refresh the credentials list. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Credentials"],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "For a new connection, provide providerId and displayName. For a reconnect, provide only credentialId; the existing display name is preserved.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateCredentialConnectionBody"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"200": {
|
||
"description": "A short-lived browser authorization URL.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/CreateCredentialConnectionResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"409": {
|
||
"$ref": "#/components/responses/Conflict"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/credentials/{credentialId}": {
|
||
"delete": {
|
||
"operationId": "deleteCredential",
|
||
"summary": "Disconnect Credential",
|
||
"description": "Disconnect an OAuth or service-account credential and clear its stored workflow, deployment, paused-run, knowledge-connector, and webhook references. Credential admin access is required. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Credentials"],
|
||
"parameters": [
|
||
{
|
||
"name": "credentialId",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Credential to disconnect.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Credential to disconnect."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace expected to own the credential.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace expected to own the credential."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The credential was disconnected.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/DeleteCredentialResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/secrets": {
|
||
"get": {
|
||
"operationId": "listSecrets",
|
||
"summary": "List Secrets",
|
||
"description": "List workspace and caller-owned personal secret metadata with opaque cursor pagination. Rows for workspace secrets marked visible (unredacted) include the stored value; every other row is metadata-only and no other response ever carries a value. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Secrets"],
|
||
"parameters": [
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace whose secret metadata should be listed.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace whose secret metadata should be listed."
|
||
}
|
||
},
|
||
{
|
||
"name": "scope",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Restrict results to one ownership scope.",
|
||
"schema": {
|
||
"description": "Restrict results to one ownership scope.",
|
||
"type": "string",
|
||
"enum": ["workspace", "personal"]
|
||
}
|
||
},
|
||
{
|
||
"name": "search",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Case-insensitive substring match against the secret name.",
|
||
"schema": {
|
||
"description": "Case-insensitive substring match against the secret name.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 200
|
||
}
|
||
},
|
||
{
|
||
"name": "sortBy",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"schema": {
|
||
"default": "name",
|
||
"description": "Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order.",
|
||
"type": "string",
|
||
"enum": ["name", "createdAt", "updatedAt"]
|
||
}
|
||
},
|
||
{
|
||
"name": "sortOrder",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Sort direction.",
|
||
"schema": {
|
||
"default": "asc",
|
||
"description": "Sort direction.",
|
||
"type": "string",
|
||
"enum": ["asc", "desc"]
|
||
}
|
||
},
|
||
{
|
||
"name": "limit",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Maximum secrets to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"schema": {
|
||
"default": 50,
|
||
"description": "Maximum secrets to return per page. Must be a whole number from 1 to 100. Defaults to 50.",
|
||
"type": "integer",
|
||
"minimum": 1,
|
||
"maximum": 100
|
||
}
|
||
},
|
||
{
|
||
"name": "cursor",
|
||
"in": "query",
|
||
"required": false,
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"schema": {
|
||
"description": "Opaque cursor from the previous page. Send it back with the same sort and filters; only `limit` may change. Change anything else and pagination must restart without a cursor.",
|
||
"type": "string",
|
||
"minLength": 1
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "Secret metadata visible to the caller.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/ListSecretsResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"/api/v2/secrets/{name}": {
|
||
"put": {
|
||
"operationId": "setSecret",
|
||
"summary": "Set Secret",
|
||
"description": "Create or replace a workspace or caller-owned personal secret. The value is encrypted at rest, is write-only, and is never included in the response. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Secrets"],
|
||
"parameters": [
|
||
{
|
||
"name": "name",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Secret to create, replace, or delete.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"pattern": "^[A-Za-z0-9_]+$",
|
||
"description": "Secret to create, replace, or delete."
|
||
}
|
||
}
|
||
],
|
||
"requestBody": {
|
||
"required": true,
|
||
"description": "Ownership scope and write-only value for the secret.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/SetSecretRequest"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"200": {
|
||
"description": "The existing secret value was replaced.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/SetSecretResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"201": {
|
||
"description": "The secret was created.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/SetSecretResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"413": {
|
||
"$ref": "#/components/responses/PayloadTooLarge"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
},
|
||
"delete": {
|
||
"operationId": "deleteSecret",
|
||
"summary": "Delete Secret",
|
||
"description": "Delete a workspace or caller-owned personal secret without reading or returning its stored value. A workspace API key is rejected with `403`; use a personal API key.",
|
||
"tags": ["Secrets"],
|
||
"parameters": [
|
||
{
|
||
"name": "name",
|
||
"in": "path",
|
||
"required": true,
|
||
"description": "Secret to create, replace, or delete.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"pattern": "^[A-Za-z0-9_]+$",
|
||
"description": "Secret to create, replace, or delete."
|
||
}
|
||
},
|
||
{
|
||
"name": "workspaceId",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Workspace the request is authorized against. A workspace secret is deleted from it; a personal secret is deleted for the caller in all of their workspaces.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace the request is authorized against. A workspace secret is deleted from it; a personal secret is deleted for the caller in all of their workspaces."
|
||
}
|
||
},
|
||
{
|
||
"name": "scope",
|
||
"in": "query",
|
||
"required": true,
|
||
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace.",
|
||
"schema": {
|
||
"type": "string",
|
||
"enum": ["workspace", "personal"],
|
||
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
|
||
}
|
||
}
|
||
],
|
||
"responses": {
|
||
"200": {
|
||
"description": "The secret was deleted.",
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"$ref": "#/components/headers/X-RateLimit-Limit"
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"$ref": "#/components/headers/X-RateLimit-Remaining"
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"$ref": "#/components/headers/X-RateLimit-Reset"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/DeleteSecretResponse"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"400": {
|
||
"$ref": "#/components/responses/BadRequest"
|
||
},
|
||
"401": {
|
||
"$ref": "#/components/responses/Unauthorized"
|
||
},
|
||
"403": {
|
||
"$ref": "#/components/responses/Forbidden"
|
||
},
|
||
"404": {
|
||
"$ref": "#/components/responses/NotFound"
|
||
},
|
||
"429": {
|
||
"$ref": "#/components/responses/RateLimited"
|
||
},
|
||
"500": {
|
||
"$ref": "#/components/responses/InternalError"
|
||
},
|
||
"503": {
|
||
"$ref": "#/components/responses/ServiceUnavailable"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"components": {
|
||
"securitySchemes": {
|
||
"apiKey": {
|
||
"type": "apiKey",
|
||
"in": "header",
|
||
"name": "X-API-Key",
|
||
"description": "Your Sim API key, personal or workspace-scoped. Generate one under Settings, then API Keys. Operations that reject workspace keys say so in their own description."
|
||
}
|
||
},
|
||
"headers": {
|
||
"X-RateLimit-Limit": {
|
||
"description": "Maximum requests allowed in the current window.",
|
||
"schema": {
|
||
"type": "integer",
|
||
"minimum": 0,
|
||
"maximum": 9007199254740991,
|
||
"title": "Rate limit",
|
||
"description": "Maximum requests allowed in the current window."
|
||
}
|
||
},
|
||
"X-RateLimit-Remaining": {
|
||
"description": "Requests remaining in the current window.",
|
||
"schema": {
|
||
"type": "integer",
|
||
"minimum": 0,
|
||
"maximum": 9007199254740991,
|
||
"title": "Rate limit remaining",
|
||
"description": "Requests remaining in the current window."
|
||
}
|
||
},
|
||
"X-RateLimit-Reset": {
|
||
"description": "ISO 8601 timestamp when the current rate-limit window resets.",
|
||
"schema": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"title": "Rate limit reset",
|
||
"description": "ISO 8601 timestamp when the current rate-limit window resets."
|
||
}
|
||
},
|
||
"Retry-After": {
|
||
"description": "Seconds to wait before retrying, sent on `429` and `503`. Add jitter rather than retrying at exactly this offset.",
|
||
"schema": {
|
||
"type": "integer",
|
||
"minimum": 0,
|
||
"maximum": 9007199254740991,
|
||
"title": "Retry after",
|
||
"description": "Seconds to wait before retrying, sent on `429` and `503`. Add jitter rather than retrying at exactly this offset."
|
||
}
|
||
},
|
||
"X-Run-Id": {
|
||
"description": "Identifier assigned to the workflow run.",
|
||
"schema": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"title": "Run identifier",
|
||
"description": "Identifier assigned to the workflow run."
|
||
}
|
||
}
|
||
},
|
||
"responses": {
|
||
"BadRequest": {
|
||
"description": "The request is invalid. This includes a query parameter sent with no value (`?limit=`, `?search=`), which is rejected rather than read as zero, empty, or the parameter default — omit the parameter instead.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "BAD_REQUEST",
|
||
"message": "Invalid request"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"Unauthorized": {
|
||
"description": "The API key is missing or invalid.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "UNAUTHORIZED",
|
||
"message": "API key required"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"Forbidden": {
|
||
"description": "The caller lacks the rights this operation requires. When the cause is one a caller can act on, `error.details.code` names it. A resource in a workspace the caller cannot reach at all answers `404` instead, so absence and denial are indistinguishable.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "FORBIDDEN",
|
||
"message": "Insufficient workspace permissions",
|
||
"details": {
|
||
"code": "INSUFFICIENT_WORKSPACE_ROLE"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"NotFound": {
|
||
"description": "The requested resource was not found.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "NOT_FOUND",
|
||
"message": "Not found"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"Conflict": {
|
||
"description": "The request conflicts with current resource state.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "CONFLICT",
|
||
"message": "API key name already exists"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"PayloadTooLarge": {
|
||
"description": "The request, or a resource collection it must materialize, exceeds the allowed size: an oversized request body, a generated artifact past the download ceiling, or a workspace folder tree too large to load in full.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "PAYLOAD_TOO_LARGE",
|
||
"message": "Request body is too large"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"RateLimited": {
|
||
"description": "The caller exceeded the request rate limit.",
|
||
"headers": {
|
||
"Retry-After": {
|
||
"$ref": "#/components/headers/Retry-After"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "RATE_LIMITED",
|
||
"message": "API rate limit exceeded",
|
||
"details": {
|
||
"retryAfter": "2026-01-01T00:00:30.000Z"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"InternalError": {
|
||
"description": "An unexpected server error occurred.",
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "INTERNAL_ERROR",
|
||
"message": "Internal server error"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"ServiceUnavailable": {
|
||
"description": "A required service is temporarily unavailable. `Retry-After` carries the seconds to wait; treat it as a floor and add jitter. The header is omitted when `error.details.code` is `ASYNC_ENQUEUE_AMBIGUOUS`, because the run may already have started — reconcile against the returned run id instead of retrying.",
|
||
"headers": {
|
||
"Retry-After": {
|
||
"$ref": "#/components/headers/Retry-After"
|
||
}
|
||
},
|
||
"content": {
|
||
"application/json": {
|
||
"schema": {
|
||
"$ref": "#/components/schemas/V2Error"
|
||
},
|
||
"example": {
|
||
"error": {
|
||
"code": "SERVICE_UNAVAILABLE",
|
||
"message": "Service temporarily unavailable"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"schemas": {
|
||
"V2Error": {
|
||
"type": "object",
|
||
"properties": {
|
||
"error": {
|
||
"type": "object",
|
||
"properties": {
|
||
"code": {
|
||
"type": "string",
|
||
"description": "Stable machine-readable error code."
|
||
},
|
||
"message": {
|
||
"type": "string",
|
||
"description": "Human-readable explanation of the error."
|
||
},
|
||
"details": {
|
||
"description": "Structured error details. On a `403` whose cause a caller can act on, this carries a `code` from a closed set:\n- `INSUFFICIENT_WORKSPACE_ROLE` — The caller has access to the workspace but its role is below the one this operation requires.\n- `PERSONAL_API_KEYS_DISABLED` — The workspace's organization does not allow personal API keys. Use a workspace API key.\n- `WORKSPACE_KEY_OPERATION_NOT_PERMITTED` — This operation is not available to a workspace-scoped API key. Use a personal API key.\n- `PRINCIPAL_KIND_NOT_PERMITTED` — This operation does not accept the caller’s kind of API key.\n- `ORGANIZATION_MEMBERSHIP_REQUIRED` — The caller is not a member of the organization it named.\n- `ORGANIZATION_ADMIN_REQUIRED` — The caller is a member of the organization but not an admin or owner.\n- `ENTERPRISE_PLAN_REQUIRED` — The organization has no active enterprise subscription.\n- `ORGANIZATION_PLAN_REQUIRED` — The organization has no active organization subscription (Pro for Teams, Max for Teams, or Enterprise).\n- `AUDIT_LOGS_DISABLED` — Audit logging is not enabled for this deployment.\n- `SKILL_EDITOR_ACCESS_REQUIRED` — The caller can write in the workspace but is not an editor of this skill.\n- `SECRET_ADMIN_ACCESS_REQUIRED` — The caller can write in the workspace but is not an admin of this secret. Ask a workspace admin, or someone holding admin on the secret, to grant access or set the value.\n- `WORKSPACE_RESOURCE_LIMIT_REACHED` — The workspace already holds the maximum number of resources of this kind. Delete one, or contact Sim to raise the limit; the message names the ceiling.\n- `PUBLIC_SHARING_NOT_ALLOWED` — The workspace's organization does not permit sharing this resource publicly. An organization admin controls the policy.\n- `CREDENTIAL_ADMIN_ACCESS_REQUIRED` — The caller can reach the workspace but cannot administer this credential.\n- `MCP_SERVER_URL_NOT_ALLOWED` — The supplied MCP server URL is outside the allowed domains or resolves to an internal address."
|
||
}
|
||
},
|
||
"required": ["code", "message"],
|
||
"additionalProperties": false,
|
||
"description": "Canonical error details."
|
||
}
|
||
},
|
||
"required": ["error"],
|
||
"additionalProperties": false,
|
||
"title": "v2 error response",
|
||
"description": "Canonical error envelope returned by the public v2 API.",
|
||
"examples": [
|
||
{
|
||
"error": {
|
||
"code": "BAD_REQUEST",
|
||
"message": "The request is invalid."
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"V2Workspace": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Unique workspace identifier."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"description": "Workspace display name."
|
||
},
|
||
"color": {
|
||
"type": "string",
|
||
"description": "Workspace color as a hexadecimal color value."
|
||
},
|
||
"logoUrl": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Workspace logo URL, or null when none is configured."
|
||
},
|
||
"memberCount": {
|
||
"type": "integer",
|
||
"minimum": 0,
|
||
"maximum": 9007199254740991,
|
||
"description": "Number of effective members, including inherited organization administrators."
|
||
},
|
||
"createdAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the workspace was created."
|
||
},
|
||
"updatedAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the workspace was last updated."
|
||
}
|
||
},
|
||
"required": ["id", "name", "color", "logoUrl", "memberCount", "createdAt", "updatedAt"],
|
||
"additionalProperties": false,
|
||
"title": "Workspace",
|
||
"description": "Public metadata for an accessible workspace."
|
||
},
|
||
"ListWorkspacesResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2Workspace"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there is nothing further to fetch. Never construct one yourself."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List workspaces response",
|
||
"description": "Public metadata for workspaces available to the API key.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"id": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"name": "Engineering",
|
||
"color": "#33C482",
|
||
"logoUrl": null,
|
||
"memberCount": 14,
|
||
"createdAt": "2026-01-15T10:30:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"GetWorkspaceResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2Workspace"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Get workspace response",
|
||
"description": "Public metadata for one workspace.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"name": "Engineering",
|
||
"color": "#33C482",
|
||
"logoUrl": null,
|
||
"memberCount": 14,
|
||
"createdAt": "2026-01-15T10:30:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"V2WorkspaceMember": {
|
||
"type": "object",
|
||
"properties": {
|
||
"email": {
|
||
"type": "string",
|
||
"format": "email",
|
||
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
|
||
"description": "Member email address and public member identifier."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"description": "Member display name."
|
||
},
|
||
"image": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Member profile image URL, or null when absent."
|
||
},
|
||
"role": {
|
||
"type": "string",
|
||
"enum": ["admin", "write", "read"],
|
||
"description": "Effective role in the workspace."
|
||
},
|
||
"isExternal": {
|
||
"type": "boolean",
|
||
"description": "Whether the member belongs to a different organization than the workspace. True only for an explicitly granted member whose own organization differs; inherited organization-administrator access is always reported as false, so this does not detect every outside caller."
|
||
},
|
||
"joinedAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when access was granted."
|
||
}
|
||
},
|
||
"required": ["email", "name", "image", "role", "isExternal", "joinedAt"],
|
||
"additionalProperties": false,
|
||
"title": "Workspace member",
|
||
"description": "An effective workspace member and their public access role."
|
||
},
|
||
"ListWorkspaceMembersResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2WorkspaceMember"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there is nothing further to fetch. Never construct one yourself."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List workspace members response",
|
||
"description": "A cursor-paginated page of effective workspace members.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"email": "jane@example.com",
|
||
"name": "Jane Smith",
|
||
"image": null,
|
||
"role": "admin",
|
||
"isExternal": false,
|
||
"joinedAt": "2026-01-15T10:30:00.000Z"
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"V2McpServer": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "Unique server identifier derived from the workspace and endpoint URL."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"description": "Server display name."
|
||
},
|
||
"description": {
|
||
"description": "Optional server description.",
|
||
"type": "string"
|
||
},
|
||
"transport": {
|
||
"default": "streamable-http",
|
||
"description": "Transport used to communicate with the server.",
|
||
"type": "string",
|
||
"enum": ["streamable-http"]
|
||
},
|
||
"authType": {
|
||
"description": "Authentication method used by the server.",
|
||
"type": "string",
|
||
"enum": ["none", "headers", "oauth"]
|
||
},
|
||
"url": {
|
||
"description": "Server endpoint URL.",
|
||
"type": "string"
|
||
},
|
||
"timeout": {
|
||
"description": "Per-request timeout in milliseconds.",
|
||
"type": "number"
|
||
},
|
||
"retries": {
|
||
"description": "Number of retries attempted per request.",
|
||
"type": "number"
|
||
},
|
||
"enabled": {
|
||
"type": "boolean",
|
||
"description": "Whether the server tools are available to workflows."
|
||
},
|
||
"connectionStatus": {
|
||
"description": "Result of the most recent connection attempt. Registration and re-registration establish no connection — the auth-type probe they may send does not count as one — so a server begins, and returns to, `disconnected` until a tool discovery runs.",
|
||
"type": "string",
|
||
"enum": ["connected", "disconnected", "error"]
|
||
},
|
||
"lastError": {
|
||
"description": "Message from the most recent failed connection, or null when absent. A re-registration clears it, since the configuration it described no longer applies.",
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"toolCount": {
|
||
"description": "Number of tools discovered on the server.",
|
||
"type": "number"
|
||
},
|
||
"lastToolsRefresh": {
|
||
"description": "ISO 8601 timestamp of the most recent tool-list refresh.",
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
|
||
},
|
||
"lastConnected": {
|
||
"description": "ISO 8601 timestamp of the most recent successful connection. Absent until the server completes one; registering a server does not set it.",
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
|
||
},
|
||
"createdAt": {
|
||
"description": "ISO 8601 timestamp when the server was registered.",
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
|
||
},
|
||
"updatedAt": {
|
||
"description": "ISO 8601 timestamp when the server was last updated.",
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
|
||
},
|
||
"oauthClientId": {
|
||
"description": "Pre-registered OAuth client identifier, when configured.",
|
||
"type": "string"
|
||
},
|
||
"hasHeaders": {
|
||
"type": "boolean",
|
||
"description": "Whether any request headers are configured."
|
||
},
|
||
"headerNames": {
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string",
|
||
"description": "Configured header name."
|
||
},
|
||
"description": "Names of configured request headers. Header values are never returned."
|
||
},
|
||
"hasOauthClientSecret": {
|
||
"type": "boolean",
|
||
"description": "Whether an OAuth client secret is stored. The value is never returned."
|
||
}
|
||
},
|
||
"required": [
|
||
"id",
|
||
"name",
|
||
"transport",
|
||
"enabled",
|
||
"createdAt",
|
||
"updatedAt",
|
||
"hasHeaders",
|
||
"headerNames",
|
||
"hasOauthClientSecret"
|
||
],
|
||
"additionalProperties": false,
|
||
"title": "MCP server",
|
||
"description": "Public MCP server configuration without write-only credential values."
|
||
},
|
||
"ListMcpServersResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2McpServer"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there is nothing further to fetch. Never construct one yourself."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List MCP servers response",
|
||
"description": "MCP servers registered in the workspace.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"id": "mcp-3f7a9c21",
|
||
"name": "Docs server",
|
||
"description": "Internal documentation tools",
|
||
"transport": "streamable-http",
|
||
"authType": "headers",
|
||
"url": "https://mcp.example.com/sse",
|
||
"timeout": 30000,
|
||
"retries": 3,
|
||
"enabled": true,
|
||
"connectionStatus": "connected",
|
||
"lastError": null,
|
||
"toolCount": 7,
|
||
"lastToolsRefresh": "2026-06-20T14:02:11.000Z",
|
||
"lastConnected": "2026-06-20T14:02:11.000Z",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z",
|
||
"hasHeaders": true,
|
||
"headerNames": ["Authorization"],
|
||
"hasOauthClientSecret": false
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"CreateMcpServerResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2McpServer"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Create MCP server response",
|
||
"description": "The registered MCP server without write-only credentials.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "mcp-3f7a9c21",
|
||
"name": "Docs server",
|
||
"description": "Internal documentation tools",
|
||
"transport": "streamable-http",
|
||
"authType": "headers",
|
||
"url": "https://mcp.example.com/sse",
|
||
"timeout": 30000,
|
||
"retries": 3,
|
||
"enabled": true,
|
||
"connectionStatus": "disconnected",
|
||
"lastError": null,
|
||
"toolCount": 0,
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z",
|
||
"hasHeaders": true,
|
||
"headerNames": ["Authorization"],
|
||
"hasOauthClientSecret": false
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"CreateMcpServerRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace in which to register the server."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Server display name."
|
||
},
|
||
"description": {
|
||
"description": "Optional server description.",
|
||
"type": "string",
|
||
"maxLength": 2000
|
||
},
|
||
"transport": {
|
||
"description": "Transport used to communicate with the server. Applied server-side as `streamable-http` when omitted on create.",
|
||
"default": "streamable-http",
|
||
"type": "string",
|
||
"enum": ["streamable-http"]
|
||
},
|
||
"url": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 2048,
|
||
"description": "Absolute HTTP or HTTPS endpoint URL without `{{ENV_VAR}}` references. It determines server identity and is immutable: delete and recreate the server to change endpoints."
|
||
},
|
||
"authType": {
|
||
"description": "Authentication method. When omitted, and no `headers` are sent, registration probes the endpoint once to classify it, falling back to `headers` when the probe fails or the server does not advertise OAuth. A server publishing RFC 9728 metadata is therefore stored as `oauth`, and headers configured afterwards will not authenticate — send this field explicitly to pin the method.",
|
||
"type": "string",
|
||
"enum": ["none", "headers", "oauth"]
|
||
},
|
||
"headers": {
|
||
"description": "Write-only request headers sent to the server. Replaced wholesale rather than merged on update: sending this field drops every stored header it does not repeat.",
|
||
"writeOnly": true,
|
||
"type": "object",
|
||
"propertyNames": {
|
||
"type": "string",
|
||
"minLength": 1
|
||
},
|
||
"additionalProperties": {
|
||
"type": "string",
|
||
"description": "Header value sent to the MCP server."
|
||
}
|
||
},
|
||
"timeout": {
|
||
"description": "Per-request timeout in milliseconds. Applied server-side as 30000 when omitted on create.",
|
||
"default": 30000,
|
||
"type": "integer",
|
||
"minimum": 1000,
|
||
"maximum": 300000
|
||
},
|
||
"retries": {
|
||
"description": "Number of retries per request. Applied server-side as 3 when omitted on create.",
|
||
"default": 3,
|
||
"type": "integer",
|
||
"minimum": 0,
|
||
"maximum": 10
|
||
},
|
||
"enabled": {
|
||
"description": "Whether the server tools are available to workflows. Applied server-side as true when omitted on create.",
|
||
"default": true,
|
||
"type": "boolean"
|
||
},
|
||
"oauthClientId": {
|
||
"description": "Pre-registered OAuth client identifier. Changing it on update revokes the stored OAuth grant and forces reauthorization.",
|
||
"anyOf": [
|
||
{
|
||
"type": "string",
|
||
"maxLength": 512
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"oauthClientSecret": {
|
||
"description": "Write-only pre-registered OAuth client secret. Sending it on update as null or a new value revokes the stored OAuth grant and forces reauthorization, as does switching away from OAuth authentication.",
|
||
"writeOnly": true,
|
||
"anyOf": [
|
||
{
|
||
"type": "string",
|
||
"maxLength": 2048
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"required": ["workspaceId", "name", "url"],
|
||
"additionalProperties": false,
|
||
"title": "Create MCP server request",
|
||
"description": "Configuration for a new MCP server.",
|
||
"examples": [
|
||
{
|
||
"workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"name": "Docs server",
|
||
"url": "https://mcp.example.com/sse",
|
||
"authType": "headers",
|
||
"headers": {
|
||
"Authorization": "Bearer YOUR_TOKEN"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"GetMcpServerResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2McpServer"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Get MCP server response",
|
||
"description": "One MCP server without write-only credentials.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "mcp-3f7a9c21",
|
||
"name": "Docs server",
|
||
"description": "Internal documentation tools",
|
||
"transport": "streamable-http",
|
||
"authType": "headers",
|
||
"url": "https://mcp.example.com/sse",
|
||
"timeout": 30000,
|
||
"retries": 3,
|
||
"enabled": true,
|
||
"connectionStatus": "connected",
|
||
"lastError": null,
|
||
"toolCount": 7,
|
||
"lastToolsRefresh": "2026-06-20T14:02:11.000Z",
|
||
"lastConnected": "2026-06-20T14:02:11.000Z",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z",
|
||
"hasHeaders": true,
|
||
"headerNames": ["Authorization"],
|
||
"hasOauthClientSecret": false
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"UpdateMcpServerResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2McpServer"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Update MCP server response",
|
||
"description": "The updated MCP server.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "mcp-3f7a9c21",
|
||
"name": "Docs server",
|
||
"description": "Internal documentation tools",
|
||
"transport": "streamable-http",
|
||
"authType": "headers",
|
||
"url": "https://mcp.example.com/sse",
|
||
"timeout": 30000,
|
||
"retries": 3,
|
||
"enabled": false,
|
||
"connectionStatus": "connected",
|
||
"lastError": null,
|
||
"toolCount": 7,
|
||
"lastToolsRefresh": "2026-06-20T14:02:11.000Z",
|
||
"lastConnected": "2026-06-20T14:02:11.000Z",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z",
|
||
"hasHeaders": true,
|
||
"headerNames": ["Authorization"],
|
||
"hasOauthClientSecret": false
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"UpdateMcpServerRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the MCP server."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Server display name."
|
||
},
|
||
"description": {
|
||
"description": "Optional server description.",
|
||
"type": "string",
|
||
"maxLength": 2000
|
||
},
|
||
"transport": {
|
||
"description": "Transport used to communicate with the server. Applied server-side as `streamable-http` when omitted on create.",
|
||
"default": "streamable-http",
|
||
"type": "string",
|
||
"enum": ["streamable-http"]
|
||
},
|
||
"url": {
|
||
"description": "Immutable server URL. When provided, it must equal the current URL; use delete and create to change endpoints.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 2048
|
||
},
|
||
"authType": {
|
||
"description": "Authentication method. When omitted, and no `headers` are sent, registration probes the endpoint once to classify it, falling back to `headers` when the probe fails or the server does not advertise OAuth. A server publishing RFC 9728 metadata is therefore stored as `oauth`, and headers configured afterwards will not authenticate — send this field explicitly to pin the method.",
|
||
"type": "string",
|
||
"enum": ["none", "headers", "oauth"]
|
||
},
|
||
"headers": {
|
||
"description": "Write-only request headers sent to the server. Replaced wholesale rather than merged on update: sending this field drops every stored header it does not repeat.",
|
||
"writeOnly": true,
|
||
"type": "object",
|
||
"propertyNames": {
|
||
"type": "string",
|
||
"minLength": 1
|
||
},
|
||
"additionalProperties": {
|
||
"type": "string",
|
||
"description": "Header value sent to the MCP server."
|
||
}
|
||
},
|
||
"timeout": {
|
||
"description": "Per-request timeout in milliseconds. Applied server-side as 30000 when omitted on create.",
|
||
"default": 30000,
|
||
"type": "integer",
|
||
"minimum": 1000,
|
||
"maximum": 300000
|
||
},
|
||
"retries": {
|
||
"description": "Number of retries per request. Applied server-side as 3 when omitted on create.",
|
||
"default": 3,
|
||
"type": "integer",
|
||
"minimum": 0,
|
||
"maximum": 10
|
||
},
|
||
"enabled": {
|
||
"description": "Whether the server tools are available to workflows. Applied server-side as true when omitted on create.",
|
||
"default": true,
|
||
"type": "boolean"
|
||
},
|
||
"oauthClientId": {
|
||
"description": "Pre-registered OAuth client identifier. Changing it on update revokes the stored OAuth grant and forces reauthorization.",
|
||
"anyOf": [
|
||
{
|
||
"type": "string",
|
||
"maxLength": 512
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"oauthClientSecret": {
|
||
"description": "Write-only pre-registered OAuth client secret. Sending it on update as null or a new value revokes the stored OAuth grant and forces reauthorization, as does switching away from OAuth authentication.",
|
||
"writeOnly": true,
|
||
"anyOf": [
|
||
{
|
||
"type": "string",
|
||
"maxLength": 2048
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"required": ["workspaceId"],
|
||
"additionalProperties": false,
|
||
"title": "Update MCP server request",
|
||
"description": "MCP server fields to change; omitted fields retain their stored values.",
|
||
"examples": [
|
||
{
|
||
"workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"enabled": false
|
||
}
|
||
]
|
||
},
|
||
"V2McpServerDeleteData": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "Identifier of the deleted MCP server."
|
||
},
|
||
"deleted": {
|
||
"type": "boolean",
|
||
"const": true,
|
||
"description": "Whether the server was deleted."
|
||
}
|
||
},
|
||
"required": ["id", "deleted"],
|
||
"additionalProperties": false,
|
||
"title": "Delete MCP server data",
|
||
"description": "MCP server deletion acknowledgement."
|
||
},
|
||
"DeleteMcpServerResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2McpServerDeleteData"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Delete MCP server response",
|
||
"description": "Acknowledgement that the MCP server was deleted.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "mcp-3f7a9c21",
|
||
"deleted": true
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"V2McpTool": {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"description": "Tool name, as the MCP server reports it."
|
||
},
|
||
"description": {
|
||
"description": "Tool description reported by the server.",
|
||
"type": "string"
|
||
},
|
||
"inputSchema": {
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"const": "object",
|
||
"description": "JSON Schema type of the argument object. MCP requires `object`."
|
||
},
|
||
"properties": {
|
||
"description": "Argument schemas keyed by argument name.",
|
||
"type": "object",
|
||
"propertyNames": {
|
||
"type": "string"
|
||
},
|
||
"additionalProperties": {
|
||
"description": "Server-defined JSON Schema for one tool argument."
|
||
}
|
||
},
|
||
"required": {
|
||
"description": "Names of the arguments the tool requires.",
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string",
|
||
"description": "Name of a required argument."
|
||
}
|
||
}
|
||
},
|
||
"required": ["type"],
|
||
"additionalProperties": {
|
||
"description": "Additional JSON Schema keyword reported by the server."
|
||
},
|
||
"description": "JSON Schema for the tool's arguments, as reported by the server."
|
||
},
|
||
"serverId": {
|
||
"type": "string",
|
||
"description": "Identifier of the MCP server exposing the tool."
|
||
},
|
||
"serverName": {
|
||
"type": "string",
|
||
"description": "Display name of the MCP server exposing the tool."
|
||
}
|
||
},
|
||
"required": ["name", "inputSchema", "serverId", "serverName"],
|
||
"additionalProperties": false,
|
||
"title": "MCP tool",
|
||
"description": "A tool exposed by a registered MCP server."
|
||
},
|
||
"ListMcpServerToolsResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2McpTool"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Always `null` — this list has no `cursor` or `limit` param and returns its whole bounded set in one page. Present so the list can gain pages later without a shape change."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List MCP server tools response",
|
||
"description": "Tools exposed by the MCP server.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"name": "search_docs",
|
||
"description": "Search the internal documentation",
|
||
"inputSchema": {
|
||
"type": "object",
|
||
"properties": {
|
||
"query": {
|
||
"type": "string",
|
||
"description": "Search terms"
|
||
}
|
||
},
|
||
"required": ["query"]
|
||
},
|
||
"serverId": "mcp-3f7a9c21",
|
||
"serverName": "Docs server"
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"V2SkillSummary": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"description": "Kebab-case name that agents use to reference the skill."
|
||
},
|
||
"description": {
|
||
"type": "string",
|
||
"description": "One-line summary of when the skill applies."
|
||
},
|
||
"readOnly": {
|
||
"type": "boolean",
|
||
"description": "Whether this is a built-in skill that cannot be modified or deleted."
|
||
},
|
||
"createdAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the skill was created. Built-in skills report the Unix epoch."
|
||
},
|
||
"updatedAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the skill was last updated. Built-in skills report the Unix epoch."
|
||
}
|
||
},
|
||
"required": ["id", "name", "description", "readOnly", "createdAt", "updatedAt"],
|
||
"additionalProperties": false,
|
||
"title": "Skill summary",
|
||
"description": "Public summary metadata for a workspace or built-in skill."
|
||
},
|
||
"ListSkillsResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2SkillSummary"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there is nothing further to fetch. Never construct one yourself."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List skills response",
|
||
"description": "Skill summaries available in the workspace.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"name": "refund-policy",
|
||
"description": "How support should handle refund requests",
|
||
"readOnly": false,
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"V2Skill": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "Unique skill identifier. A built-in skill is `builtin-` followed by its name, for example `builtin-research`."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"description": "Kebab-case name that agents use to reference the skill."
|
||
},
|
||
"description": {
|
||
"type": "string",
|
||
"description": "One-line summary of when the skill applies."
|
||
},
|
||
"readOnly": {
|
||
"type": "boolean",
|
||
"description": "Whether this is a built-in skill that cannot be modified or deleted."
|
||
},
|
||
"createdAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the skill was created. Built-in skills report the Unix epoch."
|
||
},
|
||
"updatedAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the skill was last updated. Built-in skills report the Unix epoch."
|
||
},
|
||
"content": {
|
||
"type": "string",
|
||
"description": "Skill body containing the instructions given to the agent."
|
||
}
|
||
},
|
||
"required": ["id", "name", "description", "readOnly", "createdAt", "updatedAt", "content"],
|
||
"additionalProperties": false,
|
||
"title": "Skill",
|
||
"description": "A workspace or built-in skill including its instruction body."
|
||
},
|
||
"CreateSkillResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2Skill"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Create skill response",
|
||
"description": "The created skill including its content.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"name": "refund-policy",
|
||
"description": "How support should handle refund requests",
|
||
"readOnly": false,
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z",
|
||
"content": "# Refund policy\n\nAlways check the order date first."
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"CreateSkillRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace in which to create the skill."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 64,
|
||
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
|
||
"description": "Kebab-case name, unique within the workspace and not reserved by a built-in skill."
|
||
},
|
||
"description": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 1024,
|
||
"description": "One-line summary of when the skill applies."
|
||
},
|
||
"content": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 50000,
|
||
"description": "Skill body containing the instructions given to the agent."
|
||
}
|
||
},
|
||
"required": ["workspaceId", "name", "description", "content"],
|
||
"additionalProperties": false,
|
||
"title": "Create skill request",
|
||
"description": "Definition of a new skill.",
|
||
"examples": [
|
||
{
|
||
"workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"name": "refund-policy",
|
||
"description": "How support should handle refund requests",
|
||
"content": "# Refund policy\n\nAlways check the order date first."
|
||
}
|
||
]
|
||
},
|
||
"GetSkillResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2Skill"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Get skill response",
|
||
"description": "One skill including its full content.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"name": "refund-policy",
|
||
"description": "How support should handle refund requests",
|
||
"readOnly": false,
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z",
|
||
"content": "# Refund policy\n\nAlways check the order date first."
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"UpdateSkillResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2Skill"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Update skill response",
|
||
"description": "The updated skill including its full content.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"name": "refund-policy",
|
||
"description": "Updated refund guidance",
|
||
"readOnly": false,
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z",
|
||
"content": "# Refund policy\n\nAlways check the order date first."
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"UpdateSkillRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the skill."
|
||
},
|
||
"name": {
|
||
"description": "New kebab-case skill name.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 64,
|
||
"pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
|
||
},
|
||
"description": {
|
||
"description": "New one-line summary of when the skill applies.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 1024
|
||
},
|
||
"content": {
|
||
"description": "Replacement skill body.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 50000
|
||
}
|
||
},
|
||
"required": ["workspaceId"],
|
||
"additionalProperties": false,
|
||
"title": "Update skill request",
|
||
"description": "Skill fields to change; at least one editable field is required.",
|
||
"examples": [
|
||
{
|
||
"workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"description": "Updated refund guidance"
|
||
}
|
||
]
|
||
},
|
||
"V2SkillDeleteData": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "Identifier of the deleted skill."
|
||
},
|
||
"deleted": {
|
||
"type": "boolean",
|
||
"const": true,
|
||
"description": "Whether the skill was deleted."
|
||
}
|
||
},
|
||
"required": ["id", "deleted"],
|
||
"additionalProperties": false,
|
||
"title": "Delete skill data",
|
||
"description": "Skill deletion acknowledgement."
|
||
},
|
||
"DeleteSkillResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2SkillDeleteData"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Delete skill response",
|
||
"description": "Acknowledgement that the skill was deleted.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"deleted": true
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"V2SkillEditor": {
|
||
"type": "object",
|
||
"properties": {
|
||
"email": {
|
||
"type": "string",
|
||
"format": "email",
|
||
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
|
||
"description": "Email address of the skill editor."
|
||
},
|
||
"name": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Display name of the skill editor."
|
||
},
|
||
"image": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Profile image URL of the skill editor."
|
||
},
|
||
"isWorkspaceAdmin": {
|
||
"type": "boolean",
|
||
"description": "Whether editor access is derived from workspace administration."
|
||
}
|
||
},
|
||
"required": ["email", "name", "image", "isWorkspaceAdmin"],
|
||
"additionalProperties": false,
|
||
"title": "Skill editor",
|
||
"description": "Public identity fields for a user who can edit a skill."
|
||
},
|
||
"ListSkillEditorsResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2SkillEditor"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there is nothing further to fetch. Never construct one yourself."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List skill editors response",
|
||
"description": "Public identity fields for users who can edit the skill.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"email": "jane@example.com",
|
||
"name": "Jane Smith",
|
||
"image": null,
|
||
"isWorkspaceAdmin": false
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"GrantSkillEditorResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2SkillEditor"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Grant skill editor response",
|
||
"description": "Public identity fields for the editor.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"email": "jane@example.com",
|
||
"name": "Jane Smith",
|
||
"image": null,
|
||
"isWorkspaceAdmin": false
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"GrantSkillEditorRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the skill."
|
||
},
|
||
"email": {
|
||
"type": "string",
|
||
"format": "email",
|
||
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
|
||
"description": "Email address of a current workspace member."
|
||
}
|
||
},
|
||
"required": ["workspaceId", "email"],
|
||
"additionalProperties": false,
|
||
"title": "Grant skill editor request",
|
||
"description": "Workspace scope and email of the member to grant.",
|
||
"examples": [
|
||
{
|
||
"workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"email": "jane@example.com"
|
||
}
|
||
]
|
||
},
|
||
"V2SkillEditorDeleteData": {
|
||
"type": "object",
|
||
"properties": {
|
||
"email": {
|
||
"type": "string",
|
||
"format": "email",
|
||
"pattern": "^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$",
|
||
"description": "Email address whose explicit editor grant was revoked."
|
||
},
|
||
"revoked": {
|
||
"type": "boolean",
|
||
"const": true,
|
||
"description": "Whether the explicit editor grant was revoked."
|
||
}
|
||
},
|
||
"required": ["email", "revoked"],
|
||
"additionalProperties": false,
|
||
"title": "Revoke skill editor data",
|
||
"description": "Skill editor revocation acknowledgement."
|
||
},
|
||
"RevokeSkillEditorResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2SkillEditorDeleteData"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Revoke skill editor response",
|
||
"description": "Acknowledgement that the explicit editor grant was revoked.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"email": "jane@example.com",
|
||
"revoked": true
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"V2CustomTool": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "Unique custom tool identifier."
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"description": "Display title, unique within the workspace."
|
||
},
|
||
"schema": {
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"const": "function",
|
||
"description": "Function declaration discriminator."
|
||
},
|
||
"function": {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Function name presented to the model."
|
||
},
|
||
"description": {
|
||
"description": "Optional explanation of what the function does.",
|
||
"type": "string"
|
||
},
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"description": "JSON Schema type for the arguments, usually `object`."
|
||
},
|
||
"properties": {
|
||
"type": "object",
|
||
"propertyNames": {
|
||
"type": "string"
|
||
},
|
||
"additionalProperties": {
|
||
"description": "Caller-defined JSON Schema for one tool argument."
|
||
},
|
||
"description": "Caller-defined argument schemas keyed by argument name."
|
||
},
|
||
"required": {
|
||
"description": "Names of required arguments.",
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
}
|
||
}
|
||
},
|
||
"required": ["type", "properties"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
},
|
||
"description": "JSON Schema describing the arguments accepted by the tool."
|
||
}
|
||
},
|
||
"required": ["name", "parameters"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
},
|
||
"description": "OpenAI-style function definition."
|
||
}
|
||
},
|
||
"required": ["type", "function"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
},
|
||
"description": "OpenAI-style function declaration describing the callable tool surface."
|
||
},
|
||
"code": {
|
||
"type": "string",
|
||
"description": "Tool implementation executed in the sandboxed function runtime."
|
||
},
|
||
"createdAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the tool was created."
|
||
},
|
||
"updatedAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the tool was last updated."
|
||
}
|
||
},
|
||
"required": ["id", "title", "schema", "code", "createdAt", "updatedAt"],
|
||
"additionalProperties": false,
|
||
"title": "Custom tool",
|
||
"description": "A workspace custom tool and its callable function declaration."
|
||
},
|
||
"ListCustomToolsResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2CustomTool"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there is nothing further to fetch. Never construct one yourself."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List custom tools response",
|
||
"description": "Custom tools defined in the workspace.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"title": "lookup_order",
|
||
"schema": {
|
||
"type": "function",
|
||
"function": {
|
||
"name": "lookup_order",
|
||
"description": "Look up an order by id",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"orderId": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"required": ["orderId"]
|
||
}
|
||
}
|
||
},
|
||
"code": "return { ok: true }",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"CreateCustomToolResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2CustomTool"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Create custom tool response",
|
||
"description": "The created custom tool.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"title": "lookup_order",
|
||
"schema": {
|
||
"type": "function",
|
||
"function": {
|
||
"name": "lookup_order",
|
||
"description": "Look up an order by id",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"orderId": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"required": ["orderId"]
|
||
}
|
||
}
|
||
},
|
||
"code": "return { ok: true }",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"CreateCustomToolRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace in which to create the custom tool."
|
||
},
|
||
"title": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 200,
|
||
"description": "Display title, unique within the workspace."
|
||
},
|
||
"schema": {
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"const": "function",
|
||
"description": "Function declaration discriminator."
|
||
},
|
||
"function": {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Function name presented to the model."
|
||
},
|
||
"description": {
|
||
"description": "Optional explanation of what the function does.",
|
||
"type": "string"
|
||
},
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"description": "JSON Schema type for the arguments, usually `object`."
|
||
},
|
||
"properties": {
|
||
"type": "object",
|
||
"propertyNames": {
|
||
"type": "string"
|
||
},
|
||
"additionalProperties": {
|
||
"description": "Caller-defined JSON Schema for one tool argument."
|
||
},
|
||
"description": "Caller-defined argument schemas keyed by argument name."
|
||
},
|
||
"required": {
|
||
"description": "Names of required arguments.",
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
}
|
||
}
|
||
},
|
||
"required": ["type", "properties"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
},
|
||
"description": "JSON Schema describing the arguments accepted by the tool."
|
||
}
|
||
},
|
||
"required": ["name", "parameters"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
},
|
||
"description": "OpenAI-style function definition."
|
||
}
|
||
},
|
||
"required": ["type", "function"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
},
|
||
"description": "OpenAI-style function declaration describing the callable tool surface."
|
||
},
|
||
"code": {
|
||
"type": "string",
|
||
"maxLength": 100000,
|
||
"description": "Tool implementation executed in the sandboxed function runtime."
|
||
}
|
||
},
|
||
"required": ["workspaceId", "title", "schema", "code"],
|
||
"additionalProperties": false,
|
||
"title": "Create custom tool request",
|
||
"description": "Definition and implementation of a new custom tool.",
|
||
"examples": [
|
||
{
|
||
"workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"title": "lookup_order",
|
||
"schema": {
|
||
"type": "function",
|
||
"function": {
|
||
"name": "lookup_order",
|
||
"description": "Look up an order by id",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"orderId": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"required": ["orderId"]
|
||
}
|
||
}
|
||
},
|
||
"code": "return { ok: true }"
|
||
}
|
||
]
|
||
},
|
||
"GetCustomToolResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2CustomTool"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Get custom tool response",
|
||
"description": "One custom tool.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"title": "lookup_order",
|
||
"schema": {
|
||
"type": "function",
|
||
"function": {
|
||
"name": "lookup_order",
|
||
"description": "Look up an order by id",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"orderId": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"required": ["orderId"]
|
||
}
|
||
}
|
||
},
|
||
"code": "return { ok: true }",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"UpdateCustomToolResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2CustomTool"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Update custom tool response",
|
||
"description": "The updated custom tool.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"title": "lookup_order",
|
||
"schema": {
|
||
"type": "function",
|
||
"function": {
|
||
"name": "lookup_order",
|
||
"description": "Look up an order by id",
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"orderId": {
|
||
"type": "string"
|
||
}
|
||
},
|
||
"required": ["orderId"]
|
||
}
|
||
}
|
||
},
|
||
"code": "return { ok: false }",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"UpdateCustomToolRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that owns the custom tool."
|
||
},
|
||
"title": {
|
||
"description": "New display title for the tool.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 200
|
||
},
|
||
"schema": {
|
||
"description": "Replacement function declaration.",
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"const": "function",
|
||
"description": "Function declaration discriminator."
|
||
},
|
||
"function": {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Function name presented to the model."
|
||
},
|
||
"description": {
|
||
"description": "Optional explanation of what the function does.",
|
||
"type": "string"
|
||
},
|
||
"parameters": {
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"description": "JSON Schema type for the arguments, usually `object`."
|
||
},
|
||
"properties": {
|
||
"type": "object",
|
||
"propertyNames": {
|
||
"type": "string"
|
||
},
|
||
"additionalProperties": {
|
||
"description": "Caller-defined JSON Schema for one tool argument."
|
||
},
|
||
"description": "Caller-defined argument schemas keyed by argument name."
|
||
},
|
||
"required": {
|
||
"description": "Names of required arguments.",
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string"
|
||
}
|
||
}
|
||
},
|
||
"required": ["type", "properties"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
},
|
||
"description": "JSON Schema describing the arguments accepted by the tool."
|
||
}
|
||
},
|
||
"required": ["name", "parameters"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
},
|
||
"description": "OpenAI-style function definition."
|
||
}
|
||
},
|
||
"required": ["type", "function"],
|
||
"additionalProperties": {
|
||
"description": "Caller-defined extension value preserved by the public API."
|
||
}
|
||
},
|
||
"code": {
|
||
"description": "Replacement tool implementation.",
|
||
"type": "string",
|
||
"maxLength": 100000
|
||
}
|
||
},
|
||
"required": ["workspaceId"],
|
||
"additionalProperties": false,
|
||
"title": "Update custom tool request",
|
||
"description": "Custom tool fields to change; at least one editable field is required.",
|
||
"examples": [
|
||
{
|
||
"workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"code": "return { ok: false }"
|
||
}
|
||
]
|
||
},
|
||
"V2CustomToolDeleteData": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "Identifier of the deleted custom tool."
|
||
},
|
||
"deleted": {
|
||
"type": "boolean",
|
||
"const": true,
|
||
"description": "Whether the custom tool was deleted."
|
||
}
|
||
},
|
||
"required": ["id", "deleted"],
|
||
"additionalProperties": false,
|
||
"title": "Delete custom tool data",
|
||
"description": "Custom tool deletion acknowledgement."
|
||
},
|
||
"DeleteCustomToolResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2CustomToolDeleteData"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Delete custom tool response",
|
||
"description": "Acknowledgement that the custom tool was deleted.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "V1StGXR8Z5jdHi6BmyT",
|
||
"deleted": true
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"V2Credential": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"description": "Unique credential identifier."
|
||
},
|
||
"type": {
|
||
"type": "string",
|
||
"enum": ["oauth", "service_account"],
|
||
"description": "Authenticated connection type."
|
||
},
|
||
"displayName": {
|
||
"type": "string",
|
||
"description": "Credential display name."
|
||
},
|
||
"description": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Optional credential description."
|
||
},
|
||
"providerId": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Integration provider authenticated by this credential."
|
||
},
|
||
"accountId": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Linked account identifier for OAuth credentials."
|
||
},
|
||
"hasServiceAccountKey": {
|
||
"type": "boolean",
|
||
"description": "Whether a service-account payload is stored. Its contents are never returned."
|
||
},
|
||
"role": {
|
||
"type": "string",
|
||
"enum": ["admin", "member"],
|
||
"description": "Caller role for the credential."
|
||
},
|
||
"createdAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the credential was created."
|
||
},
|
||
"updatedAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the credential was last updated."
|
||
}
|
||
},
|
||
"required": [
|
||
"id",
|
||
"type",
|
||
"displayName",
|
||
"description",
|
||
"providerId",
|
||
"accountId",
|
||
"hasServiceAccountKey",
|
||
"role",
|
||
"createdAt",
|
||
"updatedAt"
|
||
],
|
||
"additionalProperties": false,
|
||
"title": "Credential",
|
||
"description": "Public authenticated-connection metadata without secret material."
|
||
},
|
||
"ListCredentialsResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2Credential"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there is nothing further to fetch. Never construct one yourself."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List credentials response",
|
||
"description": "Credential metadata visible to the caller.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
|
||
"type": "service_account",
|
||
"displayName": "Zoom service account",
|
||
"description": null,
|
||
"providerId": "zoom-service-account",
|
||
"accountId": null,
|
||
"hasServiceAccountKey": true,
|
||
"role": "admin",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"V2CredentialProvider": {
|
||
"oneOf": [
|
||
{
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"const": "oauth",
|
||
"description": "Browser-based OAuth connection method."
|
||
},
|
||
"serviceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Stable credential-provider identifier."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Credential provider display name."
|
||
},
|
||
"description": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 1000,
|
||
"description": "Credential provider description."
|
||
},
|
||
"providerFamily": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Owning provider family identifier."
|
||
},
|
||
"available": {
|
||
"type": "boolean",
|
||
"description": "Whether this caller can connect the provider in the current deployment."
|
||
},
|
||
"supportsReconnect": {
|
||
"type": "boolean",
|
||
"description": "Whether existing credentials for this service can be reconnected."
|
||
},
|
||
"authorizationOptions": {
|
||
"minItems": 1,
|
||
"maxItems": 10,
|
||
"type": "array",
|
||
"items": {
|
||
"type": "object",
|
||
"properties": {
|
||
"providerId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Exact OAuth provider identifier accepted by the connection endpoint."
|
||
},
|
||
"label": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Human-readable authorization-server label."
|
||
}
|
||
},
|
||
"required": ["providerId", "label"],
|
||
"additionalProperties": false
|
||
},
|
||
"description": "Authorization servers available for this OAuth service."
|
||
}
|
||
},
|
||
"required": [
|
||
"type",
|
||
"serviceId",
|
||
"name",
|
||
"description",
|
||
"providerFamily",
|
||
"available",
|
||
"supportsReconnect",
|
||
"authorizationOptions"
|
||
],
|
||
"additionalProperties": false
|
||
},
|
||
{
|
||
"type": "object",
|
||
"properties": {
|
||
"type": {
|
||
"type": "string",
|
||
"const": "service_account",
|
||
"description": "Direct service-account credential method."
|
||
},
|
||
"serviceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Stable credential-provider identifier."
|
||
},
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Credential provider display name."
|
||
},
|
||
"description": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 1000,
|
||
"description": "Credential provider description."
|
||
},
|
||
"providerFamily": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Owning provider family identifier."
|
||
},
|
||
"available": {
|
||
"type": "boolean",
|
||
"description": "Whether this caller can connect the provider in the current deployment."
|
||
},
|
||
"providerId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Exact service-account provider ID accepted by credential creation."
|
||
},
|
||
"docsUrl": {
|
||
"type": "string",
|
||
"format": "uri",
|
||
"description": "Setup guide for the provider."
|
||
},
|
||
"helpText": {
|
||
"description": "Provider-specific setup guidance.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 2000
|
||
},
|
||
"requiresClientGeneratedCredentialId": {
|
||
"type": "boolean",
|
||
"description": "Whether the caller must generate and submit the credential ID before setup."
|
||
},
|
||
"fields": {
|
||
"minItems": 1,
|
||
"maxItems": 20,
|
||
"type": "array",
|
||
"items": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Exact create-body field name."
|
||
},
|
||
"label": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Human-readable field label."
|
||
},
|
||
"placeholder": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 1000,
|
||
"description": "Suggested input placeholder."
|
||
},
|
||
"required": {
|
||
"type": "boolean",
|
||
"description": "Whether the field is required for the selected flow."
|
||
},
|
||
"secret": {
|
||
"type": "boolean",
|
||
"description": "Whether the submitted field is write-only secret material."
|
||
},
|
||
"multiline": {
|
||
"type": "boolean",
|
||
"description": "Whether the field is intended for multi-line input."
|
||
},
|
||
"requiredForAuthMethods": {
|
||
"description": "Authentication methods for which this field is required.",
|
||
"minItems": 1,
|
||
"maxItems": 10,
|
||
"type": "array",
|
||
"items": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 64
|
||
}
|
||
},
|
||
"options": {
|
||
"description": "Fixed values accepted by a selector field.",
|
||
"minItems": 1,
|
||
"maxItems": 20,
|
||
"type": "array",
|
||
"items": {
|
||
"type": "object",
|
||
"properties": {
|
||
"value": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Submitted option value."
|
||
},
|
||
"label": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Human-readable option label."
|
||
}
|
||
},
|
||
"required": ["value", "label"],
|
||
"additionalProperties": false
|
||
}
|
||
},
|
||
"hint": {
|
||
"description": "Provider-specific setup guidance.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 2000
|
||
}
|
||
},
|
||
"required": ["id", "label", "placeholder", "required", "secret", "multiline"],
|
||
"additionalProperties": false
|
||
},
|
||
"description": "Create-body fields accepted by this provider. Secret fields are write-only."
|
||
}
|
||
},
|
||
"required": [
|
||
"type",
|
||
"serviceId",
|
||
"name",
|
||
"description",
|
||
"providerFamily",
|
||
"available",
|
||
"providerId",
|
||
"docsUrl",
|
||
"requiresClientGeneratedCredentialId",
|
||
"fields"
|
||
],
|
||
"additionalProperties": false
|
||
}
|
||
],
|
||
"title": "Credential Provider",
|
||
"description": "An OAuth or service-account connection method available to a workspace."
|
||
},
|
||
"ListCredentialProvidersResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2CredentialProvider"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Always `null` — this list has no `cursor` or `limit` param and returns its whole bounded set in one page. Present so the list can gain pages later without a shape change."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List credential providers response",
|
||
"description": "OAuth and service-account connection methods.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"type": "oauth",
|
||
"serviceId": "salesforce",
|
||
"name": "Salesforce",
|
||
"description": "Connect to Salesforce CRM data and operations.",
|
||
"providerFamily": "salesforce",
|
||
"available": true,
|
||
"supportsReconnect": true,
|
||
"authorizationOptions": [
|
||
{
|
||
"providerId": "salesforce",
|
||
"label": "Production"
|
||
},
|
||
{
|
||
"providerId": "salesforce-sandbox",
|
||
"label": "Sandbox"
|
||
}
|
||
]
|
||
},
|
||
{
|
||
"type": "service_account",
|
||
"serviceId": "zoom-service-account",
|
||
"providerId": "zoom-service-account",
|
||
"name": "Zoom server-to-server app",
|
||
"description": "Connect Zoom with a server-to-server app.",
|
||
"providerFamily": "zoom",
|
||
"available": true,
|
||
"docsUrl": "https://docs.sim.ai/integrations/zoom-service-account",
|
||
"requiresClientGeneratedCredentialId": false,
|
||
"fields": [
|
||
{
|
||
"id": "clientId",
|
||
"label": "Client ID",
|
||
"placeholder": "Paste the client ID",
|
||
"required": true,
|
||
"secret": false,
|
||
"multiline": false
|
||
},
|
||
{
|
||
"id": "clientSecret",
|
||
"label": "Client secret",
|
||
"placeholder": "Paste the client secret",
|
||
"required": true,
|
||
"secret": true,
|
||
"multiline": false
|
||
},
|
||
{
|
||
"id": "orgId",
|
||
"label": "Account ID",
|
||
"placeholder": "Paste the account ID",
|
||
"required": true,
|
||
"secret": false,
|
||
"multiline": false
|
||
}
|
||
]
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"CreateServiceAccountCredentialResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2Credential"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Create service-account credential response",
|
||
"description": "Verified credential metadata without secret material.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
|
||
"type": "service_account",
|
||
"displayName": "Zoom service account",
|
||
"description": null,
|
||
"providerId": "zoom-service-account",
|
||
"accountId": null,
|
||
"hasServiceAccountKey": true,
|
||
"role": "admin",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"CreateServiceAccountCredentialRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that will own the credential."
|
||
},
|
||
"type": {
|
||
"type": "string",
|
||
"const": "service_account",
|
||
"description": "Service-account credential discriminator."
|
||
},
|
||
"providerId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Exact service-account provider ID returned by provider discovery."
|
||
},
|
||
"displayName": {
|
||
"description": "Optional name; providers may derive one from the verified account identity.",
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255
|
||
},
|
||
"description": {
|
||
"description": "Optional credential description.",
|
||
"type": "string",
|
||
"maxLength": 500
|
||
},
|
||
"id": {
|
||
"description": "Required only when provider discovery requests a client-generated ID.",
|
||
"type": "string",
|
||
"format": "uuid",
|
||
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"
|
||
},
|
||
"credentials": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 131072,
|
||
"description": "Write-only JSON object string containing the fields declared by credential-provider discovery.",
|
||
"writeOnly": true
|
||
}
|
||
},
|
||
"required": ["workspaceId", "type", "providerId", "credentials"],
|
||
"additionalProperties": false,
|
||
"title": "Create service-account credential request",
|
||
"description": "Provider identifier, optional display metadata, and a write-only JSON object string containing the fields declared by provider discovery."
|
||
},
|
||
"V2CredentialConnectionAuthorization": {
|
||
"type": "object",
|
||
"properties": {
|
||
"authorizationUrl": {
|
||
"type": "string",
|
||
"format": "uri",
|
||
"description": "Short-lived Sim browser URL that starts the OAuth authorization flow."
|
||
},
|
||
"expiresAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the connection link expires."
|
||
}
|
||
},
|
||
"required": ["authorizationUrl", "expiresAt"],
|
||
"additionalProperties": false,
|
||
"title": "Credential Connection Authorization",
|
||
"description": "A short-lived browser entrypoint for an OAuth connection flow."
|
||
},
|
||
"CreateCredentialConnectionResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2CredentialConnectionAuthorization"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Create credential connection response",
|
||
"description": "Short-lived Sim browser entrypoint and its expiry.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"authorizationUrl": "https://www.sim.ai/api/auth/oauth2/authorize?draftId=draft-123",
|
||
"expiresAt": "2026-06-20T14:17:11.000Z"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"CreateCredentialConnectionBody": {
|
||
"anyOf": [
|
||
{
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace that will own the credential."
|
||
},
|
||
"providerId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Exact OAuth provider ID returned by credential-provider discovery."
|
||
},
|
||
"displayName": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Name shown for the new credential in Sim."
|
||
}
|
||
},
|
||
"required": ["workspaceId", "providerId", "displayName"],
|
||
"additionalProperties": false
|
||
},
|
||
{
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace expected to own the credential."
|
||
},
|
||
"credentialId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"description": "Existing OAuth credential to reconnect in place."
|
||
}
|
||
},
|
||
"required": ["workspaceId", "credentialId"],
|
||
"additionalProperties": false
|
||
}
|
||
],
|
||
"title": "Create credential connection body",
|
||
"description": "For a new connection, provide providerId and displayName. For a reconnect, provide only credentialId; the existing display name is preserved."
|
||
},
|
||
"V2CredentialDeleteData": {
|
||
"type": "object",
|
||
"properties": {
|
||
"id": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"description": "Disconnected credential identifier."
|
||
},
|
||
"deleted": {
|
||
"type": "boolean",
|
||
"const": true,
|
||
"description": "Whether the credential was disconnected."
|
||
}
|
||
},
|
||
"required": ["id", "deleted"],
|
||
"additionalProperties": false,
|
||
"title": "Delete credential data",
|
||
"description": "Credential disconnection acknowledgement."
|
||
},
|
||
"DeleteCredentialResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2CredentialDeleteData"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Disconnect credential response",
|
||
"description": "Acknowledgement that the credential was disconnected.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
|
||
"deleted": true
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"V2SecretWithValue": {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"pattern": "^[A-Za-z0-9_]+$",
|
||
"description": "Secret name containing only letters, numbers, and underscores."
|
||
},
|
||
"scope": {
|
||
"type": "string",
|
||
"enum": ["workspace", "personal"],
|
||
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
|
||
},
|
||
"description": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "What the secret is for, as set on the workspace secret. Always null for a personal secret, which has no shared audience."
|
||
},
|
||
"unredacted": {
|
||
"type": "boolean",
|
||
"description": "Whether the workspace secret opts out of redaction, so its value appears in plaintext in run logs and model-visible content. Always false for a personal secret."
|
||
},
|
||
"role": {
|
||
"type": "string",
|
||
"enum": ["admin", "member"],
|
||
"description": "Caller role for the secret."
|
||
},
|
||
"createdAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the secret was created."
|
||
},
|
||
"updatedAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the secret was last updated."
|
||
},
|
||
"value": {
|
||
"description": "The stored secret value. Present only when the workspace secret is marked visible (unredacted); omitted for every other secret.",
|
||
"type": "string"
|
||
}
|
||
},
|
||
"required": [
|
||
"name",
|
||
"scope",
|
||
"description",
|
||
"unredacted",
|
||
"role",
|
||
"createdAt",
|
||
"updatedAt"
|
||
],
|
||
"additionalProperties": false,
|
||
"title": "Secret metadata with visible value",
|
||
"description": "Secret metadata; the stored value is included only for a workspace secret marked visible (unredacted)."
|
||
},
|
||
"ListSecretsResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"type": "array",
|
||
"items": {
|
||
"$ref": "#/components/schemas/V2SecretWithValue"
|
||
},
|
||
"description": "Items in the current page."
|
||
},
|
||
"nextCursor": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "Opaque cursor for the next page. Send it back as `cursor`; `null` means there is nothing further to fetch. Never construct one yourself."
|
||
}
|
||
},
|
||
"required": ["data", "nextCursor"],
|
||
"additionalProperties": false,
|
||
"title": "List secrets response",
|
||
"description": "Secret metadata visible to the caller; visible (unredacted) workspace secrets carry their value.",
|
||
"examples": [
|
||
{
|
||
"data": [
|
||
{
|
||
"name": "STRIPE_API_KEY",
|
||
"scope": "workspace",
|
||
"description": "Production billing key — rotate quarterly.",
|
||
"unredacted": false,
|
||
"role": "admin",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
},
|
||
{
|
||
"name": "STAGING_BASE_URL",
|
||
"scope": "workspace",
|
||
"description": "Staging environment base URL.",
|
||
"unredacted": true,
|
||
"role": "member",
|
||
"createdAt": "2026-06-03T11:30:00.000Z",
|
||
"updatedAt": "2026-06-21T08:45:09.000Z",
|
||
"value": "https://staging.example.com"
|
||
}
|
||
],
|
||
"nextCursor": null
|
||
}
|
||
]
|
||
},
|
||
"V2Secret": {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"pattern": "^[A-Za-z0-9_]+$",
|
||
"description": "Secret name containing only letters, numbers, and underscores."
|
||
},
|
||
"scope": {
|
||
"type": "string",
|
||
"enum": ["workspace", "personal"],
|
||
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
|
||
},
|
||
"description": {
|
||
"anyOf": [
|
||
{
|
||
"type": "string"
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
],
|
||
"description": "What the secret is for, as set on the workspace secret. Always null for a personal secret, which has no shared audience."
|
||
},
|
||
"unredacted": {
|
||
"type": "boolean",
|
||
"description": "Whether the workspace secret opts out of redaction, so its value appears in plaintext in run logs and model-visible content. Always false for a personal secret."
|
||
},
|
||
"role": {
|
||
"type": "string",
|
||
"enum": ["admin", "member"],
|
||
"description": "Caller role for the secret."
|
||
},
|
||
"createdAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the secret was created."
|
||
},
|
||
"updatedAt": {
|
||
"type": "string",
|
||
"format": "date-time",
|
||
"pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$",
|
||
"description": "ISO 8601 timestamp when the secret was last updated."
|
||
}
|
||
},
|
||
"required": [
|
||
"name",
|
||
"scope",
|
||
"description",
|
||
"unredacted",
|
||
"role",
|
||
"createdAt",
|
||
"updatedAt"
|
||
],
|
||
"additionalProperties": false,
|
||
"title": "Secret metadata",
|
||
"description": "Public secret metadata without the stored secret value."
|
||
},
|
||
"SetSecretResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2Secret"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Set secret response",
|
||
"description": "Metadata for the created or replaced secret without its value.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"name": "STRIPE_API_KEY",
|
||
"scope": "workspace",
|
||
"description": "Production billing key — rotate quarterly.",
|
||
"unredacted": false,
|
||
"role": "admin",
|
||
"createdAt": "2026-06-01T09:14:00.000Z",
|
||
"updatedAt": "2026-06-20T14:02:11.000Z"
|
||
}
|
||
}
|
||
]
|
||
},
|
||
"SetSecretRequest": {
|
||
"type": "object",
|
||
"properties": {
|
||
"workspaceId": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 128,
|
||
"description": "Workspace the request is authorized against. A workspace secret is written to it; a personal secret is written to the caller and is available in all of their workspaces."
|
||
},
|
||
"scope": {
|
||
"type": "string",
|
||
"enum": ["workspace", "personal"],
|
||
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
|
||
},
|
||
"value": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 65536,
|
||
"description": "Write-only secret value. It is never returned.",
|
||
"writeOnly": true
|
||
},
|
||
"description": {
|
||
"description": "What the secret is for, shown to teammates. Workspace scope only — sending it for a personal secret is rejected. Omit it to leave an existing description untouched; send null or an empty string to clear one.",
|
||
"anyOf": [
|
||
{
|
||
"type": "string",
|
||
"maxLength": 500
|
||
},
|
||
{
|
||
"type": "null"
|
||
}
|
||
]
|
||
},
|
||
"unredacted": {
|
||
"description": "Opt the workspace secret out of redaction: its value then appears in plaintext in run logs, model-visible content, and files, including publicly shared log links. Workspace scope only — sending it for a personal secret is rejected. Omit it to leave the current setting untouched.",
|
||
"type": "boolean"
|
||
}
|
||
},
|
||
"required": ["workspaceId", "scope", "value"],
|
||
"additionalProperties": false,
|
||
"title": "Set secret request",
|
||
"description": "Ownership scope and write-only value for the secret.",
|
||
"examples": [
|
||
{
|
||
"workspaceId": "a91c4b2e-6d3f-4e8a-b5c7-0d9e2f1a8c64",
|
||
"scope": "workspace",
|
||
"value": "YOUR_SECRET_VALUE"
|
||
}
|
||
]
|
||
},
|
||
"V2SecretDeleteData": {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"minLength": 1,
|
||
"maxLength": 255,
|
||
"pattern": "^[A-Za-z0-9_]+$",
|
||
"description": "Secret name containing only letters, numbers, and underscores."
|
||
},
|
||
"scope": {
|
||
"type": "string",
|
||
"enum": ["workspace", "personal"],
|
||
"description": "Whether the secret belongs to the workspace or to the caller. A personal secret belongs to the caller across every workspace, not to one workspace."
|
||
},
|
||
"deleted": {
|
||
"type": "boolean",
|
||
"const": true,
|
||
"description": "Whether the secret was deleted."
|
||
}
|
||
},
|
||
"required": ["name", "scope", "deleted"],
|
||
"additionalProperties": false,
|
||
"title": "Delete secret data",
|
||
"description": "Secret deletion acknowledgement without the stored value."
|
||
},
|
||
"DeleteSecretResponse": {
|
||
"type": "object",
|
||
"properties": {
|
||
"data": {
|
||
"description": "Response data.",
|
||
"$ref": "#/components/schemas/V2SecretDeleteData"
|
||
}
|
||
},
|
||
"required": ["data"],
|
||
"additionalProperties": false,
|
||
"title": "Delete secret response",
|
||
"description": "Acknowledgement that the secret was deleted.",
|
||
"examples": [
|
||
{
|
||
"data": {
|
||
"name": "STRIPE_API_KEY",
|
||
"scope": "workspace",
|
||
"deleted": true
|
||
}
|
||
}
|
||
]
|
||
}
|
||
}
|
||
},
|
||
"x-generated-by": "scripts/generate-openapi.ts"
|
||
}
|