Resource guide
Connections are workspace-scoped provider state
Catalog browsing and connection lifecycle share one workspace capability. Duet derives the provider entity from the authenticated workspace. Clients never send an entity ID or arbitrary return destination, and every connected-account ID is verified against that workspace before deletion.
Keep credentials and connection state at the provider
Start a connection with an integration slug and a same-origin product path. Duet validates that path and returns a hosted authorization URL. Credentials go directly from the browser to the integration provider; Duet does not receive or store them. When the browser returns, treat its status parameter as a notice and refetch the catalog and connection list. The provider remains the sole source of truth; Duet does not mirror pending, active, failed, or disconnected integration rows.
Every accepted catalog or connection page contains at most 100 rows. Provider identities,
descriptions, and URLs must fit the public UTF-8 contract. Invalid optional logos are omitted; any
other invalid or oversized provider page fails as integration_provider_failed instead of leaking
a partial page. These bounds apply before provider data reaches the public API, including both
provider and public continuation tokens.
Agent access is separate durable Duet policy keyed by integration slug, so it survives disconnect
and reconnect. An omitted allowedAgentIds field means every agent, including future agents; an
explicit empty array means no agent; and a non-empty array names the exact durable agent IDs that
receive the toolkit. The reserved root ID selects default Duet. Send an empty object to restore
the all-agents default.
Canceled authorization is a successful lifecycle outcome with no active connection. It is safe to show the catalog again. Disconnect is idempotent, so cleanup code may repeat it when a prior response was lost.
Integrations
11 operations /v1 /ws /{workspaceSlug} /integrations /catalogSearch and page through the provider-neutral integration catalog
- Scope
ws:{workspaceSlug}:integrations- Request
- No JSON request body
- Query
Query parameters JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "cursor": { "type": "string", "minLength": 1 }, "limit": { "default": 50, "type": "integer", "minimum": 1, "maximum": 100 }, "q": { "type": "string", "maxLength": 200 } }, "additionalProperties": false }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "items": { "maxItems": 100, "type": "array", "items": { "type": "object", "properties": { "integration": { "type": "string" }, "name": { "type": "string", "minLength": 1 }, "description": { "type": "string" }, "logoUrl": { "type": "string" }, "connected": { "type": "boolean" } }, "required": [ "integration", "name", "connected" ], "additionalProperties": false } }, "nextCursor": { "anyOf": [ { "type": "string", "minLength": 1 }, { "type": "null" } ] } }, "required": [ "items", "nextCursor" ], "additionalProperties": false }- Errors
Error body JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "anyOf": [ { "anyOf": [ { "type": "object", "properties": { "error": { "type": "string", "const": "integration_provider_failed" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration provider rejected or returned invalid data (502)" }, { "type": "object", "properties": { "error": { "type": "string", "const": "integration_provider_not_configured" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration provider is not configured for this deployment (503)" } ] }, { "type": "object", "properties": { "error": { "type": "string", "const": "invalid_request" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration request or provider identity is outside the accepted contract (400)" } ] }, { "type": "object", "properties": { "error": { "type": "string", "const": "invalid_cursor" } }, "required": [ "error" ], "additionalProperties": false, "description": "Opaque collection cursor is malformed or bound to another walk (400)" } ] }- Delivery
- Standard response
- Retry
- Not declared idempotent
/v1 /ws /{workspaceSlug} /integrations /connectBegin an OAuth connection using server-derived tenant identity
- Scope
ws:{workspaceSlug}:integrations- Request
Request JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "integration": { "type": "string", "minLength": 1 }, "redirectTo": { "type": "string", "minLength": 1, "maxLength": 2048 } }, "required": [ "integration", "redirectTo" ] }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "integration": { "type": "string" }, "authorizeUrl": { "type": "string" } }, "required": [ "integration", "authorizeUrl" ], "additionalProperties": false }- Errors
Error body JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "anyOf": [ { "type": "object", "properties": { "error": { "type": "string", "const": "integration_provider_failed" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration provider rejected or returned invalid data (502)" }, { "type": "object", "properties": { "error": { "type": "string", "const": "integration_provider_not_configured" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration provider is not configured for this deployment (503)" } ] }, { "type": "object", "properties": { "error": { "type": "string", "const": "invalid_request" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration request or provider identity is outside the accepted contract (400)" }, { "type": "object", "properties": { "error": { "type": "string", "const": "integration_already_connected" } }, "required": [ "error" ], "additionalProperties": false, "description": "This integration already has an active connection (409)" }, { "type": "object", "properties": { "error": { "type": "string", "const": "redirect_not_allowed" } }, "required": [ "error" ], "additionalProperties": false, "description": "The requested browser return destination is not allowed (400)" } ] }- Delivery
- Standard response
- Retry
- Not declared idempotent
/v1 /ws /{workspaceSlug} /integrations /connectionsList workspace integration connections directly from the provider
- Scope
ws:{workspaceSlug}:integrations- Request
- No JSON request body
- Query
Query parameters JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "cursor": { "type": "string", "minLength": 1 }, "limit": { "default": 50, "type": "integer", "minimum": 1, "maximum": 100 } }, "additionalProperties": false }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "items": { "maxItems": 100, "type": "array", "items": { "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "integration": { "type": "string" }, "name": { "type": "string", "minLength": 1 }, "logoUrl": { "type": "string" }, "status": { "type": "string", "enum": [ "active", "pending", "error", "disconnected" ] }, "connectedAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "updatedAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "allowedAgentIds": { "maxItems": 51, "type": "array", "items": { "type": "string" } } }, "required": [ "id", "integration", "status", "connectedAt", "updatedAt" ], "additionalProperties": false } }, "nextCursor": { "anyOf": [ { "type": "string", "minLength": 1 }, { "type": "null" } ] } }, "required": [ "items", "nextCursor" ], "additionalProperties": false }- Errors
Error body JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "anyOf": [ { "anyOf": [ { "type": "object", "properties": { "error": { "type": "string", "const": "integration_provider_failed" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration provider rejected or returned invalid data (502)" }, { "type": "object", "properties": { "error": { "type": "string", "const": "integration_provider_not_configured" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration provider is not configured for this deployment (503)" } ] }, { "type": "object", "properties": { "error": { "type": "string", "const": "invalid_request" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration request or provider identity is outside the accepted contract (400)" } ] }, { "type": "object", "properties": { "error": { "type": "string", "const": "invalid_cursor" } }, "required": [ "error" ], "additionalProperties": false, "description": "Opaque collection cursor is malformed or bound to another walk (400)" } ] }- Delivery
- Standard response
- Retry
- Not declared idempotent
/v1 /ws /{workspaceSlug} /integrations /connections /{connectionId}Idempotently disconnect one tenant-owned integration account
- Scope
ws:{workspaceSlug}:integrations- Request
- No JSON request body
- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "id": { "type": "string", "minLength": 1 }, "disconnected": { "type": "boolean" } }, "required": [ "id", "disconnected" ], "additionalProperties": false }- Errors
Error body JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "anyOf": [ { "anyOf": [ { "type": "object", "properties": { "error": { "type": "string", "const": "integration_provider_failed" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration provider rejected or returned invalid data (502)" }, { "type": "object", "properties": { "error": { "type": "string", "const": "integration_provider_not_configured" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration provider is not configured for this deployment (503)" } ] }, { "type": "object", "properties": { "error": { "type": "string", "const": "invalid_request" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration request or provider identity is outside the accepted contract (400)" } ] }- Delivery
- Standard response
- Retry
- Declared idempotent
/v1 /ws /{workspaceSlug} /integrations /{toolkitSlug} /agent-policySet or clear the agents that receive one integration toolkit
- Scope
ws:{workspaceSlug}:integrations- Request
Request JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "allowedAgentIds": { "maxItems": 51, "type": "array", "items": { "type": "string", "minLength": 1 } } } }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "integration": { "type": "string" }, "allowedAgentIds": { "maxItems": 51, "type": "array", "items": { "type": "string" } } }, "required": [ "integration" ], "additionalProperties": false }- Errors
The integration request or provider identity is outside the accepted contract (400)
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "error": { "type": "string", "const": "invalid_request" } }, "required": [ "error" ], "additionalProperties": false, "description": "The integration request or provider identity is outside the accepted contract (400)" }- Delivery
- Standard response
- Retry
- Declared idempotent
/v1 /integrations /composio /execute /{toolSlug}Execute a Composio tool for the API key’s workspace; Duet injects the upstream Composio credentials server-side and returns the raw provider response.
- Scope
api_key- Request
Request JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "arguments": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} }, "workspace": { "type": "string" } } }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema" }- Delivery
- Standard response
- Retry
- Not declared idempotent
/v1 /ws /{workspaceSlug} /mcp-servers /probeDry-run a remote MCP server for its tool count, per-turn cost, and auth requirement
- Scope
ws:{workspaceSlug}:integrations- Request
Request JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "name": { "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,48}$" }, "url": { "type": "string", "minLength": 1, "maxLength": 2048 }, "auth": { "oneOf": [ { "type": "object", "properties": { "kind": { "type": "string", "const": "none" } }, "required": [ "kind" ] }, { "type": "object", "properties": { "kind": { "type": "string", "const": "oauth" } }, "required": [ "kind" ] }, { "type": "object", "properties": { "kind": { "type": "string", "const": "static" }, "token": { "type": "string", "minLength": 1, "maxLength": 8192 } }, "required": [ "kind", "token" ] } ] } }, "required": [ "name", "url" ] }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "auth": { "type": "string", "enum": [ "none", "oauth" ] }, "toolCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "estimatedPromptBytes": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "droppedToolNames": { "maxItems": 128, "type": "array", "items": { "type": "string", "minLength": 1 } }, "registrationSupported": { "type": "boolean" } }, "required": [ "auth", "toolCount", "estimatedPromptBytes" ], "additionalProperties": false }- Delivery
- Standard response
- Retry
- Not declared idempotent
/v1 /ws /{workspaceSlug} /mcp-serversAttach a remote MCP server to the workspace after a successful probe
- Scope
ws:{workspaceSlug}:integrations- Request
Request JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "name": { "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,48}$" }, "url": { "type": "string", "minLength": 1, "maxLength": 2048 }, "auth": { "oneOf": [ { "type": "object", "properties": { "kind": { "type": "string", "const": "none" } }, "required": [ "kind" ] }, { "type": "object", "properties": { "kind": { "type": "string", "const": "oauth" } }, "required": [ "kind" ] }, { "type": "object", "properties": { "kind": { "type": "string", "const": "static" }, "token": { "type": "string", "minLength": 1, "maxLength": 8192 } }, "required": [ "kind", "token" ] } ] }, "label": { "type": "string", "minLength": 1, "maxLength": 128 } }, "required": [ "name", "url" ] }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "name": { "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,48}$" }, "label": { "type": "string", "minLength": 1, "maxLength": 128 }, "url": { "type": "string", "minLength": 1, "maxLength": 2048 }, "authKind": { "type": "string", "enum": [ "none", "oauth", "static" ] }, "state": { "type": "string", "enum": [ "needs_auth", "ready", "reauth_required", "disconnecting" ] }, "toolCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "estimatedPromptBytes": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "droppedToolNames": { "maxItems": 128, "type": "array", "items": { "type": "string", "minLength": 1 } }, "lastSuccessAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "lastErrorAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "lastErrorCode": { "type": "string", "enum": [ "unauthorized", "reauth_required", "unreachable", "upstream_error", "result_too_large", "timeout" ] }, "allowedAgentIds": { "maxItems": 51, "type": "array", "items": { "type": "string", "minLength": 1 } }, "createdAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "updatedAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "name", "label", "url", "authKind", "state", "createdAt", "updatedAt" ], "additionalProperties": false }- Delivery
- Standard response
- Retry
- Not declared idempotent
/v1 /ws /{workspaceSlug} /mcp-serversList the workspace’s custom MCP servers with their health and per-agent scoping
- Scope
ws:{workspaceSlug}:integrations- Request
- No JSON request body
- Query
Query parameters JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "cursor": { "type": "string", "minLength": 1 }, "limit": { "default": 50, "type": "integer", "minimum": 1, "maximum": 100 } }, "additionalProperties": false }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "items": { "type": "array", "items": { "type": "object", "properties": { "name": { "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,48}$" }, "label": { "type": "string", "minLength": 1, "maxLength": 128 }, "url": { "type": "string", "minLength": 1, "maxLength": 2048 }, "authKind": { "type": "string", "enum": [ "none", "oauth", "static" ] }, "state": { "type": "string", "enum": [ "needs_auth", "ready", "reauth_required", "disconnecting" ] }, "toolCount": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "estimatedPromptBytes": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "droppedToolNames": { "maxItems": 128, "type": "array", "items": { "type": "string", "minLength": 1 } }, "lastSuccessAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "lastErrorAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "lastErrorCode": { "type": "string", "enum": [ "unauthorized", "reauth_required", "unreachable", "upstream_error", "result_too_large", "timeout" ] }, "allowedAgentIds": { "maxItems": 51, "type": "array", "items": { "type": "string", "minLength": 1 } }, "createdAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "updatedAt": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "name", "label", "url", "authKind", "state", "createdAt", "updatedAt" ], "additionalProperties": false } }, "nextCursor": { "anyOf": [ { "type": "string", "minLength": 1 }, { "type": "null" } ] } }, "required": [ "items", "nextCursor" ], "additionalProperties": false }- Errors
Opaque collection cursor is malformed or bound to another walk (400)
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "error": { "type": "string", "const": "invalid_cursor" } }, "required": [ "error" ], "additionalProperties": false, "description": "Opaque collection cursor is malformed or bound to another walk (400)" }- Delivery
- Standard response
- Retry
- Not declared idempotent
/v1 /ws /{workspaceSlug} /mcp-servers /{name}Idempotently detach one custom MCP server and its stored credential
- Scope
ws:{workspaceSlug}:integrations- Request
- No JSON request body
- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "name": { "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,48}$" }, "removed": { "type": "boolean" }, "revoked": { "type": "string", "enum": [ "revoked", "not_supported", "failed" ] }, "registration": { "type": "string", "enum": [ "deleted", "retained", "not_supported" ] } }, "required": [ "name", "removed", "revoked", "registration" ], "additionalProperties": false }- Delivery
- Standard response
- Retry
- Declared idempotent
/v1 /ws /{workspaceSlug} /mcp-servers /{name} /agent-policySet or clear the agents that receive one custom MCP server
- Scope
ws:{workspaceSlug}:integrations- Request
Request JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "allowedAgentIds": { "maxItems": 51, "type": "array", "items": { "type": "string", "minLength": 1 } } } }- Response
Response JSON schema
{ "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "name": { "type": "string", "pattern": "^[a-zA-Z0-9_-]{1,48}$" }, "allowedAgentIds": { "maxItems": 51, "type": "array", "items": { "type": "string", "minLength": 1 } } }, "required": [ "name" ], "additionalProperties": false }- Delivery
- Standard response
- Retry
- Declared idempotent