{"openapi":"3.1.0","info":{"title":"CallDeskTech API","version":"1.0.0","description":"Build, publish and operate voice agents. Authenticate with `Authorization: Bearer cdk_live_…` (create keys in Settings → API Keys). A key is pinned to one workspace; call `GET /me` to get its tenant id."},"servers":[{"url":"https://0.0.0.0:3000/api/v1"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"cdk_live_… API key"}}},"paths":{"/me":{"get":{"tags":["Account"],"summary":"Who am I?","description":"For an API key, returns the tenant it is pinned to — use that id in the paths below.","responses":{"200":{"description":"Returns { auth, tenantId, tenantName }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/agents":{"get":{"tags":["Agents"],"summary":"List agents","description":"Each agent includes its latest version’s engine/voice and any routed phone numbers.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"responses":{"200":{"description":"Returns { agents: Agent[] }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"post":{"tags":["Agents"],"summary":"Create an agent","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"string"},"mode":{"description":"'simple' | 'advanced'"}},"required":["name"]}}}},"responses":{"200":{"description":"Returns { agent }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/agents/{agentId}":{"get":{"tags":["Agents"],"summary":"Get an agent","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { agent }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"patch":{"tags":["Agents"],"summary":"Rename an agent","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"string"}}}}}},"responses":{"200":{"description":"Returns { agent }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"delete":{"tags":["Agents"],"summary":"Delete an agent","description":"Also deletes its versions, subflows and knowledge bases.","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { success }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/agents/{agentId}/versions":{"get":{"tags":["Agents"],"summary":"List versions","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { versions: AgentVersion[] }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"post":{"tags":["Agents"],"summary":"Publish a new version","description":"Versions are immutable. `nodes` is the conversation-flow graph; `subflow_ref` nodes are embedded as snapshots at publish time.","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"flowName":{"description":"string"},"startNodeId":{"description":"string"},"nodes":{"description":"FlowNode[]"},"globalSettings":{"description":"object"},"voiceEngine":{"description":"'poc' | 'retell'"},"voiceId":{"description":"string"},"ttsBackend":{"description":"'kokoro' | 'elevenlabs' | 'cartesia' | 'minimax'"}},"required":["flowName","startNodeId","nodes","voiceEngine"]}}}},"responses":{"200":{"description":"Returns { version, flow }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/agent-templates":{"get":{"tags":["Agents"],"summary":"List agent templates","description":"Built-in templates (receptionist, medical receptionist, payment collection, IVR navigation and more) that can be installed as an agent.","responses":{"200":{"description":"Returns { templates: { id, label, description, category, defaultVariables: {name: value}, variables: string[] (the {{placeholders}} you can set on install) }[] }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/agents/from-template":{"post":{"tags":["Agents"],"summary":"Create an agent from a template","description":"Creates the agent, its subflows and knowledge base, and publishes version 1. `voiceEngine` \"poc\" runs on CallDesk; \"retell\" also creates the equivalent Retell conversation-flow agent (some node types are approximated; see `warnings`). `transferTo` and `functionUrl` fill empty transfer numbers and function webhooks. `variables` sets the template's {{placeholders}} (see GET /agent-templates); business_name defaults to the tenant name.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"templateId":{"description":"string (from GET /agent-templates)"},"name":{"description":"string"},"voiceEngine":{"description":"'poc' | 'retell'"},"transferTo":{"description":"E.164 string"},"functionUrl":{"description":"https URL"},"calendarTools":{"description":"false to turn off live calendar lookups and bookings"},"variables":{"description":"object, e.g. {\"business_name\": \"Acme Dental\", \"agent_name\": \"Sam\"}"}},"required":["templateId"]}}}},"responses":{"200":{"description":"Returns { agentId, versionId, versionNumber, template, voiceEngine, retellAgentId?, warnings? }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/subflows":{"get":{"tags":["Subflows"],"summary":"List subflows","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"agentId","in":"query","required":false,"description":"Only library subflows plus this agent’s own","schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { subflows: Subflow[] }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"post":{"tags":["Subflows"],"summary":"Create a subflow","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"string"},"scope":{"description":"'agent' | 'library'"},"agentId":{"description":"string (agent scope)"},"nodes":{"description":"FlowNode[]"},"startNodeId":{"description":"string"}},"required":["name"]}}}},"responses":{"200":{"description":"Returns { subflow }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/subflows/{subflowId}":{"get":{"tags":["Subflows"],"summary":"Get a subflow","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"subflowId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { subflow }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"patch":{"tags":["Subflows"],"summary":"Update a subflow","description":"Already-published versions keep the snapshot they embedded.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"subflowId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"string"},"nodes":{"description":"FlowNode[]"},"startNodeId":{"description":"string"},"scope":{"description":"string"}}}}}},"responses":{"200":{"description":"Returns { subflow }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"delete":{"tags":["Subflows"],"summary":"Delete a subflow","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"subflowId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { ok }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/knowledge-bases":{"get":{"tags":["Knowledge bases"],"summary":"List knowledge bases","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"responses":{"200":{"description":"Returns { knowledgeBases }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"post":{"tags":["Knowledge bases"],"summary":"Create a knowledge base","description":"Set `agent_id` — a knowledge_base node only sees content from a KB attached to its agent.","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"string"},"source_type":{"description":"'website' | 'pdf' | 'manual'"},"source_url":{"description":"string"},"agent_id":{"description":"string"}},"required":["name","source_type"]}}}},"responses":{"200":{"description":"Returns { knowledgeBase }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/knowledge-bases/{knowledgeBaseId}":{"patch":{"tags":["Knowledge bases"],"summary":"Rename or re-attach to an agent","parameters":[{"name":"knowledgeBaseId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"string"},"agent_id":{"description":"string | null"}}}}}},"responses":{"200":{"description":"Returns { knowledgeBase }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"delete":{"tags":["Knowledge bases"],"summary":"Delete a knowledge base","parameters":[{"name":"knowledgeBaseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { success }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/knowledge-bases/{knowledgeBaseId}/items":{"get":{"tags":["Knowledge bases"],"summary":"List Q&A items","parameters":[{"name":"knowledgeBaseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { items }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"post":{"tags":["Knowledge bases"],"summary":"Add Q&A items","parameters":[{"name":"knowledgeBaseId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"items":{"description":"{ question: string, answer: string }[]"}},"required":["items"]}}}},"responses":{"200":{"description":"Returns { items }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/phone-numbers":{"get":{"tags":["Phone numbers"],"summary":"List phone numbers","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"responses":{"200":{"description":"Returns { phoneNumbers }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/phone-numbers/{phoneNumberId}/routing":{"post":{"tags":["Phone numbers"],"summary":"Route a number to an agent version","parameters":[{"name":"phoneNumberId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"direction":{"description":"'inbound' | 'outbound'"},"agentVersionId":{"description":"string | null"}},"required":["direction"]}}}},"responses":{"200":{"description":"Returns { phoneNumber }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/phone-numbers/{phoneNumberId}/call":{"post":{"tags":["Calls"],"summary":"Place an outbound call","description":"Calls `toNumber` from this number using its outbound agent. Rate-limited per workspace (429).","parameters":[{"name":"phoneNumberId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"toNumber":{"description":"E.164 string"}},"required":["toNumber"]}}}},"responses":{"200":{"description":"Returns { call: { sid, to } }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/calls":{"get":{"tags":["Calls"],"summary":"List calls","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"limit","in":"query","required":false,"description":"default 50","schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { callLogs: CallLog[] }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/calls/{callId}":{"get":{"tags":["Calls"],"summary":"Get a call","description":"Includes transcript, outcome, duration, transfer status, and `analysis` (post-call analysis fields, null unless configured on the agent).","parameters":[{"name":"callId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { callLog }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/calls/{callId}/recording":{"get":{"tags":["Calls"],"summary":"Stream a call recording","parameters":[{"name":"callId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns audio"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/batch-calls":{"get":{"tags":["Batch calls"],"summary":"List batch calls","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"responses":{"200":{"description":"Returns { batches }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"post":{"tags":["Batch calls"],"summary":"Create a batch","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"agentVersionId":{"description":"string"},"phoneNumbers":{"description":"string[] (E.164)"}},"required":["agentVersionId","phoneNumbers"]}}}},"responses":{"200":{"description":"Returns { batch }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/batch-calls/{batchId}/run":{"post":{"tags":["Batch calls"],"summary":"Start a batch","description":"Dials paced by the platform-wide and per-workspace rate limits.","parameters":[{"name":"batchId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { started, ... }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhooks","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"responses":{"200":{"description":"Returns { webhooks }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"post":{"tags":["Webhooks"],"summary":"Register a webhook","description":"Events: `call.started` (Retell-engine calls only), `call.completed` (includes `analysis` when configured), `call.transferred`, `call.analyzed` (post-call analysis results). Deliveries are signed with the returned `whsec_` secret (X-CallDesk-Event header names the event).","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"description":"https URL"},"events":{"description":"('call.started' | 'call.completed' | 'call.transferred' | 'call.analyzed')[]"}},"required":["url"]}}}},"responses":{"200":{"description":"Returns { webhook }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/webhooks/{webhookId}":{"patch":{"tags":["Webhooks"],"summary":"Update a webhook","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"description":"string"},"events":{"description":"string[]"},"enabled":{"description":"boolean"}}}}}},"responses":{"200":{"description":"Returns { webhook }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { success }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/webhooks/{webhookId}/test":{"post":{"tags":["Webhooks"],"summary":"Send a test delivery","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"webhookId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { ok }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/contacts":{"get":{"tags":["Contacts"],"summary":"List contacts","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"}],"responses":{"200":{"description":"Returns { contacts }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/analytics":{"get":{"tags":["Analytics"],"summary":"Call analytics by day","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"days","in":"query","required":false,"description":"7 | 30 | 90","schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { series, totals }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/tenants/{tenantId}/qa/overview":{"get":{"tags":["Quality"],"summary":"QA scores, resolution and transfer metrics","parameters":[{"name":"tenantId","in":"path","required":true,"schema":{"type":"string"},"description":"Workspace id — from GET /me"},{"name":"days","in":"query","required":false,"description":"7 | 30 | 90","schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { avgScore, resolutionRate, transferSuccessRate, ... }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/agents/{agentId}/test-cases":{"get":{"tags":["Quality"],"summary":"List simulation test cases","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { testCases }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}},"post":{"tags":["Quality"],"summary":"Create a test case","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"description":"string"},"persona":{"description":"string"},"successCriteria":{"description":"string"}}}}}},"responses":{"200":{"description":"Returns { testCase }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}},"/agents/{agentId}/test-cases/{testCaseId}/run":{"post":{"tags":["Quality"],"summary":"Run a simulation","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string"}},{"name":"testCaseId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Returns { passed, transcript, reasoning }"},"401":{"description":"Missing or invalid credentials"},"404":{"description":"Not found, or not in your workspace"},"429":{"description":"Rate limited"}}}}}}