Publish a workflow as a hosted chat, or replace the chat it already publishes. Not to be confused with /workflows/{workflowId}/deployment (singular), which is the workflow's own API deployment — its live version and whether the draft has drifted. That path governs whether the workflow is executable at all; this one governs the hosted chat it is served on. The chat is a singleton of its workflow, so it has no id of its own in any path and no separate create verb: PUT is create-or-replace and is the only write.
Replace, not merge. The chat ends up as exactly what the body describes: an omitted optional field takes its platform default rather than whatever the previous chat carried, so sending the same body twice leaves the same result. password is therefore required whenever authType is "password" and rejected otherwise — it is write-only and never readable back, so carrying one over implicitly is the one place a replace would quietly stop meaning replace. allowedEmails follows the same rule: required and non-empty for "email" and "sso", rejected for the modes that admit no allow-list. customizations is the one documented exception: it merges per field, so an omitted imageUrl keeps the stored one rather than clearing it, and customization keys this surface does not declare do not survive the write. That behaviour is shared with the in-app editor and the Copilot deploy tool, which both send partial objects.
This also deploys the workflow, because a chat serves the live version: a draft that has drifted is republished as part of the call. Two conditions answer 409 — an identifier another live chat already holds, and a workflow deployment attempt still preparing, which the caller can retry once it becomes active. authType: "public" leaves the chat open to anyone holding the URL. A workspace API key is rejected with 403; use a personal API key.
/api/v2/workflows/{workflowId}/deployments/chatAuthorization
apiKey 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.
In: header
Path Parameters
Unique workflow identifier.
1 <= lengthRequest Body
application/json
The complete desired state of a workflow's chat.
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://www.sim.ai/api/v2/workflows/3b1f7c92-8d4e-4a6b-9c0d-5e2f8a714b36/deployments/chat" \ -H "X-API-Key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "identifier": "support", "title": "Support chat" }'{
"data": {
"id": "chat_01J8ZK3QW4M6X2R9T7B5C0V2",
"workflowId": "3b1f7c92-8d4e-4a6b-9c0d-5e2f8a714b36",
"workspaceId": "9f4c2a10-3b7e-4d58-8f6a-2c1d0e5b7a94",
"identifier": "support",
"url": "https://sim.ai/chat/support",
"title": "Support chat",
"description": "Ask about billing, onboarding, or outages.",
"isActive": true,
"authType": "public",
"hasPassword": false,
"allowedEmails": [],
"customizations": {
"primaryColor": "#6F3DFA",
"welcomeMessage": "Hi there! How can I help?"
},
"outputConfigs": [
{
"blockId": "block_01J8ZK3QW4M6X2R9T7B5C0V4",
"path": "content"
}
],
"includeThinking": false,
"includeToolCalls": false,
"createdAt": "2026-06-12T10:30:00.000Z",
"updatedAt": "2026-06-12T10:30:00.000Z"
}
}{
"error": {
"code": "BAD_REQUEST",
"message": "Invalid request"
}
}{
"error": {
"code": "UNAUTHORIZED",
"message": "API key required"
}
}{
"error": {
"code": "FORBIDDEN",
"message": "Insufficient workspace permissions",
"details": {
"code": "INSUFFICIENT_WORKSPACE_ROLE"
}
}
}{
"error": {
"code": "NOT_FOUND",
"message": "Not found"
}
}{
"error": {
"code": "CONFLICT",
"message": "Webhook path already in use"
}
}{
"error": {
"code": "PAYLOAD_TOO_LARGE",
"message": "Request body is too large"
}
}{
"error": {
"code": "UNSUPPORTED_MEDIA_TYPE",
"message": "Request body must be sent as application/json"
}
}{
"error": {
"code": "LOCKED",
"message": "Workflow is locked"
}
}{
"error": {
"code": "RATE_LIMITED",
"message": "API rate limit exceeded",
"details": {
"retryAfter": "2026-01-01T00:00:30.000Z"
}
}
}{
"error": {
"code": "INTERNAL_ERROR",
"message": "Internal server error"
}
}{
"error": {
"code": "SERVICE_UNAVAILABLE",
"message": "Service temporarily unavailable"
}
}