openapi: 3.0.0 info: title: Agent Management API version: 1.0.0 description: API for managing agents, their templates, and call logs paths: /user: get: summary: Get user details tags: - User security: - BearerAuth: [] responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: _id: type: string description: The ID of the user firstName: type: string description: The first name of the user lastName: type: string description: The last name of the user userEmail: type: string description: The email of the user authProvider: type: string description: The authentication provider of the user isEmailVerified: type: boolean description: Whether the user's email is verified organizationId: type: string description: The organization ID of the user "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /organization: get: summary: Get organization details tags: - Organization security: - BearerAuth: [] responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: _id: type: string description: The organization ID name: type: string description: The organization name members: type: array items: type: object properties: _id: type: string description: The member ID userEmail: type: string description: The member email subscription: type: object properties: planId: type: string description: The subscription plan ID "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/template: get: summary: Get agent templates tags: - Agent Templates security: - BearerAuth: [] parameters: - name: region in: query required: false description: Filter templates by region. Omit to return all templates. schema: type: string enum: - us - in responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: type: object properties: _id: type: string description: MongoDB ObjectId of the template id: type: string description: The ID of the agent template name: type: string description: The name of the agent template description: type: string description: The description of the agent template avatarUrl: type: string description: The avatar URL of the agent template referenceUrl: type: string description: The docs URL of the agent template industry: type: string description: The industry the template is designed for (e.g. "Finance", "Healthcare") useCase: type: string description: The use case the template addresses (e.g. "Lead Generation") callType: type: string description: The type of calls the template handles enum: - Inbound - Outbound - Both workflowType: type: string description: The workflow architecture of the template enum: - SINGLE_PROMPT - WORKFLOW_GRAPH region: type: string description: Human-readable region the template is available in enum: - India - US trending: type: boolean description: Whether the template is featured or trending defaultLanguage: type: string description: The default language configured in the template enum: - English - Hindi - Marathi - Gujarati singlePromptConfig: type: object description: Configuration for single-prompt agents properties: prompt: type: string description: The system prompt used by the agent tools: type: array description: Tools available to the agent items: type: object properties: name: type: string description: The name of the tool description: type: string description: What the tool does input_schema: type: object description: JSON Schema describing the tool's input parameters "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "400": $ref: "#/components/responses/BadRequestError" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/from-template: post: summary: Create agent from template tags: - Agent Templates security: - BearerAuth: [] description: We have created templates for some common use cases. You can use these templates to create an agent. For getting list of templates, you can use the /agent/template endpoint. It will give you the list of templates with their description and id. You can pass the id of the template in the request body to create an agent from the template. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateAgentFromTemplateRequest" responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string example: "60d0fe4f5311236168a109ca" description: The ID of the created agent "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent: get: summary: Get all agents tags: - Agents security: - BearerAuth: [] description: Agents are the main entities in the system. Agents are used to create conversations. You can create workflow for an agent and configure it for different use cases. You can also create custom workflows for an agent. This API will give you the list of agents created by organization you are a part of. parameters: - in: query name: page schema: type: integer default: 1 description: Page number - in: query name: offset schema: type: integer default: 10 description: Number of items to return per page - in: query name: search schema: type: string description: Search query - in: query name: type required: false schema: type: string enum: - single_prompt - workflow_graph description: Filter agents by workflow type - in: query name: sortField required: false schema: type: string default: createdAt enum: - createdAt - updatedAt - totalCalls - name - workflowType description: Field to sort results by - in: query name: sortOrder required: false schema: type: string default: desc enum: - asc - desc description: Sort direction - in: query name: archived required: false schema: type: boolean default: false description: When true, returns only archived agents. Omit or set to false to return active agents. responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: agents: type: array items: $ref: "#/components/schemas/AgentDTO" total: type: number description: Total number of agents "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "500": $ref: "#/components/responses/InternalServerErrorResponse" post: summary: Create a new agent tags: - Agents security: - BearerAuth: [] description: You can create a new agent by passing the name of the agent in the request body. You can use update-workflow endpoint next to assign custom workflow to the agent. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateAgentRequest" responses: "201": description: Agent created successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string example: "60d0fe4f5311236168a109ca" description: The ID of the created agent "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}: get: summary: Get agent by ID description: | Returns the agent document merged with the resolved config of the active version under `_resolvedConfig`. Non-versioned fields (name, telephonyProductId, allowInboundCall, etc.) sit at the top level; versioned fields (prompt, tools, language, synthesizer, post-call analytics, …) are resolved from the target version and exposed under `_resolvedConfig`. **Previewing a draft or specific version** Pass `?draftId=` to resolve config from a specific draft instead of the active version. Pass `?versionId=` to resolve config from a specific published version. When either param is used, the response includes `_configSource: "draft" | "version" | "active"` indicating which config was resolved. Notable resolved fields in `_resolvedConfig`: - `prompt` — active version's single-prompt text - `tools` — configured tools on the resolved version - `postCallAnalyticsConfig` — disposition metrics + analytics model flags - `modelName` — LLM model name on the resolved version - `defaultLanguage`, `supportedLanguages` — active language config - `firstMessage`, `globalPrompt` — active messaging config - `workflowGraph` — full node graph for `workflow_graph` agents To read prompt + tools alone, use `GET /agent/{id}/workflow` (deprecated for new integrations but still live). To inspect a specific non-active version, use `GET /agent/{id}/versions/{versionId}`. **400 — also used for "not found":** if the agent ID does not exist in the organization, the API returns 400 with `errors: ["No agent found"]` rather than 404. tags: - Agents security: - BearerAuth: [] parameters: - in: path name: id required: true schema: type: string - in: query name: draftId required: false schema: type: string description: Resolve `_resolvedConfig` from this draft instead of the active version. Sets `_configSource` to `"draft"` in the response. - in: query name: versionId required: false schema: type: string description: Resolve `_resolvedConfig` from this published version instead of the active version. Sets `_configSource` to `"version"` in the response. responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/AgentDTO" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "500": $ref: "#/components/responses/InternalServerErrorResponse" patch: summary: Update agent metadata description: | Update agent fields. Behavior depends on whether the agent has versioning enabled: **Versioned agents** (have an active published version): only metadata fields are accepted — `name`, `description`, `avatarUrl`, `telephonyProductId`, `allowInboundCall`, `visibleToEveryone`. Submitting any config-level field returns 400 with `"Agent has versioning enabled. Config changes must be made through drafts."`. Use `PATCH /agent/{id}/drafts/{draftId}/config` instead. **Non-versioned agents** (no active version): all configuration fields are accepted, the same full set as `POST /agent`. **400 is also returned when:** - The agent is locked (`"Agent is locked, please unlock it to update"`) - Cross-field constraint violated (e.g. `north_indic` language requires `transcriberType: pulse`) **403** is returned when selecting a gated model (`gpt-5.2`, `electron-kogta`, `electron-kogta-v2`) without org-level access. tags: - Agents security: - BearerAuth: [] parameters: - in: path name: id required: true schema: type: string requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateAgentRequest" responses: "200": description: Agent updated successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string example: "60d0fe4f5311236168a109ca" description: The ID of the updated agent "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/archive: delete: operationId: deleteAgent summary: Archive or unarchive an agent description: | Soft-archives the agent — it is excluded from listings and stops accepting calls, but all data is preserved and the operation is fully reversible. Pass `?on=false` to unarchive (restore) a previously archived agent. **409 is returned when:** - The agent is already in the requested state (`"Agent is already archived"` / `"Agent is already active"`) - The agent is linked to an active campaign (`"Agent is associated with the [status] campaign "[name]". Complete or remove the campaign before archiving."`) tags: - Agents security: - BearerAuth: [] parameters: - in: path name: id required: true schema: type: string - in: query name: on required: false schema: type: boolean default: true description: | `true` (default) — archive the agent. `false` — unarchive (restore) a previously archived agent. responses: "200": description: Agent archived or unarchived successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: message: type: string description: Human-readable outcome message enum: - Agent archived - Agent unarchived "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent not found "409": description: | Conflict — agent is already in the requested state, or is linked to an active campaign. "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/duplicate: post: summary: Duplicate agent to another organization description: | Duplicates a SINGLE_PROMPT agent's live active version into a target organization (can also be the same organization). Copies all versioned configuration but strips organization-specific resources: knowledge base tools are removed, default variable values are blanked, and a new avatar is generated. The duplicate starts with a published V1 as its active version. **400 is returned when:** - The source agent is archived (`"Cannot duplicate an archived agent"`) - The agent has no `activeVersionId` (`"This agent has no active version and cannot be duplicated"`) - The active version exists but is not published/active (`"This agent has no active published version and cannot be duplicated"`) - The agent is not `SINGLE_PROMPT` workflow type tags: - Agents security: - BearerAuth: [] parameters: - in: path name: id required: true schema: type: string description: The ID of the source agent to duplicate requestBody: required: true content: application/json: schema: type: object required: - targetOrganizationId properties: targetOrganizationId: type: string pattern: "^[a-fA-F0-9]{24}$" description: | MongoDB ObjectId of the target organization. Must be a 24-character hex string. The authenticated user must be a member of this organization. example: "60d0fe4f5311236168a109ca" responses: "201": description: Agent duplicated successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: _id: type: string example: "60d0fe4f5311236168a109cb" description: The ID of the newly created agent "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Forbidden — authenticated user is not a member of the target organization content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "404": description: | Not found. Possible messages: - `"Agent not found"` — source agent doesn't exist or doesn't belong to the caller's org - `"Target organization not found"` — the `targetOrganizationId` doesn't exist content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" # ── Deprecated: Workflow endpoints (still live) ──────────────────────── # Both still work in production and are actively used by customers, but # they bypass the versioning system. Prefer PATCH /agent/{id}/drafts/{draftId}/config # for writes and GET /agent/{id} for reads. /agent/{id}/workflow: get: summary: Get agent workflow deprecated: true description: | **Deprecated** — prefer `GET /agent/{id}` (config is resolved into `_resolvedConfig` including prompt, tools, and post-call analytics). Returns the active version's prompt and tools for single-prompt agents, or the workflow graph data for workflow_graph agents. Customers still rely on this to fetch their current prompt + tools — endpoint is kept live for now. **Caveat:** the `versionId` query param (if passed) is silently ignored. The response always reflects the currently-active version. To inspect a non-active version, use `GET /agent/{id}/versions/{versionId}`. tags: - Agents security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the agent schema: type: string responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object description: The active version's workflow. properties: prompt: type: string description: Active prompt (single-prompt agents only). tools: type: array items: $ref: "#/components/schemas/Tool" description: Active tool list (single-prompt agents only). type: $ref: "#/components/schemas/WorkflowType" description: Workflow type. Present for workflow_graph agents. data: oneOf: - $ref: "#/components/schemas/WorkflowGraphData" - $ref: "#/components/schemas/SinglePromptData" description: Graph data for workflow_graph agents. "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Agent not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /workflow/{id}: patch: summary: Update workflow configuration deprecated: true description: | **Deprecated** — use `PATCH /agent/{id}/drafts/{draftId}/config` instead. Directly mutates the legacy workflow document for an agent. This write path bypasses the versioning system entirely: the change is not captured as a new version, and future version activations may overwrite the legacy doc back to whatever the version snapshot contains. ⚠ **Writing here on a versioned agent can silently wipe tools, prompt, or other fields that were missing from the PATCH payload.** Only use this if you know the agent is not using versioning, or if you are intentionally hot-patching the legacy doc. tags: - Agents security: - BearerAuth: [] parameters: - in: path name: id required: true description: The workflow ID (found at `agent.workflowId` on the agent document). schema: type: string example: "60d0fe4f5311236168a109ca" requestBody: required: true content: application/json: schema: type: object required: [type] properties: type: $ref: "#/components/schemas/WorkflowType" workflowGraph: type: object description: Required when `type = workflow_graph`. Exactly one of `workflowGraph` or `singlePromptConfig` must be provided. properties: nodes: type: array items: type: object edges: type: array items: type: object singlePromptConfig: $ref: "#/components/schemas/SinglePromptConfig" responses: "200": description: Workflow updated successfully. "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Workflow not found. "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation: get: summary: Get all conversation logs description: Retrieve paginated conversation logs with support for various filters. Returns call logs for agents belonging to the authenticated user's organization. tags: - Logs security: - BearerAuth: [] parameters: - in: query name: page schema: type: integer default: 1 minimum: 1 description: Page number for pagination example: 1 - in: query name: limit schema: type: integer default: 5 minimum: 1 maximum: 500 description: Number of items per page. Server-side cap is 500 — values above 500 are silently clamped. example: 10 - in: query name: agentIds schema: type: string description: Comma-separated list of agent IDs to filter by example: "60d0fe4f5311236168a109ca,60d0fe4f5311236168a109cb" - in: query name: campaignIds schema: type: string description: Comma-separated list of campaign IDs to filter by example: "60d0fe4f5311236168a109ca,60d0fe4f5311236168a109cb" - in: query name: callTypes schema: type: string enum: - telephony_inbound - telephony_outbound - webcall description: Comma-separated list of call types to filter by example: "telephony_outbound,telephony_inbound" - in: query name: search schema: type: string description: Search query to filter by callId, fromNumber, or toNumber example: "+1234567890" - in: query name: statusFilter schema: type: string description: | Comma-separated list of call statuses to filter by. Available statuses: pending, in_progress, in_queue, processing, active, completed, failed, no_answer, cancelled example: "completed,failed" - in: query name: disconnectReasonFilter schema: type: string description: | Comma-separated list of disconnect reasons to filter by. Available reasons: user_hangup, agent_hangup, connection_error, timeout, system_error, transfer_complete example: "user_hangup,agent_hangup" - in: query name: callAttemptFilter schema: type: string description: | Comma-separated list of call attempt types to filter by. Available filters: initial (first attempt calls), retry (retry attempt calls), all (all calls) example: "initial" - in: query name: durationFilter schema: type: string description: | Comma-separated list of duration ranges to filter by. Available ranges: 0-30 (0-30 seconds), 30-60 (30-60 seconds), 1-5 (1-5 minutes), 5+ (more than 5 minutes) example: "0-30,30-60" - in: query name: sortBy required: false schema: type: string enum: - createdAt - updatedAt - callDuration - avgLatency description: Field to sort results by - in: query name: sortOrder required: false schema: type: string enum: - asc - desc description: Sort direction - in: query name: dateFrom required: false schema: type: string format: date-time description: ISO date — return calls created on or after this date example: "2025-01-01T00:00:00.000Z" - in: query name: dateTo required: false schema: type: string format: date-time description: ISO date — return calls created on or before this date example: "2025-01-31T23:59:59.999Z" - in: query name: versionFilter required: false schema: type: string description: Comma-separated version IDs to filter calls by the agent version that handled them responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: logs: type: array items: type: object properties: _id: type: string description: The database ID of the call log example: "60d0fe4f5311236168a109ca" callId: type: string description: The unique call identifier example: "CALL-1737000000000-abc123" status: type: string description: The status of the call enum: [pending, in_progress, in_queue, processing, active, completed, failed, no_answer, cancelled] example: "completed" duration: type: number description: The duration of the call in seconds example: 120 from: type: string description: The phone number the call was made from example: "+15551234567" to: type: string description: The phone number the call was made to example: "+15559876543" type: type: string description: The type of call enum: [telephony_inbound, telephony_outbound, webcall] example: "telephony_outbound" agentId: type: string description: The ID of the agent that handled the call example: "60d0fe4f5311236168a109ca" recordingUrl: type: string description: URL to the call recording (if available) example: "https://storage.example.com/recordings/call-123.mp3" recordingDualUrl: type: string description: URL to the dual-channel call recording (if available) example: "https://storage.example.com/recordings/call-123-dual.mp3" disconnectionReason: type: string description: The reason the call was disconnected example: "user_hangup" retryCount: type: integer description: Number of retry attempts for this call example: 0 createdAt: type: string format: date-time description: When the call was created example: "2025-01-15T10:30:00.000Z" dispositionMetrics: type: object description: Custom disposition metrics for the call additionalProperties: type: string example: interested: "yes" follow_up_needed: "no" agentDispositionConfig: type: array description: Configuration for disposition metrics items: type: object properties: identifier: type: string type: type: string callFailureReason: type: string description: Reason the call failed, if applicable callCost: type: number description: Discounted total cost of the call versionId: type: string description: ID of the agent version that handled this call versionNumber: type: number description: Human-readable version number of the agent version used isTest: type: boolean description: Whether this was a test call retryCallId: type: string description: ID of the retry call if this call was retried retryAttemptNumber: type: number description: Which retry attempt this was (0 = initial, 1 = first retry, etc.) postCallAnalytics: type: object description: | Post-call analytics results evaluated against the call transcript. Contains disposition metric values with confidence scores. properties: summary: type: string description: Auto-generated summary of the call dispositionMetrics: type: array description: Evaluated disposition metrics for this call items: type: object properties: identifier: type: string description: Metric identifier matching the agent config value: type: string description: The evaluated value for this metric confidence: type: number description: Confidence score for the evaluation (0–1) turnLatencyMetrics: type: object description: Per-turn latency statistics for the call properties: avgLatency: type: number description: Average turn latency in milliseconds medianLatency: type: number description: Median turn latency in milliseconds turns: type: number description: Total number of turns in the call latencies: type: array items: type: number description: Array of individual turn latencies in milliseconds pagination: type: object properties: total: type: integer description: Total number of matching call logs example: 150 page: type: integer description: Current page number example: 1 limit: type: integer description: Number of items per page (page size) example: 10 hasMore: type: boolean description: Whether there are more pages available example: true totalPages: type: integer description: Total number of pages example: 15 dispositionMetricsConfig: type: array description: Global disposition metrics configuration items: type: object properties: identifier: type: string type: type: string "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation/search: post: summary: Search conversation logs by call IDs description: | Fetch specific conversation logs by their callIds. This endpoint allows you to retrieve up to 100 specific calls at once. Only returns calls that belong to agents in your organization (security check enforced). Unlike the GET /conversation endpoint, this endpoint can also return retry calls (non-root calls). **Differences from GET /conversation response:** each log item has the same base structure but the following three fields are **not** included here: - `dispositionMetrics` — not enriched - `agentDispositionConfig` — not enriched - `versionNumber` — not enriched tags: - Logs security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - callIds properties: callIds: type: array items: type: string minItems: 1 maxItems: 100 description: | Array of callIds to fetch. Format: `CALL-{13-digit-timestamp}-{6-char-hex}` (e.g. `CALL-1737000000000-abc123`). Minimum 1, maximum 100 per request. example: ["CALL-1737000000000-abc123", "CALL-1737000000001-def456"] responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: logs: type: array items: type: object properties: _id: type: string description: The database ID of the call log example: "60d0fe4f5311236168a109ca" callId: type: string description: The unique call identifier example: "CALL-1737000000000-abc123" status: type: string description: The status of the call enum: [pending, in_progress, in_queue, processing, active, completed, failed, no_answer, cancelled] example: "completed" duration: type: number description: The duration of the call in seconds example: 120 from: type: string description: The phone number the call was made from example: "+15551234567" to: type: string description: The phone number the call was made to example: "+15559876543" type: type: string description: The type of call enum: [telephony_inbound, telephony_outbound, webcall] example: "telephony_outbound" agentId: type: string description: The ID of the agent that handled the call example: "60d0fe4f5311236168a109ca" recordingUrl: type: string description: URL to the call recording (if available) recordingDualUrl: type: string description: URL to the dual-channel call recording (if available) disconnectionReason: type: string description: The reason the call was disconnected retryCount: type: integer description: Number of retry attempts for this call createdAt: type: string format: date-time description: When the call was created callFailureReason: type: string description: Reason the call failed, if applicable callCost: type: number description: Discounted total cost of the call versionId: type: string description: ID of the agent version that handled this call isTest: type: boolean description: Whether this was a test call retryCallId: type: string description: ID of the retry call if this call was retried retryAttemptNumber: type: number description: Which retry attempt this was (0 = initial) postCallAnalytics: type: object description: Post-call analytics results evaluated against the call transcript properties: summary: type: string dispositionMetrics: type: array items: type: object properties: identifier: type: string value: type: string confidence: type: number turnLatencyMetrics: type: object description: Per-turn latency statistics for the call properties: avgLatency: type: number medianLatency: type: number turns: type: number latencies: type: array items: type: number total: type: integer description: Number of logs returned example: 2 requestedCount: type: integer description: Number of callIds requested example: 3 "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation/{id}: get: summary: Get conversation log by ID description: Retrieve detailed information about a specific conversation including transcript, events, and latency metrics. tags: - Logs security: - BearerAuth: [] parameters: - in: path name: id required: true description: The callId of the conversation (format `CALL-{13-digit-timestamp}-{6-char-hex}`). You can get the callId from the conversation logs endpoint. schema: type: string example: "CALL-1737000000000-abc123" responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: _id: type: string description: The database ID of the conversation log example: "60d0fe4f5311236168a109ca" callId: type: string description: The unique call identifier example: "CALL-1737000000000-abc123" agent: $ref: "#/components/schemas/AgentDTO" status: type: string description: The status of the conversation enum: [pending, in_progress, in_queue, processing, active, completed, failed, no_answer, cancelled] example: "completed" duration: type: number description: The duration of the conversation in seconds example: 300 recordingUrl: type: string description: The recording URL of the conversation recordingDualUrl: type: string description: URL to the dual-channel recording of the conversation from: type: string description: The phone number of the caller to: type: string description: The phone number of the callee type: type: string description: The type of the conversation enum: - telephony_inbound - telephony_outbound - webcall transcript: type: array description: The reconstructed transcript of the conversation items: type: object properties: role: type: string enum: [agent, user] description: Who spoke this turn content: type: string description: The spoken text for this turn timestamp: type: number description: Timestamp offset in milliseconds from call start variables: type: object description: Runtime variables resolved and used during the call additionalProperties: true events: type: array description: Raw event stream from the relay service items: type: object additionalProperties: true callCost: type: number description: Discounted total cost of the call callFailureReason: type: string description: Reason the call failed, if applicable retryCallId: type: string description: ID of the retry call if this call was retried postCallAnalytics: type: object description: Post-call analytics results evaluated against the call transcript properties: summary: type: string description: Auto-generated summary of the call dispositionMetrics: type: array description: Evaluated disposition metrics for this call items: type: object properties: identifier: type: string description: Metric identifier matching the agent config value: type: string description: The evaluated value for this metric confidence: type: number description: Confidence score for the evaluation (0–1) turnLatencyMetrics: type: object description: Per-turn latency statistics for the call. Replaces the deprecated average_*_latency fields. properties: turns: type: number description: Total number of turns in the call avgLatency: type: number description: Average turn latency in milliseconds medianLatency: type: number description: Median turn latency in milliseconds minLatency: type: number description: Minimum turn latency in milliseconds maxLatency: type: number description: Maximum turn latency in milliseconds latencies: type: array items: type: number description: Array of individual turn latencies in milliseconds transitions: type: array description: Per-turn timing breakdown items: type: object properties: turn: type: number user_end: type: number description: Timestamp (ms) when the user finished speaking bot_start: type: number description: Timestamp (ms) when the agent started responding latency: type: number description: Latency for this turn in milliseconds processedAt: type: string format: date-time description: When the latency metrics were computed voiceConfigUsed: type: object description: The voice configuration that was actually used for this call properties: model: type: string description: The TTS model used for the call voiceId: type: string description: The voice ID used for the call gender: type: string description: The gender of the voice used for the call slmModelUsed: type: string description: The SLM/LLM model that was actually used for this call "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Conversation log not found — the callId does not exist or does not belong to the caller's organization "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation/outbound: post: summary: Start an outbound call description: | Initiates an outbound telephony call with a specified agent and phone number. **400 is returned for:** - Invalid `agentId` format (`"Invalid agent id"`) - Invalid `phoneNumber` format (`"Invalid phone number"`) - Invalid `fromProductId` format (`"Invalid product id"`) - Agent not found or not in the caller's org (`"Agent not found"`) - Agent is archived (`"Agent is archived and cannot initiate calls"`) - `workflow_graph` agent has no workflow configured (`"Workflow not found"`) - Workflow has validation errors (`"Invalid workflow, please fix the errors..."`) **403** is returned for `workflow_graph` agents when the org lacks conversational agents access. **Test calls:** set the `x-test-call: true` header to mark the resulting call log as a test call (`isTest: true`). Test calls are subject to concurrent slot limits. tags: - Calls security: - BearerAuth: [] parameters: - in: header name: x-test-call required: false schema: type: string enum: ["true"] description: | Set to "true" to mark this as a test call. The call log will have isTest=true and counts against concurrent test-call slot limits. requestBody: required: true content: application/json: schema: type: object required: - agentId - phoneNumber properties: agentId: type: string description: MongoDB ObjectId of the agent initiating the conversation example: "60d0fe4f5311236168a109ca" phoneNumber: type: string description: The E.164 phone number to call example: "+1234567890" variables: type: object description: | Variables to inject into the agent's prompt at call time. Values must be string, number, or boolean — nested objects are not supported. additionalProperties: oneOf: - type: string - type: number - type: boolean example: { "name": "John", "age": 30, "vip": true } fromProductId: type: string description: ID of the telephony product (phone number) to call from. Get this from `GET /product/phone-numbers`. example: "60d0fe4f5311236168a109ca" versionId: type: string description: | ID of a specific published agent version to use for this call. Useful for test calls — attributes the call log to that version so you can track which version was tested. operatorId: type: string description: | Integration operator identifier. Pass `"webengage"` to trigger the WebEngage integration flow. operatorData: type: object description: Arbitrary data passed to the operator (e.g. `userId`, `journeyId` for WebEngage). additionalProperties: true responses: "200": description: Successfully started the outbound conversation content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: conversationId: type: string description: | The callId of the initiated call (format `CALL-{13-digit-timestamp}-{6-char-hex}`). Use this value as the `id` path parameter in `GET /conversation/{id}` and as an entry in `POST /conversation/search`. example: "CALL-1737000000000-abc123" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "500": $ref: "#/components/responses/InternalServerErrorResponse" /events: get: summary: Subscribe to live call events (SSE) description: | Real-time streaming of user speech (STT) and agent speech (TTS) events for an active call via Server-Sent Events. The connection is real-time — events stream directly from the call runtime as they are produced. The SSE connection auto-closes when the call ends (`sse_close` event). Only active calls can be subscribed to; completed calls return a 400 error. **Transcript event types:** - `user_interim_transcription` — Partial, in-progress transcription as the user speaks. Use for live preview only; will be superseded by `user_transcription`. - `user_transcription` — Final transcription for a completed user speech turn. - `tts_completed` — Fired when the agent finishes speaking a TTS segment. Includes the spoken text and optionally TTS latency. **Lifecycle events:** - `sse_init` — Sent immediately when the SSE connection is established. - `sse_close` — Sent when the call ends, right before the server closes the connection. Other event types (e.g. `call_start`, `call_end`, `turn_latency`, metrics) are also sent on this stream. tags: - Live Transcripts security: - BearerAuth: [] parameters: - name: callId in: query required: true description: The call ID to subscribe events for schema: type: string example: "CALL-1758124225863-80752e" responses: "200": description: SSE event stream established successfully content: text/event-stream: schema: type: object description: | Events are sent as `data: \n\n`. Each event has an `event_type` field. properties: event_type: type: string description: The type of event enum: - sse_init - user_interim_transcription - user_transcription - tts_completed - sse_close event_id: type: string description: Unique identifier for the event timestamp: type: string format: date-time description: ISO 8601 timestamp of the event call_id: type: string description: The call ID this event belongs to interim_transcription_text: type: string description: Partial transcription text (only for `user_interim_transcription`) user_transcription_text: type: string description: Final transcription text (only for `user_transcription`) tts_text: type: string description: Text spoken by the agent (only for `tts_completed`) tts_latency: type: integer description: TTS latency in milliseconds (only for `tts_completed`) examples: sse_init: summary: SSE connection initialized value: event_type: sse_init event_time: "2026-03-02T10:00:00.000Z" user_interim_transcription: summary: Partial user speech value: event_type: user_interim_transcription event_id: evt_abc123 timestamp: "2026-03-02T10:00:01.123Z" call_id: "CALL-1758124225863-80752e" interim_transcription_text: "I wanted to ask about my" user_transcription: summary: Final user speech value: event_type: user_transcription event_id: evt_abc456 timestamp: "2026-03-02T10:00:02.456Z" call_id: "CALL-1758124225863-80752e" user_transcription_text: "I wanted to ask about my recent order" tts_completed: summary: Agent finished speaking value: event_type: tts_completed event_id: evt_abc789 timestamp: "2026-03-02T10:00:03.789Z" call_id: "CALL-1758124225863-80752e" tts_latency: 245 tts_text: "Sure, I can help you with your recent order. Could you provide your order number?" sse_close: summary: Call ended value: event_type: sse_close event_time: "2026-03-02T10:05:00.000Z" "400": description: Missing or invalid callId, or call is already completed $ref: "#/components/responses/BadRequestError" "404": description: Not authorized (org mismatch) or call/agent not found content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string /campaign: get: summary: Retrieve all campaigns description: Get all campaigns for the authenticated organization. tags: - Campaigns security: - BearerAuth: [] parameters: - in: query name: page required: false schema: type: integer default: 1 description: Page number for pagination - in: query name: offset required: false schema: type: integer default: 5 description: Number of campaigns per page - in: query name: status required: false schema: type: string enum: [draft, scheduled, processing, running, paused, completed, failed] description: Filter campaigns by status - in: query name: search required: false schema: type: string description: Search campaigns by name - in: query name: sortField required: false schema: type: string default: createdAt enum: [createdAt, updatedAt] description: Field to sort by - in: query name: sortOrder required: false schema: type: string default: desc enum: [asc, desc] description: Sort direction responses: "200": description: A list of campaigns content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: campaigns: type: array items: type: object properties: _id: type: string description: The unique identifier for the campaign name: type: string description: The name of the campaign description: type: string description: The description of the campaign organization: type: string description: The ID of the organization agent: type: object description: The agent assigned to this campaign properties: _id: type: string name: type: string workflowType: type: string audience: type: object description: The audience assigned to this campaign properties: _id: type: string name: type: string createdBy: type: string description: The ID of the user who created the campaign participantsCount: type: integer description: The number of participants in the campaign status: type: string enum: [draft, scheduled, processing, running, paused, completed, failed] description: Current status of the campaign maxRetries: type: integer description: Maximum retry attempts per failed call retryDelay: type: integer description: Delay in minutes between retry attempts retryAttempts: type: integer description: Total retry attempts made so far scheduledAt: type: string format: date-time pausedAt: type: string format: date-time cancelledCallsCount: type: integer createdAt: type: string format: date-time description: The date and time when the campaign was created updatedAt: type: string format: date-time description: The date and time when the campaign was last updated pagination: type: object properties: total: type: integer page: type: integer offset: type: integer hasMore: type: boolean totalPages: type: integer totalCampaignCount: type: integer description: Total number of campaigns in the organization (unfiltered) "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" post: summary: Create a campaign description: Create a campaign tags: - Campaigns security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: The name of the campaign example: "My Campaign" description: type: string description: The description of the campaign example: "This is a campaign to test the API" audienceId: type: string description: The ID of the audience example: "60d0fe4f5311236168a109ca" agentId: type: string description: The ID of the agent example: "60d0fe4f5311236168a109ca" phoneNumberIds: type: array description: | Optional list of caller-ID phone number IDs to rotate across when placing outbound calls for this campaign. If omitted, the agent's default phone number is used. items: type: string example: ["60d0fe4f5311236168a109cb"] scheduledAt: type: string format: date-time description: | Optional ISO-8601 timestamp for when the campaign should start dialing. Must be in the future. If provided, the campaign is created in `scheduled` status; otherwise it starts in `draft` status and must be started manually. example: "2026-04-24T10:00:00.000Z" maxRetries: type: integer minimum: 0 maximum: 10 default: 3 description: | Maximum number of times a failed call is retried before the participant is marked as failed. `0` disables retries. example: 3 retryDelay: type: integer minimum: 1 maximum: 1440 default: 15 description: | Delay in minutes between retry attempts for a failed call. example: 15 required: - name - audienceId - agentId responses: "201": description: | Campaign created successfully. Note: the response is the raw Mongoose document — `agentId` and `audienceId` are plain ObjectId strings here, not nested objects as returned by GET endpoints. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: _id: type: string description: The unique identifier for the campaign name: type: string description: The name of the campaign description: type: string description: The description of the campaign organization: type: string description: The ID of the organization agentId: type: string description: Raw ObjectId of the agent (not a nested object) createdBy: type: string description: The ID of the user who created the campaign audienceId: type: string description: Raw ObjectId of the audience (not a nested object) participantsCount: type: integer description: The number of participants in the campaign scheduledAt: type: string format: date-time description: The scheduled start time, if provided at creation. maxRetries: type: integer description: Maximum retries per failed call (echoes request). retryDelay: type: integer description: Delay in minutes between retry attempts (echoes request). retryAttempts: type: integer description: Number of retries attempted so far across the campaign. status: type: string enum: [draft, scheduled, processing, running, paused, completed, failed] description: Current campaign status. createdAt: type: string format: date-time description: The date and time when the campaign was created updatedAt: type: string format: date-time description: The date and time when the campaign was last updated "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "500": $ref: "#/components/responses/InternalServerErrorResponse" /campaign/{id}: get: summary: Get a campaign description: Get a campaign with detailed metrics tags: - Campaigns security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the campaign schema: type: string responses: "200": description: Campaign details with metrics content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: campaign: type: object properties: _id: type: string description: The unique identifier for the campaign name: type: string description: The name of the campaign description: type: string description: The description of the campaign organization: type: string description: The ID of the organization agent: type: object description: The agent assigned to this campaign properties: _id: type: string name: type: string workflowType: type: string audience: type: object description: The audience assigned to this campaign properties: _id: type: string name: type: string createdBy: type: string description: The ID of the user who created the campaign participantsCount: type: integer description: The number of participants in the campaign status: type: string enum: [draft, scheduled, processing, running, paused, completed, failed] description: The current status of the campaign maxRetries: type: integer description: Maximum number of retry attempts example: 3 retryDelay: type: integer description: Delay between retries in minutes example: 15 retryAttempts: type: integer description: Total retry attempts made so far scheduledAt: type: string format: date-time description: Scheduled start time for the campaign pausedAt: type: string format: date-time description: When the campaign was paused cancelledCallsCount: type: integer description: Number of calls cancelled (e.g. when campaign was paused) error: type: string description: Error message if the campaign failed failedAt: type: string format: date-time description: When the campaign entered failed state createdAt: type: string format: date-time description: The date and time when the campaign was created updatedAt: type: string format: date-time description: The date and time when the campaign was last updated events: type: array description: Campaign events history items: type: object properties: _id: type: string triggerSource: type: string eventAction: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time metrics: type: object description: Campaign performance metrics properties: total_participants: type: integer description: Total number of contacts in the campaign audience example: 500 contacts_called: type: integer description: Number of unique contacts where a call was attempted (statuses ACTIVE, COMPLETED, FAILED, NO_ANSWER) example: 247 contacts_connected: type: integer description: Number of unique contacts who answered and had a conversation (status COMPLETED) example: 150 "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: summary: Delete a campaign description: Delete a campaign tags: - Campaigns security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the campaign schema: type: string responses: "200": description: Campaign deleted successfully content: application/json: schema: type: object properties: status: type: boolean example: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Campaign not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /campaign/{id}/start: post: summary: Start or resume a campaign description: | Queues the campaign for processing and returns immediately — the campaign is **not** yet running when the 202 is returned. Poll `GET /campaign/{id}` and watch for `status: "running"`. This endpoint also acts as a **resume** endpoint: if the campaign is currently paused, calling this endpoint resumes it (`status` transitions from `paused` → `running`). tags: - Campaigns security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the campaign schema: type: string responses: "202": description: Campaign queued for processing content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: message: type: string example: "Campaign is being processed" taskId: type: string description: Internal task identifier for the queued job campaignId: type: string description: The ID of the campaign "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Campaign not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /campaign/{id}/pause: post: summary: Pause a campaign description: | Queues a pause task and returns immediately — the campaign is **not** immediately paused. Poll `GET /campaign/{id}` and watch for `status: "paused"`. tags: - Campaigns security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the campaign schema: type: string responses: "200": description: Pause task queued successfully content: application/json: schema: type: object properties: status: type: boolean example: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase: get: summary: Get all knowledge bases description: Get all knowledge bases tags: - Knowledge Base security: - BearerAuth: [] responses: "200": description: A list of knowledge bases content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: $ref: "#/components/schemas/KnowledgeBase" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" post: summary: Create a knowledge base description: Create a knowledge base tags: - Knowledge Base security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: name: type: string minLength: 1 maxLength: 40 description: Name of the knowledge base (1–40 characters, trimmed) description: type: string required: - name responses: "201": description: Knowledge base created successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string example: "60d0fe4f5311236168a109ca" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/{id}: get: summary: Get a knowledge base description: Get a knowledge base tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the knowledge base schema: type: string responses: "200": description: A knowledge base content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/KnowledgeBase" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Knowledge base not found "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: summary: Delete a knowledge base description: | Delete a knowledge base. **400 is returned when the knowledge base is still linked to an agent:** `"This knowledge base is connected to an agent. Please detach it from the agent before deleting."` Detach the KB from all agents (via agent config) before attempting deletion. tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the knowledge base schema: type: string responses: "200": description: Knowledge base deleted successfully content: application/json: schema: type: object properties: status: type: boolean example: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Knowledge base not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/{id}/items: get: summary: Get all knowledge base items description: Get all knowledge base items tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the knowledge base schema: type: string responses: "200": description: A list of knowledge base items content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: $ref: "#/components/schemas/KnowledgeBaseItem" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/{knowledgeBaseId}/items/{knowledgeBaseItemId}: delete: summary: Delete a knowledge base item description: Delete a knowledge base item tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: knowledgeBaseId required: true description: The ID of the knowledge base schema: type: string - in: path name: knowledgeBaseItemId required: true description: The ID of the knowledge base item schema: type: string responses: "200": description: Knowledge base item deleted successfully content: application/json: schema: type: object properties: status: type: boolean example: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/{id}/items/upload-media: post: summary: Upload a PDF file to a knowledge base description: | Upload a PDF file to a knowledge base. Only PDF files are accepted (validated by MIME type and extension). **400 is returned for billing/entitlement failures before the file is processed:** - `"Insufficient credits for KB storage upload."` — account lacks upload credits - `"KB storage access is not enabled for your account."` — plan doesn't include KB storage No application-level file size limit is enforced — any proxy or infrastructure limits (e.g. nginx) apply instead. tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the knowledge base schema: type: string requestBody: required: true content: multipart/form-data: schema: type: object properties: media: type: string format: binary required: - media responses: "201": description: Knowledge base item created successfully content: application/json: schema: type: object properties: status: type: boolean example: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/phone-numbers: get: summary: Get acquired phone numbers description: | Retrieve all platform-purchased telephony numbers (Twilio/Plivo) for the organization. **Note:** Imported SIP numbers added via `POST /product/import-phone-number` are **not** included in this response — they are stored as a separate product type and returned by a different internal call. tags: - Phone Numbers security: - BearerAuth: [] responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: type: object properties: _id: type: string description: The unique identifier for the phone number example: "6867ca76d0f8f2e0f4201281" productType: type: string enum: [telephony] description: The product type — always `telephony` for numbers returned by this endpoint isActive: type: boolean description: Whether the phone number is active example: false agentId: type: string nullable: true description: ID of the agent currently assigned to this number, or null if unassigned attributes: type: object description: Telephony provider attributes for the phone number properties: provider: type: string enum: [twilio, plivo] description: The telephony provider example: "twilio" phoneNumber: type: string description: The actual phone number in E.164 format example: "+13412184691" countryCode: type: string description: ISO 3166-1 alpha-2 country code of the number example: "US" areaCode: type: string description: Area code of the number (if applicable) example: "341" complianceApplicationId: type: string description: Compliance application ID associated with the number (if applicable) createdAt: type: string format: date-time description: The date and time when the phone number was created example: "2025-07-04T12:35:02.821Z" updatedAt: type: string format: date-time description: The date and time when the phone number was last updated example: "2025-07-07T08:11:35.327Z" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/import-phone-number: post: summary: Import a SIP phone number description: | Bring your own SIP trunk by importing an existing phone number with its SIP termination URL. Atoms creates both inbound and outbound SIP trunks so your number works for making and receiving calls through the platform. If `name` is omitted, a name is auto-generated from the phone number and user ID. tags: - Phone Numbers security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - phoneNumber - sipTerminationUrl properties: phoneNumber: type: string description: Your existing phone number. E.164 format is recommended but not enforced server-side — any non-empty string is accepted. example: "+14155551234" sipTerminationUrl: type: string description: The SIP URI where calls should be routed to your infrastructure example: "sip:trunk.your-provider.com" name: type: string description: A friendly display name for this number example: "Main Support Line" sipUsername: type: string description: Username for SIP authentication (if your trunk requires it) example: "my-sip-user" sipPassword: type: string description: Password for SIP authentication (if your trunk requires it) example: "my-sip-password" example: phoneNumber: "+14155551234" sipTerminationUrl: "sip:trunk.your-provider.com" name: "Main Support Line" sipUsername: "" sipPassword: "" responses: "200": description: Phone number imported successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: _id: type: string description: Unique identifier of the created product example: "507f1f77bcf86cd799439011" productType: type: string enum: [custom] description: The type of product created — always `custom` for imported SIP numbers example: "custom" isActive: type: boolean description: Whether the number is active and ready to use example: true attributes: type: object properties: name: type: string description: Display name for the number example: "Main Support Line" phoneNumber: type: string description: The imported phone number example: "+14155551234" outboundSipTrunkId: type: string description: Identifier for the outbound SIP trunk created example: "ST_xxxxxxxxxxxx" inboundSipTrunkId: type: string description: Identifier for the inbound SIP trunk created example: "ST_xxxxxxxxxxxx" agentId: type: string nullable: true description: ID of the agent assigned to this number (null if unassigned) example: null createdAt: type: string format: date-time description: Timestamp when the product was created example: "2026-03-16T12:00:00.000Z" updatedAt: type: string format: date-time description: Timestamp when the product was last updated example: "2026-03-16T12:00:00.000Z" "400": description: | Bad request — missing required fields or phone number already imported. Exact error when a duplicate number is submitted: `"Number already present"` content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string description: List of validation error messages example: ["Phone number is required"] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /compliance/status: get: summary: Get compliance status description: | Returns the current compliance status for a given country, number type, and user type. This is the single endpoint the frontend uses to determine which step to render (form, submitted, accepted, rejected, expired, or suspended). tags: - Compliance security: - BearerAuth: [] parameters: - name: countryIso in: query required: true schema: type: string minLength: 2 maxLength: 2 description: ISO 3166-1 alpha-2 country code example: "IN" - name: numberType in: query required: true schema: type: string enum: [local, mobile, tollfree] description: The type of phone number example: "local" - name: userType in: query required: true schema: type: string enum: [individual, business] description: The type of end user example: "business" responses: "200": description: Compliance status retrieved successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: step: type: string enum: [form, submitted, accepted, rejected, expired, suspended] description: | The current compliance step: - `form` — no application exists, user should submit one - `submitted` — application is under review - `accepted` — approved, user can rent numbers - `rejected` — rejected, user can resubmit with corrected documents - `expired` — compliance expired - `suspended` — compliance suspended example: "form" application: nullable: true description: The existing compliance application, or null if none exists $ref: "#/components/schemas/ComplianceApplication" requiredDocuments: type: array description: Document types required for this country/numberType/userType combination items: $ref: "#/components/schemas/RequiredDocumentType" "400": description: Invalid query parameters "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /compliance/requirements: get: summary: Get compliance requirements description: | Discover what documents are required for a given country, number type, and user type. Results are cached for 1 hour. Returns an empty `documentTypes` array if no compliance is needed for the given combination. tags: - Compliance security: - BearerAuth: [] parameters: - name: countryIso in: query required: true schema: type: string minLength: 2 maxLength: 2 description: ISO 3166-1 alpha-2 country code example: "IN" - name: numberType in: query required: true schema: type: string enum: [local, mobile, tollfree] description: The type of phone number example: "local" - name: userType in: query required: true schema: type: string enum: [individual, business] description: The type of end user example: "business" responses: "200": description: Requirements retrieved successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/ComplianceRequirement" "400": description: Invalid query parameters "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /compliance/applications: post: summary: Submit a compliance application description: | Submit a new compliance application with end-user details and supporting documents. One application is allowed per organization per country per number type per user type. The request uses `multipart/form-data` because documents are uploaded inline. The `endUser` and `documents` fields are JSON strings embedded in the form data. tags: - Compliance security: - BearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object required: - countryIso - numberType - userType - endUser - documents - files properties: countryIso: type: string minLength: 2 maxLength: 2 description: ISO 3166-1 alpha-2 country code example: "IN" numberType: type: string enum: [local, mobile, tollfree] description: The type of phone number example: "local" userType: type: string enum: [individual, business] description: The type of end user example: "business" endUser: type: string description: | JSON string containing end-user details. Example: ```json { "name": "Acme Corp", "country": "IN" } ``` example: '{"name": "Acme Corp", "country": "IN"}' documents: type: string description: | JSON string containing an array of document metadata. Each entry must have a `documentTypeId` (from the requirements endpoint) and optional `dataFields`. Example: ```json [{"documentTypeId": "dt_123", "dataFields": {"business_name": "Acme Corp"}}] ``` example: '[{"documentTypeId": "dt_123", "dataFields": {"business_name": "Acme Corp"}}]' files: type: array items: type: string format: binary description: | Document files in the same order as the `documents` metadata array. Accepted formats: PDF, JPEG, PNG. Maximum 5 MB per file, up to 10 files. responses: "201": description: Application submitted successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/ComplianceApplication" "400": description: Validation error (invalid JSON, file count mismatch, unsupported file type) "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "409": description: A compliance application already exists for this country/numberType/userType "500": $ref: "#/components/responses/InternalServerErrorResponse" /compliance/applications/{id}: patch: summary: Resubmit a rejected compliance application description: | Resubmit a previously rejected compliance application with corrected documents. Only applications in `rejected` status can be resubmitted. All documents must be re-uploaded — partial updates are not supported. tags: - Compliance security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: The compliance application ID requestBody: required: true content: multipart/form-data: schema: type: object required: - documents - files properties: documents: type: string description: | JSON string containing an array of document metadata. Same format as the create endpoint. example: '[{"documentTypeId": "dt_123", "dataFields": {"business_name": "Acme Corp"}}]' files: type: array items: type: string format: binary description: | Replacement document files. Must match the length of the `documents` array. Accepted formats: PDF, JPEG, PNG. Maximum 5 MB per file. responses: "200": description: Application resubmitted successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/ComplianceApplication" "400": description: Only rejected applications can be resubmitted, or validation error "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Application not found or does not belong to this organization "500": $ref: "#/components/responses/InternalServerErrorResponse" /compliance/applications/{id}/refresh: post: summary: Refresh compliance application status description: | Manually poll Plivo for the latest status of a compliance application. Use this as a fallback when webhooks are delayed. The frontend enforces a 60-second cooldown between refreshes. tags: - Compliance security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: The compliance application ID responses: "200": description: Application status refreshed content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/ComplianceApplication" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Application not found or does not belong to this organization "500": $ref: "#/components/responses/InternalServerErrorResponse" /webhook: get: summary: Get webhooks description: Retrieve all webhooks for the organization or a specific webhook by ID tags: - Webhooks security: - BearerAuth: [] parameters: - in: query name: webhookId schema: type: string description: Optional MongoDB ObjectId (24-char hex) of a specific webhook to retrieve. If omitted, returns all webhooks for the organization. responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: oneOf: - $ref: "#/components/schemas/Webhook" - type: array items: $ref: "#/components/schemas/Webhook" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" post: summary: Create a webhook description: | Create a new webhook with subscriptions for specific agents and events. **400 is also returned when the endpoint URL is already registered:** `"A webhook with this URL has already been registered"` tags: - Webhooks security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: endpoint: type: string description: The webhook endpoint URL example: "https://example.com/webhook" description: type: string description: The description of the webhook example: "Webhook for conversation events" events: type: array description: Array of events to subscribe to items: type: object required: - agentId - eventType properties: agentId: type: string description: The ID of the agent example: "60d0fe4f5311236168a109ca" eventType: type: string enum: [pre-conversation, post-conversation, analytics-completed] description: The type of event to subscribe to example: "post-conversation" required: - endpoint - description - events responses: "201": description: Webhook created successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string description: The ID of the created webhook example: "60d0fe4f5311236168a109ca" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /webhook-events/pre-conversation: post: x-fern-webhook: true tags: - Webhooks summary: pre-conversation operationId: webhookEventPreConversation description: | Fired **before** the agent begins speaking. Use this to enrich CRM data, log call attempts, or gate outbound calls. Does **not** contain `callData`, `transcript`, `variables`, `analytics`, or `recordingUrl`. `callData` is on `post-conversation` and `analytics-completed`; `transcript`, `variables`, and `recordingUrl` are only on `post-conversation`; `analytics` is only on `analytics-completed`. For the full field-level reference, see the [Webhooks guide](/atoms/atoms-platform/features/webhooks). requestBody: description: Event body delivered to your configured webhook URL. required: true content: application/json: schema: $ref: "#/components/schemas/WebhookEventPreConversation" responses: "2XX": description: Your endpoint should return a 2XX status to acknowledge receipt. /webhook-events/post-conversation: post: x-fern-webhook: true tags: - Webhooks summary: post-conversation operationId: webhookEventPostConversation description: | Fired **after** the call ends. Contains the full transcript, call metadata, recording URL, and all agent variables that were in scope during the conversation. For the full field-level reference, see the [Webhooks guide](/atoms/atoms-platform/features/webhooks). requestBody: description: Event body delivered to your configured webhook URL. required: true content: application/json: schema: $ref: "#/components/schemas/WebhookEventPostConversation" responses: "2XX": description: Your endpoint should return a 2XX status to acknowledge receipt. /webhook-events/analytics-completed: post: x-fern-webhook: true tags: - Webhooks summary: analytics-completed operationId: webhookEventAnalyticsCompleted description: | Fired **after** Atoms finishes running the configured disposition and success metrics on the transcript. Arrives some time after `post-conversation`. For the full field-level reference, see the [Webhooks guide](/atoms/atoms-platform/features/webhooks). requestBody: description: Event body delivered to your configured webhook URL. required: true content: application/json: schema: $ref: "#/components/schemas/WebhookEventAnalyticsCompleted" responses: "2XX": description: Your endpoint should return a 2XX status to acknowledge receipt. /webhook/{id}: delete: summary: Delete a webhook description: | Delete a webhook by its ID. **400 is returned when the webhook still has active agent subscriptions:** `"Cannot delete webhook: It is currently assigned to one or more agents. Please remove all agent assignments first."` Call `DELETE /agent/{agentId}/webhook-subscriptions` for each assigned agent before deleting. **400 is also returned for an invalid webhook ID format:** `"The provided Webhook ID is invalid."` tags: - Webhooks security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the webhook to delete schema: type: string responses: "200": description: Webhook deleted successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string description: Success message example: "Webhook deleted successfully" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Webhook not found content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Webhook not found"] "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{agentId}/webhook-subscriptions: get: summary: Get webhook subscriptions for an agent description: Retrieve webhook subscriptions for a given agent ID tags: - Webhooks security: - BearerAuth: [] parameters: - in: path name: agentId required: true description: The ID of the agent schema: type: string responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: $ref: "#/components/schemas/WebhookSubscription" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent not found content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Agent not found"] "500": $ref: "#/components/responses/InternalServerErrorResponse" post: summary: Replace webhook subscriptions for an agent description: | **Replaces** all existing webhook subscriptions for the agent with the provided event types. Any previously configured subscriptions for this agent are deleted before the new ones are created. To add subscriptions without removing existing ones, retrieve current subscriptions first and include them in the request. tags: - Webhooks security: - BearerAuth: [] parameters: - in: path name: agentId required: true description: The ID of the agent to create subscriptions for schema: type: string requestBody: required: true content: application/json: schema: type: object properties: eventTypes: type: array description: Array of event types to subscribe to items: type: string enum: [pre-conversation, post-conversation, analytics-completed] description: The type of event to subscribe to example: "post-conversation" webhookId: type: string description: The ID of the webhook to subscribe to example: "60d0fe4f5311236168a109ca" required: - eventTypes - webhookId responses: "201": description: Subscriptions created successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string description: Success message example: "Subscriptions created successfully" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent not found content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Agent not found"] "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: summary: Delete webhook subscriptions for an agent description: | Deletes **all** webhook subscriptions for the agent, regardless of which webhook they belong to. If the agent has subscriptions across multiple webhooks, all of them are removed in a single call. tags: - Webhooks security: - BearerAuth: [] parameters: - in: path name: agentId required: true description: The ID of the agent to filter subscriptions by schema: type: string responses: "200": description: Subscriptions deleted successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string description: Success message example: "Subscriptions deleted successfully" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent not found content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Agent not found"] "500": $ref: "#/components/responses/InternalServerErrorResponse" /audience: get: summary: Get all audiences description: Retrieve all audiences created by the authenticated user. Users can only access audiences they have created. tags: - Audience security: - BearerAuth: [] responses: "200": description: Successfully retrieved audiences content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: type: object properties: _id: type: string description: The unique identifier for the audience example: "60d0fe4f5311236168a109ca" name: type: string description: The name of the audience example: "My Customer List" description: type: string description: The description of the audience example: "List of customers for marketing campaign" phoneNumberColumnName: type: string description: The name of the column in the CSV that contains phone numbers example: "phoneNumber" organization: type: string description: The organization ID example: "60d0fe4f5311236168a109cb" createdBy: type: string description: The user ID who created the audience example: "60d0fe4f5311236168a109cc" createdAt: type: string format: date-time description: The date and time when the audience was created example: "2025-01-15T10:30:00.000Z" updatedAt: type: string format: date-time description: The date and time when the audience was last updated example: "2025-01-15T10:30:00.000Z" memberCount: type: number description: Current number of members in the audience hasCampaigns: type: boolean description: Whether any campaigns are currently using this audience campaigns: type: array description: Active campaigns using this audience items: type: object properties: _id: type: string name: type: string status: type: string createdAt: type: string format: date-time "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" post: summary: Create audience with CSV upload description: | Create a new audience by uploading a CSV file containing phone numbers. Only CSV text files are accepted — binary files will produce malformed data. **Additional 400 cases:** - Duplicate phone numbers in the CSV: `"Some phone numbers in your CSV already exist in this audience. Please remove duplicate entries and try again."` - Member limit exceeded: `"Audience cannot exceed X members"` tags: - Audience security: - BearerAuth: [] requestBody: required: true content: multipart/form-data: schema: type: object properties: name: type: string description: The name of the audience example: "test_audience" description: type: string description: Optional description of the audience example: "List of customers for marketing campaign" phoneNumberColumnName: type: string description: The name of the column in the CSV that contains phone numbers example: "phoneNumber" identifierColumnName: type: string description: The name of the column in the CSV that contains identifiers (e.g., names) example: "Name" file: type: string format: binary description: CSV file containing phone numbers and identifiers (max 5MB) example: "audience_template.csv" required: - name - phoneNumberColumnName - file responses: "200": description: Audience created successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: _id: type: string description: The unique identifier for the audience example: "60d0fe4f5311236168a109ca" name: type: string description: The name of the audience example: "My Customer List" description: type: string description: The description of the audience example: "List of customers for marketing campaign" phoneNumberColumnName: type: string description: The name of the column in the CSV that contains phone numbers example: "phoneNumber" identifierColumnName: type: string description: The name of the column in the CSV that contains identifiers example: "Name" organization: type: string description: The organization ID example: "60d0fe4f5311236168a109cb" createdBy: type: string description: The user ID who created the audience example: "60d0fe4f5311236168a109cc" createdAt: type: string format: date-time description: The date and time when the audience was created example: "2025-01-15T10:30:00.000Z" updatedAt: type: string format: date-time description: The date and time when the audience was last updated example: "2025-01-15T10:30:00.000Z" "400": description: Bad request content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: [ "CSV file is required", "Some phone numbers in your CSV already exist in this audience. Please remove duplicate entries and try again.", ] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /audience/{id}: get: summary: Get audience by ID description: | Retrieve a specific audience by its ID. Note: if the audience belongs to a different organization, the API returns 404 (not 403) — ownership is deliberately obscured. tags: - Audience security: - BearerAuth: [] parameters: - name: id in: path required: true description: The unique identifier of the audience schema: type: string example: "60d0fe4f5311236168a109ca" responses: "200": description: Successfully retrieved audience content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: _id: type: string description: The unique identifier for the audience example: "60d0fe4f5311236168a109ca" name: type: string description: The name of the audience example: "My Customer List" description: type: string description: The description of the audience example: "List of customers for marketing campaign" phoneNumberColumnName: type: string description: The name of the column in the CSV that contains phone numbers example: "phoneNumber" organization: type: string description: The organization ID example: "60d0fe4f5311236168a109cb" createdBy: type: string description: The user ID who created the audience example: "60d0fe4f5311236168a109cc" createdAt: type: string format: date-time description: The date and time when the audience was created example: "2025-01-15T10:30:00.000Z" updatedAt: type: string format: date-time description: The date and time when the audience was last updated example: "2025-01-15T10:30:00.000Z" "400": description: Bad request content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Audience ID missing"] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Audience not found (also returned when audience belongs to a different organization) "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: summary: Delete audience description: | Delete a specific audience by its ID. Users can only delete audiences they created. **400 is returned if the audience is used by an active campaign:** `"can't delete audience, campaign with this audience exists"` Remove the campaign first, then retry deletion. On success, `data` is always an empty array `[]`. tags: - Audience security: - BearerAuth: [] parameters: - name: id in: path required: true description: The unique identifier of the audience to delete schema: type: string example: "60d0fe4f5311236168a109ca" responses: "200": description: Audience deleted successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array example: [] "400": description: Bad request content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["can't delete audience, campaign with this audience 60d0fe4f5311236168a109ca exists"] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Audience not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /audience/{id}/members: get: summary: Get audience members description: Retrieve members of a specific audience with pagination support. Users can only access members of audiences they created. tags: - Audience security: - BearerAuth: [] parameters: - name: id in: path required: true description: The unique identifier of the audience schema: type: string example: "60d0fe4f5311236168a109ca" - name: page in: query required: false description: Page number for pagination (default is 1) schema: type: integer minimum: 1 default: 1 example: 1 - name: offset in: query required: false description: | Number of items per page (default is 5). Note: this parameter is named "offset", not "limit" — sending ?limit=N is silently ignored. schema: type: integer minimum: 1 default: 5 example: 10 responses: "200": description: Successfully retrieved audience members content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: members: type: array items: type: object properties: _id: type: string description: The unique identifier for the audience member example: "60d0fe4f5311236168a109cd" data: type: object description: Dynamic data from CSV, structure depends on uploaded file example: phoneNumber: "+1234567890" name: "John Doe" email: "john@example.com" totalCount: type: integer description: Total number of members in the audience example: 150 totalPages: type: integer description: Total number of pages available example: 15 hasMore: type: boolean description: Whether there are more pages available example: true "400": description: Bad request content: application/json: schema: type: object properties: status: type: string example: "error" errors: type: array items: type: string example: ["Audience ID is required"] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Forbidden — audience belongs to a different organization "404": description: Audience not found "500": description: Internal server error content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Failed to fetch audience members"] post: summary: Add audience members description: | Add new members to an existing audience. Each member object must include a key matching the audience's `phoneNumberColumnName`. If it's missing, the API returns 400: `"Each member must have a field"`. Adding members that would exceed the audience limit also returns 400. Note: if the audience belongs to a different organization, the API returns 404 (not 403). tags: - Audience security: - BearerAuth: [] parameters: - name: id in: path required: true description: The unique identifier of the audience schema: type: string example: "60d0fe4f5311236168a109ca" requestBody: required: true content: application/json: schema: type: object properties: members: type: array description: Array of member objects with dynamic structure based on audience configuration items: type: object description: Member data with keys matching the audience's CSV structure. Must include the phone number column. example: phoneNumber: "+1234567890" name: "John Doe" email: "john@example.com" required: - members responses: "200": description: Members added successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: type: object properties: message: type: string example: "5 members added successfully" data: type: object properties: added: type: integer description: Number of members successfully added example: 5 skipped: type: integer description: Number of members skipped (e.g., duplicates) example: 2 "400": description: Bad request content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: [ "Each member must have a phoneNumber field", "Cannot add 15 members. You currently have 9990 members in this audience. The maximum limit is 10000 members. You can add up to 10 more members.", ] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Audience not found (also returned when audience belongs to a different organization) "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: summary: Delete audience members description: Remove specific members from an audience by their member IDs. Users can only delete members from audiences they created. tags: - Audience security: - BearerAuth: [] parameters: - name: id in: path required: true description: The unique identifier of the audience schema: type: string example: "60d0fe4f5311236168a109ca" requestBody: required: true content: application/json: schema: type: object properties: memberIds: type: array description: Array of member IDs to delete items: type: string example: "60d0fe4f5311236168a109cd" required: - memberIds responses: "200": description: Members deleted successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: deletedCount: type: integer description: Number of members successfully deleted example: 3 "400": description: Bad request content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Audience ID missing"] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Audience not found (also returned when audience belongs to a different organization) "500": $ref: "#/components/responses/InternalServerErrorResponse" /audience/{id}/members/search: get: summary: Search audience members description: | Search for members within a specific audience using flexible search parameters. Users can only search members of audiences they created. **Search Types:** - **General Search** (`query`): Searches across all fields in the audience member data - **Field-Specific Search**: Use any field name as a parameter (e.g., `firstName=john`, `phoneNumber=123456`, `email=test@example.com`) **Examples:** - `?query=john` - General search across all fields - `?firstName=john` - Search specifically in firstName field - `?phoneNumber=555-1234` - Search specifically in phoneNumber field - `?firstName=john&lastName=doe` - Search for members matching both criteria **Note:** When using phoneNumber field, do not use quotes around the phone number. You can use either a general search OR field-specific searches, but not both simultaneously. tags: - Audience security: - BearerAuth: [] parameters: - name: id in: path required: true description: The unique identifier of the audience schema: type: string example: "60d0fe4f5311236168a109ca" - name: query in: query required: false description: General search term that searches across all fields in audience member data schema: type: string example: "john" - name: "*" in: query required: false description: | Any field name can be used as a query parameter for field-specific searches. Examples: firstName, lastName, phoneNumber, email, etc. The parameter name becomes the field to search in, and the value is the search term. When using phoneNumber field, do not use quotes around the phone number. schema: type: string example: "field_value" responses: "200": description: Search results returned successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: members: type: array items: type: object properties: _id: type: string description: The unique identifier for the audience member example: "60d0fe4f5311236168a109cd" data: type: object description: Dynamic data from CSV, structure depends on uploaded file example: phoneNumber: "+1234567890" name: "John Doe" email: "john@example.com" searchInfo: type: object description: Information about the search performed properties: searchType: type: string description: The type of search performed enum: ["general", "multiple"] example: "multiple" searchTerm: type: string description: The search term(s) used example: "john" searchFields: type: array items: type: string description: The specific fields searched (for field-specific searches) example: ["firstName", "lastName"] totalResults: type: integer description: The number of results returned example: 5 "400": description: Bad request content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: [ "At least one search parameter is required. Use 'query' for general search across all fields, or use field-specific searches like 'firstName=john' or 'phoneNumber=123456'.", ] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Audience not found "500": description: Internal server error content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Failed to search audience members"] # ── Agent Versioning: Drafts ─────────────────────────────────────────── /agent/{id}/drafts: post: summary: Create a draft description: Create a new draft from an existing published version or another draft. Exactly one of sourceVersionId or sourceDraftId is required. tags: - Agent Versioning - Drafts security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateDraftRequest" responses: "201": description: Draft created successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/AgentVersion" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" get: summary: List active drafts description: List all active (non-discarded) drafts for an agent. tags: - Agent Versioning - Drafts security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: allOf: - $ref: "#/components/schemas/AgentVersion" - type: object properties: lastEditorName: type: string nullable: true description: Display name of the last editor "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}: get: summary: Get draft detail description: Returns the latest revision of a draft along with its edit history. tags: - Agent Versioning - Drafts security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/DraftId" - name: limit in: query required: false description: Max number of edit history entries to return (1-100) schema: type: integer minimum: 1 maximum: 100 responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: latest: $ref: "#/components/schemas/AgentVersion" editHistory: type: array items: $ref: "#/components/schemas/DraftEditHistoryEntry" editCount: type: integer description: Total number of edits on this draft "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" patch: summary: Rename a draft description: | Rename a draft. For config changes, use PATCH /agent/{id}/drafts/{draftId}/config instead. tags: - Agent Versioning - Drafts security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/DraftId" requestBody: required: true content: application/json: schema: type: object required: - draftName properties: draftName: type: string maxLength: 100 description: New name for the draft responses: "200": description: Draft renamed successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: draftName: type: string "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: summary: Discard a draft description: Discard (soft-delete) a draft. Only the draft creator or an admin can discard. tags: - Agent Versioning - Drafts security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/DraftId" responses: "200": description: Draft discarded successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: "null" "403": $ref: "#/components/responses/ForbiddenError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}/diff: get: summary: Get draft diff description: Compare a draft against its source version or another specified version. tags: - Agent Versioning - Drafts security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/DraftId" - name: compareTo in: query required: false description: Version ID to compare against. If omitted, compares against the source version. schema: type: string pattern: "^[a-f\\d]{24}$" responses: "200": description: Diff returned successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object description: Section-by-section diff between the draft and the comparison target "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}/publish: post: summary: Publish a draft description: Publish a draft as a new versioned release. Optionally activate it immediately. tags: - Agent Versioning - Drafts security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/DraftId" requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/PublishDraftRequest" responses: "201": description: Draft published as a new version content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/AgentVersion" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}/test-call: post: summary: Test call with draft config description: Initiate a test call using the draft's resolved configuration. tags: - Agent Versioning - Drafts security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/DraftId" requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/TestCallRequest" responses: "200": description: Test call initiated content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object description: Test call result details "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}/config: patch: summary: Edit draft config (prompt, tools, post-call metrics, voice, etc.) description: | Update the configuration of a draft. This single endpoint is how every agent-level config field is changed: prompt, tools, voice, language, **post-call analytics (disposition metrics)**, and more. There is no standalone post-call-analytics endpoint — it lives here as the `postCallAnalyticsConfig` body field. ## Post-Call Analytics Pass a `postCallAnalyticsConfig` object to configure disposition metrics (STRING, BOOLEAN, INTEGER, ENUM, DATETIME) that are automatically extracted from each completed call, along with the `useInternalAnalyticsModel` and `useReasoningModel` flags. See the [Post-Call Metrics guide](/atoms/atoms-platform/features/post-call-metrics) for a full Python walkthrough and disposition metric schema reference. ## Full payload Accepts the full agent-shaped config payload (language, synthesizer, slmModel, defaultVariables, preCallAPI, etc.) plus two draft-specific fields: - `singlePromptConfig` — prompt and tools (end_call, transfer_call, api_call, extract_dynamic_variables, knowledge_base_search). - `postCallAnalyticsConfig` — disposition metrics + analytics/ reasoning model flags. Each PATCH increments the draft's revision counter. Config is not live until the draft is published and activated (see `/drafts/{draftId}/publish` and `/versions/{versionId}/activate`). tags: - Agent Versioning - Drafts - Post-Call Analytics security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/DraftId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/DraftConfigRequest" responses: "200": description: Draft config updated successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/AgentVersion" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" # ── Agent Versioning: Published Versions ─────────────────────────────── /agent/{id}/versions: get: summary: List published versions description: List published versions for an agent with pagination and optional pin filter. tags: - Agent Versioning - Versions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - name: limit in: query required: false description: Number of versions to return (1-100, default 20) schema: type: integer minimum: 1 maximum: 100 default: 20 - name: skip in: query required: false description: Number of versions to skip (default 0) schema: type: integer minimum: 0 default: 0 - name: isPinned in: query required: false description: Filter by pinned status schema: type: boolean responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: versions: type: array items: allOf: - $ref: "#/components/schemas/AgentVersion" - type: object properties: publishedByName: type: string nullable: true description: Display name of the user who published total: type: integer description: Total count of matching versions "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/diff: get: summary: Diff two versions description: Compare two published versions side-by-side by their IDs. tags: - Agent Versioning - Versions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - name: versionA in: query required: true description: ID of the first version schema: type: string pattern: "^[a-f\\d]{24}$" - name: versionB in: query required: true description: ID of the second version schema: type: string pattern: "^[a-f\\d]{24}$" responses: "200": description: Diff returned successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object description: Section-by-section diff between the two versions "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/compare-metrics: get: summary: Compare metrics between two versions description: Compare analytics/call metrics between two published versions over an optional date range. tags: - Agent Versioning - Versions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - name: versionA in: query required: true description: ID of the first version schema: type: string pattern: "^[a-f\\d]{24}$" - name: versionB in: query required: true description: ID of the second version schema: type: string pattern: "^[a-f\\d]{24}$" - name: dateFrom in: query required: false description: Start date for the comparison range (ISO 8601) schema: type: string format: date-time - name: dateTo in: query required: false description: End date for the comparison range (ISO 8601) schema: type: string format: date-time responses: "200": description: Metrics comparison returned content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object description: Aggregated metrics for each version "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/{versionId}: get: summary: Get version detail description: | Returns the full detail of a specific published version (read-only). Published versions are config-immutable — to modify config, create a draft from this version and publish it as a new version. tags: - Agent Versioning - Versions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/VersionId" responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: version: $ref: "#/components/schemas/AgentVersion" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" patch: summary: Update version metadata (label, description, pin only) description: | Update a published version's label, description, or pinned status. At least one field is required. Published versions (both active and inactive) are config-immutable — their agent configuration cannot be changed. To modify config, create a new draft from the version, edit the draft, and publish it as a new version. tags: - Agent Versioning - Versions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/VersionId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateVersionMetaRequest" responses: "200": description: Version metadata updated content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/AgentVersion" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/{versionId}/activate: patch: summary: Activate a version description: | Set a published version as the active version for the agent. The previously active version is deactivated. This does not modify the version's config — it only changes which version serves live traffic. tags: - Agent Versioning - Versions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/VersionId" responses: "200": description: Version activated successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/AgentVersion" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/{versionId}/test-call: post: summary: Test call with version config description: Initiate a test call using a specific published version's configuration. tags: - Agent Versioning - Versions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/VersionId" requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/TestCallRequest" responses: "200": description: Test call initiated content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object description: Test call result details "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" # ── GET /agent/{id}/resolved-config — REMOVED ────────────────────────── # Unused by UI. Resolved config is served via GET /agent/{id}?draftId=X # which merges _resolvedConfig into the agent DTO. Marked for backend # removal in tasks/09-backend-misc-cleanup.md. components: securitySchemes: BearerAuth: type: http scheme: bearer description: API key from the console ApiKey collection, sent as Bearer token. Also accepts session cookies for browser-based auth. parameters: AgentId: name: id in: path required: true description: The agent ID schema: type: string example: "60d0fe4f5311236168a109ca" DraftId: name: draftId in: path required: true description: The draft ID schema: type: string VersionId: name: versionId in: path required: true description: The published version ID schema: type: string pattern: "^[a-f\\d]{24}$" schemas: ApiResponse: type: object properties: status: type: boolean data: type: object UnauthorizedErrorResponse: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Unauthorized: User not found"] InternalServerErrorResponse: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Internal server error"] BadRequestErrorResponse: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Invalid input"] CreateAgentFromTemplateRequest: type: object required: - agentName - templateId properties: agentName: type: string description: Name of the agent agentDescription: type: string description: Description of the agent templateId: type: string description: ID of the template to use. You can get the list of templates with their description and id from the /agent/template endpoint. CreateAgentRequest: type: object required: - name properties: name: type: string description: type: string backgroundSound: type: string enum: ["", "office", "cafe", "call_center", "static"] default: "" description: "Ambient background sound during calls. Options: '' (none), 'office', 'cafe', 'call_center', 'static'. Note: this value is currently overridden by the server default on creation; update via PATCH after creation." # visibleToEveryone: # type: boolean # default: false language: type: object description: | Language configuration for the agent. Cross-field rule: `default` must be one of the values in `supported`. Tamil (`ta`) cannot be combined with other languages in `supported`. properties: default: type: string enum: [en, hi, mr, gu, ta, es, north_indic, bn, or] description: "The default language of the agent. Note: `ta` cannot be combined with other languages in `supported`." default: en supported: type: array description: | Languages the agent understands. `default` must be one of these values. Tamil (`ta`) cannot be combined with other languages. items: type: string enum: [en, hi, mr, gu, ta, es, north_indic, bn, or] switching: type: object description: Language switching configuration for the agent. If enabled, the agent will be able to switch between languages based on the user's language. properties: isEnabled: type: boolean description: Whether to enable language switching for the agent default: false minWordsForDetection: type: number minimum: 1 maximum: 10 description: Minimum number of words required for language detection default: 2 strongSignalThreshold: type: number minimum: 0.1 maximum: 0.9 description: Threshold for strong language signal detection (0.1 to 0.9) default: 0.7 weakSignalThreshold: type: number minimum: 0.1 maximum: 0.9 description: Threshold for weak language signal detection (0.1 to 0.9) default: 0.3 minConsecutiveForWeakThresholdSwitch: type: number minimum: 1 maximum: 5 description: Minimum consecutive detections required for weak threshold language switch default: 2 synthesizer: type: object description: | Synthesizer (TTS) configuration for the agent. Models `waves`, `waves_lightning_large`, `waves_lightning_v2`, and `waves_lightning_v3_1` validate `voiceId` against the Waves API. All other models accept any voiceId. Cloned voices are regular voiceIds — use them with any compatible Waves model. properties: voiceConfig: type: object description: Voice configuration for the synthesizer. properties: model: type: string enum: - waves - waves_lightning_large - waves_lightning_v2 - waves_lightning_v3_1 - waves_lightning_v3 - waves_lightning_v2_http - gpt-realtime - gpt-realtime-mini default: waves_lightning_large description: The TTS model to use. voiceId: type: string default: nyah description: The voice ID to use. For cloned voices, pass the voiceId from the Waves platform with a compatible model. gender: type: string enum: - male - female default: female description: The gender of the voice. default: model: waves_lightning_large voiceId: nyah speed: type: number minimum: 0 maximum: 2 default: 1.2 consistency: type: number minimum: 0 maximum: 1 default: 0.5 similarity: type: number minimum: 0 maximum: 1 default: 0 enhancement: type: number enum: [0, 1, 2] default: 1 sampleRate: type: number enum: [8000, 16000, 24000, 44100] default: 16000 description: Output audio sample rate in Hz. globalKnowledgeBaseId: type: string description: The global knowledge base ID of the agent. You can create a global knowledge base by using the /knowledgebase endpoint and assign it to the agent. The agent will use this knowledge base for its responses. slmModel: type: string enum: - electron - electron-kogta - electron-kogta-v2 - gpt-4o - gpt-4.1 - gpt-5.2 - gpt-realtime - gpt-realtime-mini default: electron description: | The LLM model to use for the agent. Note: `gpt-5.2`, `electron-kogta`, and `electron-kogta-v2` require org-level access and return 403 if not enabled. `workflowType` must be `single_prompt` to use `gpt-realtime` or `gpt-realtime-mini`. defaultVariables: type: object description: The default variables to use for the agent. These variables will be used if no variables are provided when initiating a conversation with the agent. preCallAPI: type: object description: Configuration for an API call to be made before the call starts. The response variables can be injected into the agent's prompt. properties: isEnabled: type: boolean default: false description: Whether the pre-call API is enabled. url: type: string format: uri description: The URL of the API endpoint to call. method: type: string enum: ["GET", "POST", "PUT", "DELETE", "PATCH"] description: The HTTP method to use for the API call. headers: type: object additionalProperties: type: string description: Optional HTTP headers to include in the request. body: type: object description: Optional request body for POST/PUT/PATCH requests. timeout: type: integer minimum: 1 maximum: 30 default: 5 description: Timeout in seconds for the API call. queryParams: type: object description: Optional query parameters to include in the request URL. responseVariables: type: array description: List of variables to extract from the API response using JSON path expressions. items: type: object required: - variableName - jsonPath properties: variableName: type: string description: The name of the variable to inject into the agent prompt. jsonPath: type: string description: JSON path expression to extract the value from the API response. required: - url - method globalPrompt: type: string maxLength: 4000 description: | Set global instructions for your agent's personality, role, and behavior throughout conversations. Note: Only used for workflow_graph agents. Maximum 4000 characters. telephonyProductId: type: array items: type: string description: IDs of telephony products (phone numbers) to associate with the agent for inbound/outbound calls. workflowType: $ref: "#/components/schemas/WorkflowType" default: single_prompt description: The type of workflow to create for the agent. Defaults to `single_prompt` if not specified. Using `workflow_graph` requires conversational agent access (403 if not enabled). firstMessage: type: string maxLength: 500 description: The first message the agent sends when a conversation starts. muteUserUntilFirstBotResponse: type: boolean description: When true, the user's audio is muted until the agent has finished its first response. allowInterruptions: type: boolean description: Whether the user can interrupt the agent while it is speaking. waitForUserToSpeakFirst: type: boolean description: When true, the agent waits for the user to speak before sending the first message. interruptionBackoffTimer: type: number minimum: 0 maximum: 10 description: Seconds the agent waits after being interrupted before resuming speech. smartTurnConfig: type: object description: Smart turn-detection configuration. When enabled, the agent uses an additional model to decide whether the user has finished a turn. properties: isEnabled: type: boolean waitTimeInSecs: type: number minimum: 0 maximum: 10 description: How long to wait after the user stops speaking before responding. voiceDetectionConfig: type: object description: Voice activity detection (VAD) configuration. Controls how the agent decides when speech is present. properties: confidence: type: number minimum: 0 maximum: 1 description: Minimum VAD confidence threshold to register speech. minVolume: type: number minimum: 0 maximum: 1 description: Minimum input volume threshold to register speech. triggerTimeInSecs: type: number minimum: 0 maximum: 10 description: How long sustained speech must be detected before turning the VAD on. releaseTimeInSecs: type: number minimum: 0 maximum: 10 description: How long after silence before the VAD turns off. voiceMailDetectionConfig: type: object description: Voicemail-detection configuration. When the call hits a voicemail tone, the agent plays `endText` and ends the call. properties: enabled: type: boolean endText: type: string maxLength: 200 description: Message played before hanging up when voicemail is detected. denoisingConfig: type: object description: Background-noise denoising configuration for the agent's input audio. properties: isEnabled: type: boolean redactionConfig: type: object description: PII redaction configuration. When enabled, personally identifiable information is redacted from transcripts before storage. properties: isEnabled: type: boolean pronunciationDicts: type: array description: Pronunciation overrides — words the TTS engine should pronounce differently from its default. items: type: object required: - word - pronunciation properties: word: type: string description: The word to override. pronunciation: type: string description: How the word should be pronounced (phonetic spelling). llmIdleTimeoutConfig: type: object description: Timeout configuration for the LLM stage of a conversation. Triggers a retry or call termination when the LLM does not respond within the configured window. properties: chatTimeoutTimeInSecs: type: number minimum: 1 maximum: 300 description: LLM idle timeout for chat conversations, in seconds. webcallTimeoutTimeInSecs: type: number minimum: 1 maximum: 300 description: LLM idle timeout for web calls, in seconds. telephonyTimeoutTimeInSecs: type: number minimum: 1 maximum: 300 description: LLM idle timeout for telephony calls, in seconds. maxRetries: type: number description: Maximum number of LLM-idle retries before terminating the call. System-defined min/max. sessionTimeoutConfig: type: object description: Maximum duration of a conversation session. The call ends after this elapsed time even if active. properties: timeoutTimeInSecs: type: number maximum: 3600 default: 1800 description: Maximum session duration in seconds (max 1 hour). Defaults to 1800 (30 minutes). timezone: type: object description: Timezone applied to scheduled actions and timestamps the agent reports to the user. properties: label: type: string description: IANA timezone label (e.g. `America/New_York`). offset: type: number description: UTC offset in minutes (e.g. -300 for EST). callDispositionConfig: type: string description: Configuration string for call disposition tracking. allowInboundCall: type: boolean default: true description: Whether the agent accepts inbound calls. enableStyleGuide: type: boolean default: true description: Whether style guide enforcement is applied to agent responses. speechFormatting: type: boolean description: Whether speech formatting is applied to the agent's responses. UpdateAgentRequest: type: object description: | Agent update payload. Behavior depends on whether the agent has versioning enabled: **Versioned agents**: only the metadata fields below are accepted. Config-level fields (language, synthesizer, slmModel, etc.) return 400. **Non-versioned agents**: all configuration fields are accepted — the same full set as `POST /agent` (see `CreateAgentRequest`). properties: name: type: string description: Name of the agent. description: type: string description: Description of the agent. avatarUrl: type: string description: URL of the agent's avatar image. telephonyProductId: type: array items: type: string description: IDs of telephony products (phone numbers) to associate with the agent. allowInboundCall: type: boolean description: Whether the agent accepts inbound calls. visibleToEveryone: type: boolean description: Whether the agent is visible to all members of the organization. DraftConfigRequest: description: | Config payload for editing a draft via `PATCH /agent/{id}/drafts/{draftId}/config`. Accepts the same shape as the legacy `PATCH /agent/{id}` body plus two versioning-era fields — `singlePromptConfig` (prompt + tools) and `postCallAnalyticsConfig`. All fields are optional; a draft save may update any subset. allOf: - $ref: "#/components/schemas/CreateAgentRequest" - type: object properties: singlePromptConfig: $ref: "#/components/schemas/SinglePromptConfig" postCallAnalyticsConfig: $ref: "#/components/schemas/PostCallAnalyticsConfig" AgentDTO: type: object properties: _id: type: string description: The ID of the agent name: type: string description: The name of the agent description: type: string description: The description of the agent backgroundSound: type: string enum: ["", "office", "cafe", "call_center", "static"] description: "Ambient background sound during calls. Options: '' (none), 'office', 'cafe', 'call_center', 'static'." organization: type: string description: The organization ID of the agent workflowId: type: string description: The workflow ID of the agent workflowType: $ref: "#/components/schemas/WorkflowType" default: workflow_graph description: The type of workflow used by the agent createdBy: type: string description: The user ID of the user who created the agent globalKnowledgeBaseId: type: string description: The global knowledge base ID of the agent language: type: object description: The language configuration of the agent properties: default: type: string description: The default language of the agent enum: [en, hi, mr, gu, ta, es, north_indic, bn, or] switching: type: object description: Language switching configuration for the agent properties: isEnabled: type: boolean description: Whether language switching is enabled for the agent minWordsForDetection: type: number description: Minimum number of words required for language detection strongSignalThreshold: type: number description: Threshold for strong language signal detection weakSignalThreshold: type: number description: Threshold for weak language signal detection minConsecutiveForWeakThresholdSwitch: type: number description: Minimum consecutive detections required for weak threshold language switch supported: type: array items: type: string description: The supported languages of the agent synthesizer: type: object description: The synthesizer (TTS) configuration of the agent properties: voiceConfig: type: object description: The voice configuration of the synthesizer properties: model: type: string description: The model of the synthesizer enum: - waves - waves_lightning_large - waves_lightning_large_voice_clone - waves_lightning_v2 default: waves_lightning_large voiceId: type: string description: The voice ID of the synthesizer. default: nyah gender: type: string enum: - male - female default: female speed: type: number default: 1.2 description: The speed of the synthesizer consistency: type: number default: 0.5 description: The consistency of the synthesizer similarity: type: number default: 0 description: The similarity of the synthesizer enhancement: type: number default: 1 description: The enhancement of the synthesizer sampleRate: type: number description: The audio sample rate used by the synthesizer slmModel: type: string enum: - electron - electron-kogta - electron-kogta-v2 - gpt-4o - gpt-4.1 - gpt-5.2 - gpt-realtime - gpt-realtime-mini description: The LLM model to use for the agent. LLM model will be used to generate the response and take decisions based on the user's query. defaultVariables: type: object description: The default variables to use for the agent. These variables will be used if no variables are provided when initiating a conversation with the agent. preCallAPI: type: object description: Configuration for an API call to be made before the call starts. The response variables can be injected into the agent's prompt. properties: isEnabled: type: boolean default: false description: Whether the pre-call API is enabled. url: type: string format: uri description: The URL of the API endpoint to call. method: type: string enum: ["GET", "POST", "PUT", "DELETE", "PATCH"] description: The HTTP method to use for the API call. headers: type: object additionalProperties: type: string description: Optional HTTP headers to include in the request. body: type: object description: Optional request body for POST/PUT/PATCH requests. timeout: type: integer minimum: 1 maximum: 30 default: 5 description: Timeout in seconds for the API call. queryParams: type: object description: Optional query parameters to include in the request URL. responseVariables: type: array description: List of variables to extract from the API response using JSON path expressions. items: type: object required: - variableName - jsonPath properties: variableName: type: string description: The name of the variable to inject into the agent prompt. jsonPath: type: string description: JSON path expression to extract the value from the API response. required: - url - method createdAt: type: string format: date-time description: The date and time when the agent was created updatedAt: type: string format: date-time description: The date and time when the agent was last updated avatarUrl: type: string description: URL of the agent's avatar image firstMessage: type: string description: The opening message spoken by the agent at the start of a call allowInterruptions: type: boolean description: Whether the agent can be interrupted mid-speech by the caller waitForUserToSpeakFirst: type: boolean description: When true, the agent waits for the caller to speak before responding totalCalls: type: number description: Total number of calls made with this agent transcriberType: type: string description: The speech-to-text engine used for transcription globalPrompt: type: string description: A global system prompt prepended to all agent interactions archived: type: boolean description: Whether the agent has been archived. Archived agents are excluded from default listings. archivedAt: type: string format: date-time description: The date and time when the agent was archived isLocked: type: boolean description: Whether the agent is locked and cannot be edited activeVersionId: type: string description: ID of the currently-active published version. Matches `versionId`. versionId: type: string description: Alias for `activeVersionId`. _resolvedConfig: type: object additionalProperties: true description: | The resolved config of the target version, merged into a flat shape. Not returned in list responses (`GET /agent`). Only populated in single-agent responses (`GET /agent/{id}`) when the agent has a published, activated version. Can contain up to ~30 fields depending on which config sections are set. properties: prompt: type: string description: Active version's single-prompt text. tools: type: array items: $ref: "#/components/schemas/Tool" description: Active version's configured tools. postCallAnalyticsConfig: $ref: "#/components/schemas/PostCallAnalyticsConfig" callDispositionConfig: type: string modelName: type: string description: LLM model name on the resolved version. transcriberType: type: string description: STT engine in use on the resolved version. defaultLanguage: type: string enum: [en, hi, mr, gu, ta, es, north_indic, bn, or] description: Default language set on the resolved version. supportedLanguages: type: array items: type: string description: Supported languages on the resolved version. languageSwitching: type: object description: Language-switching configuration on the resolved version. firstMessage: type: string description: Opening message on the resolved version. globalPrompt: type: string description: Global prompt on the resolved version (workflow_graph agents only). preCallAPI: type: object description: Pre-call API configuration on the resolved version. workflowGraph: type: object description: Full node graph for workflow_graph agents. Null for single_prompt agents. muteUserUntilFirstBotResponse: type: boolean allowInterruptions: type: boolean voiceDetectionConfig: type: object smartTurnConfig: type: object backgroundSound: type: string denoisingConfig: type: object redactionConfig: type: object llmIdleTimeoutConfig: type: object sessionTimeoutConfig: type: object _configSource: type: string enum: - active - draft - version description: | Only present when `?draftId` or `?versionId` query params are used. Indicates which config source was resolved into `_resolvedConfig`. _versionedWorkflow: type: object description: | **Deprecated — internal use only.** Legacy field present whenever `_resolvedConfig` is populated. Mirrors a subset of `_resolvedConfig` (`prompt`, `tools`, `workflowGraph`). Kept for backward compatibility with existing frontend code. Ignore in new integrations. properties: prompt: type: string tools: type: array items: $ref: "#/components/schemas/Tool" workflowGraph: type: object # ── Agent Versioning Schemas ────────────────────────────────────────── AgentVersion: type: object description: Represents either a draft revision or a published version of an agent's configuration. properties: _id: type: string description: Unique identifier agent: type: string description: The agent this version belongs to status: type: string enum: [published, draft, archived] description: Current status of the version record versionNumber: type: integer nullable: true description: Auto-incremented version number (published versions only) label: type: string nullable: true description: Human-readable label for the version maxLength: 200 description: type: string nullable: true description: Description of what changed in this version maxLength: 2000 isPinned: type: boolean default: false description: Whether the version is pinned for quick access publishedBy: type: string nullable: true description: User ID of who published this version draftId: type: string nullable: true description: Unique draft identifier (drafts only) draftName: type: string nullable: true description: Human-readable draft name maxLength: 100 draftRevision: type: integer nullable: true description: Revision number within the draft (drafts only) sourceVersionId: type: string nullable: true description: The published version this draft was branched from blocks: type: object description: References to the 13 config section blocks properties: workflow_prompt: type: string workflow_tools: type: string workflow_graph: type: string llm: type: string voice: type: string language: type: string call_handling: type: string detection: type: string analytics: type: string timeouts: type: string audio: type: string privacy: type: string widget: type: string workflowType: $ref: "#/components/schemas/WorkflowType" parentVersion: type: string nullable: true description: The version this was derived from isActive: type: boolean description: Whether this is the currently active version for the agent createdBy: type: string description: User ID of who created this record createdAt: type: string format: date-time updatedAt: type: string format: date-time DraftEditHistoryEntry: type: object properties: revision: type: integer description: Draft revision number changedSections: type: array items: type: string description: List of config sections that changed in this revision editorName: type: string nullable: true description: Display name of the editor editorId: type: string nullable: true description: User ID of the editor timestamp: type: string format: date-time description: When the edit was made CreateDraftRequest: type: object properties: sourceVersionId: type: string pattern: "^[a-f\\d]{24}$" description: ID of a published version to branch from sourceDraftId: type: string description: ID of an existing draft to branch from draftName: type: string maxLength: 100 description: Optional name for the draft PublishDraftRequest: type: object properties: label: type: string nullable: true maxLength: 200 description: Label for the published version description: type: string nullable: true maxLength: 2000 description: Description of the published version activate: type: boolean description: Whether to immediately activate the version after publishing default: false UpdateVersionMetaRequest: type: object description: At least one of label, description, or isPinned must be provided. properties: label: type: string nullable: true maxLength: 200 description: Version label description: type: string nullable: true maxLength: 2000 description: Version description isPinned: type: boolean description: Pin or unpin the version TestCallRequest: type: object properties: mode: type: string enum: [webcall, chat, telephony] default: webcall description: Test call mode toPhone: type: string description: Phone number for telephony mode WebhookAgent: type: object properties: _id: type: string description: The ID of the agent name: type: string description: The name of the agent description: type: string description: The description of the agent WebhookSubscriptionPopulated: type: object properties: _id: type: string description: The unique identifier for the subscription webhookId: type: string description: The ID of the webhook agentId: $ref: "#/components/schemas/WebhookAgent" nullable: true description: The populated agent details, or null if not assigned eventType: type: string enum: [pre-conversation, post-conversation, analytics-completed] description: The type of event subscribed to createdAt: type: string format: date-time description: The date and time when the subscription was created updatedAt: type: string format: date-time description: The date and time when the subscription was last updated Webhook: type: object properties: _id: type: string description: The unique identifier for the webhook url: type: string description: The webhook endpoint URL description: type: string description: The description of the webhook status: type: string enum: [enabled, disabled] description: The status of the webhook organizationId: type: string description: The organization ID createdBy: type: string description: The user ID who created the webhook subscriptions: type: array items: $ref: "#/components/schemas/WebhookSubscriptionPopulated" description: A list of subscriptions for the webhook with populated agent details. decryptedSecretKey: type: string description: The decrypted signing secret for the webhook. This is only returned when fetching a single webhook by ID. createdAt: type: string format: date-time description: The date and time when the webhook was created updatedAt: type: string format: date-time description: The date and time when the webhook was last updated WebhookSubscription: type: object properties: _id: type: string description: The unique identifier for the subscription webhookId: type: string description: The ID of the webhook agentId: type: string description: The ID of the agent eventType: type: string enum: [pre-conversation, post-conversation, analytics-completed] description: The type of event subscribed to createdAt: type: string format: date-time description: The date and time when the subscription was created updatedAt: type: string format: date-time description: The date and time when the subscription was last updated WebhookEventEnvelope: type: object description: | Common envelope shared by every webhook event Atoms delivers to your endpoint. The `metadata` field's shape varies by event type — see the per-event schemas (`WebhookEventPreConversation`, `WebhookEventPostConversation`, `WebhookEventAnalyticsCompleted`). properties: url: type: string description: The webhook URL endpoint that received the event. example: "https://example.com/webhook" description: type: string description: Human-readable label configured on the webhook (e.g. "Debt Collection Agent's Endpoint"). event: type: string description: "Event identifier in the form `{agentId}.{eventType}`." example: "69fc7dd072a0c1d28d948ace.post-conversation" id: type: string description: Unique webhook delivery ID (separate from `metadata.callId`). example: "69fd96118fd277fc807e4c23" required: - url - description - event - id WebhookEventPreConversation: type: object description: | Fired **before** the agent begins speaking. Use this to enrich CRM data, log call attempts, or gate outbound calls. Does **not** contain `callData`, `transcript`, `variables`, `analytics`, or `recordingUrl`. `callData` is on `post-conversation` and `analytics-completed`; `transcript`, `variables`, and `recordingUrl` are only on `post-conversation`; `analytics` is only on `analytics-completed`. allOf: - $ref: "#/components/schemas/WebhookEventEnvelope" - type: object required: [metadata] properties: metadata: type: object required: [agentId, eventType, conversationType, toPhone, fromPhone, callId] properties: agentId: type: string description: The Atoms agent ID that handled the call. example: "69fc7dd072a0c1d28d948ace" eventType: type: string enum: [pre-conversation] example: "pre-conversation" conversationType: type: string description: "Channel type. Known values: `telephonyOutbound`, `telephonyInbound`." example: "telephonyOutbound" toPhone: type: string description: Destination phone number in E.164 format. example: "+916296641821" fromPhone: type: string description: Originating phone number in E.164 format. example: "+918035317096" callId: type: string description: Unique call identifier. example: "CALL-1778226705739-7e4c17" WebhookEventTranscriptTurn: type: object description: One speaking turn in a `post-conversation` transcript. properties: role: type: string enum: [agent, user] description: Speaker role. content: type: string description: The spoken text for this turn. timestamp: type: string format: date-time description: ISO 8601 timestamp of when this turn began (UTC). required: [role, content, timestamp] WebhookEventCallData: type: object description: | Call-level metadata shared by `post-conversation` and `analytics-completed` events. In `analytics-completed`, the `callDirection` field may be absent. properties: fromNumber: type: string description: Originating phone number in E.164 format. example: "+918035317096" toNumber: type: string description: Destination phone number in E.164 format. example: "+916296641821" callDuration: type: number format: float description: Total call duration in **seconds** (float). example: 49.350622 callStatus: type: string enum: [completed, no_answer, failed, cancelled] description: Terminal status. callDirection: type: string enum: [telephony_outbound, telephony_inbound] description: | Call direction. Present on `post-conversation`; may be absent on `analytics-completed`. answerTime: type: string format: date-time description: ISO 8601 timestamp when the call was answered (UTC). endTime: type: string format: date-time description: ISO 8601 timestamp when the call ended (UTC). required: [fromNumber, toNumber, callDuration, callStatus, answerTime, endTime] WebhookEventPostConversation: type: object description: | Fired **after** the call ends. Contains the full transcript, call metadata, recording URL, and all agent variables that were in scope during the conversation. allOf: - $ref: "#/components/schemas/WebhookEventEnvelope" - type: object required: [metadata] properties: metadata: type: object required: [agentId, eventType, conversationType, callId, recordingUrl, callData, transcript, variables] properties: agentId: type: string example: "69fc7dd072a0c1d28d948ace" eventType: type: string enum: [post-conversation] example: "post-conversation" conversationType: type: string example: "telephonyOutbound" callId: type: string example: "CALL-1778226705739-7e4c17" recordingUrl: type: string format: uri description: URL to the composite call recording (`.wav`). callData: $ref: "#/components/schemas/WebhookEventCallData" transcript: type: array description: Ordered list of transcript turns. items: $ref: "#/components/schemas/WebhookEventTranscriptTurn" variables: type: object additionalProperties: true description: | Flat key-value map of all agent variables in scope during the call. **This object is fully dynamic.** Keys and values are entirely determined by the agent's configuration; they are not fixed by the platform. New keys can appear at any time. Store as JSON and iterate keys — do not hard-code column mappings. Common platform keys include `agent_name`, `customer_name`, `current_date`, `default_language`; domain-specific keys (e.g. `due_amount`, `bank_name`) come from your agent's prompt configuration. example: agent_name: "Nisha" customer_name: "Rahul Sharma" due_amount: "29000" WebhookEventAnalyticsMetric: type: object description: | A single disposition or success metric computed by the `analytics-completed` event. The set of metrics is configured per-agent and can vary. properties: identifier: type: string description: "Machine-readable metric name (e.g. `turn_taking_balance`, `escalation_needed`)." example: "turn_taking_balance" value: description: | The evaluated result. Type depends on `dispositionMetricType`. oneOf: - type: integer - type: string - type: boolean confidence: type: number format: float minimum: 0 maximum: 1 description: Confidence score (0–1). example: 1 reasoning: type: string description: LLM-generated explanation for the assigned value. dispositionMetricPrompt: type: string description: The prompt/question that was used to evaluate this metric. dispositionMetricType: type: string enum: [STRING, BOOLEAN, INTEGER, ENUM, DATETIME] description: Data type of `value`. required: [identifier, value, confidence, reasoning, dispositionMetricPrompt, dispositionMetricType] WebhookEventAnalyticsCompleted: type: object description: | Fired **after** Atoms finishes running the configured disposition and success metrics on the transcript. Arrives some time after `post-conversation`. allOf: - $ref: "#/components/schemas/WebhookEventEnvelope" - type: object required: [metadata] properties: metadata: type: object required: [agentId, eventType, conversationType, callId, analytics, callData] properties: agentId: type: string eventType: type: string enum: [analytics-completed] example: "analytics-completed" conversationType: type: string callId: type: string analytics: type: object required: [summary, dispositionMetrics, successMetrics] properties: summary: type: string description: LLM-generated plain-text summary of the call. dispositionMetrics: type: array items: $ref: "#/components/schemas/WebhookEventAnalyticsMetric" successMetrics: type: array description: Same schema as `dispositionMetrics`. May be empty. items: $ref: "#/components/schemas/WebhookEventAnalyticsMetric" callData: $ref: "#/components/schemas/WebhookEventCallData" KnowledgeBase: type: object properties: _id: type: string description: The unique identifier for the knowledge base name: type: string description: The name of the knowledge base description: type: string description: The description of the knowledge base organization: type: string description: The organization ID createdBy: type: string description: The user ID who created the knowledge base processingStatus: type: string enum: [pending, processing, completed, failed] description: The current processing status of the knowledge base createdAt: type: string format: date-time description: The date and time when the knowledge base was created updatedAt: type: string format: date-time description: The date and time when the knowledge base was last updated required: - _id - name - organization - createdBy KnowledgeBaseItem: type: object properties: _id: type: string description: The unique identifier for the knowledge base item itemType: type: string enum: [file, text] description: The type of the knowledge base item metadata: type: object description: Additional metadata for the item knowledgeBaseId: type: string description: The ID of the knowledge base this item belongs to processingStatus: type: string enum: [pending, processing, completed, failed] description: The processing status of the item fileName: type: string description: The name of the file (for file type items) contentType: type: string description: The MIME type of the content size: type: number description: The size of the file in bytes key: type: string description: The storage key for the file title: type: string description: The title of the item content: type: string description: The content of the item (for text type items) createdAt: type: string format: date-time description: The date and time when the item was created updatedAt: type: string format: date-time description: The date and time when the item was last updated required: - _id - itemType - knowledgeBaseId - processingStatus - createdAt - updatedAt WebhookEvent: type: object properties: _id: type: string description: The unique identifier for the event webhookId: type: string description: The ID of the webhook eventType: type: string description: The type of event payload: type: object description: The event payload status: type: string description: The status of the event createdAt: type: string format: date-time description: The date and time when the event was created WorkflowType: type: string enum: [workflow_graph, single_prompt] description: The type of workflow configuration. workflow_graph uses a node-based visual workflow, single_prompt uses a simple prompt-based configuration. WorkflowGraphData: type: object description: Workflow configuration using a node-based graph structure properties: nodes: type: array description: Array of workflow nodes items: type: object properties: id: type: string description: Unique identifier for the node type: type: string description: Type of the node (e.g., default_node, end_call, pre_call_api) position: type: object properties: x: type: number y: type: number data: type: object description: Node-specific data and configuration edges: type: array description: Array of workflow edges connecting nodes items: type: object properties: id: type: string description: Unique identifier for the edge source: type: string description: ID of the source node target: type: string description: ID of the target node type: type: string description: Type of the edge SinglePromptData: type: object description: Workflow configuration using a simple prompt-based approach properties: prompt: type: string description: The main prompt that defines the agent's behavior and responses tools: type: array description: Array of tools/functions available to the agent items: type: object description: Tool configuration object SinglePromptConfig: type: object description: Configuration for single prompt workflow type properties: prompt: type: string description: The main prompt that defines the agent's behavior and responses example: "You are a helpful AI assistant that can help users with various tasks." tools: type: array description: | Array of tools/functions available to the agent during conversations. Five tool types are supported: `end_call`, `transfer_call`, `api_call`, `extract_dynamic_variables`, and `knowledge_base_search`. Each type has its own required fields — see `Tool` schema. items: $ref: "#/components/schemas/Tool" default: [] required: [prompt] Tool: type: object description: | Tool (function) available to the agent. The `type` field determines which additional fields are required. Backend validation enforces per-type schemas. required: [type, name, description] properties: type: type: string enum: [end_call, transfer_call, api_call, extract_dynamic_variables, knowledge_base_search] description: The type of function/tool name: type: string description: Unique name for the function (no spaces) example: "end_call" description: type: string description: Description of what the function does example: "End the conversation when the user is satisfied" enabled: type: boolean default: true description: Whether the tool is enabled # ── Transfer Call specific fields ── transferNumber: type: string description: "Required for transfer_call type. Phone number to transfer the call to (E.164 format)" example: "+1234567890" transferOption: type: object description: "Required for transfer_call type. Controls cold vs warm transfer behavior." properties: type: type: string enum: [cold_transfer, warm_transfer] default: cold_transfer description: Transfer mode. `cold_transfer` hands off immediately; `warm_transfer` briefs the receiving party first. privateHandoffOption: type: object nullable: true description: Private briefing delivered to the transfer target before the caller is connected. Only used when `type = warm_transfer`. properties: type: type: string enum: [prompt, static] description: "`prompt` generates briefing from the LLM; `static` plays fixed text." prompt: type: string description: The prompt or static text for the private handoff. publicHandoffOption: type: object nullable: true description: Message played to the caller while the transfer is being set up. Only used when `type = warm_transfer`. properties: type: type: string enum: [prompt, static] prompt: type: string onHoldMusic: type: string enum: [ringtone, relaxing_sound, uplifting_beats, none] default: ringtone description: "Optional for transfer_call type. Audio played to the caller while the transfer is in progress." transferOnlyIfHuman: type: boolean default: true description: "Optional for transfer_call type. If true, the call is only transferred when a human is detected on the receiving end (voicemail/IVR skipped)." detectionTimeout: type: integer minimum: 5 maximum: 60 default: 30 description: "Optional for transfer_call type. Seconds to wait for human detection before giving up (5–60)." # ── API Call specific fields ── url: type: string format: uri description: "Required for api_call type. The URL to make the HTTP request to." example: "https://api.example.com/orders" method: type: string enum: [GET, POST, PUT, DELETE, PATCH] description: "Required for api_call type. HTTP method to use." example: "GET" timeout: type: integer minimum: 1000 maximum: 30000 default: 5000 description: "Optional for api_call type. Request timeout in milliseconds (1000–30000)." headers: type: object additionalProperties: type: string description: "Optional for api_call type. Static HTTP headers as a key/value map." example: Authorization: "Bearer TOKEN" Content-Type: "application/json" headersArray: type: array description: "Optional for api_call type. Headers as an array of key/value objects (alternative to `headers` map)." items: type: object required: [key, value] properties: key: type: string example: "Authorization" value: type: string example: "Bearer TOKEN" queryParams: type: array description: "Optional for api_call type. Query parameters to include in the request URL. Values support variable templating like `{{order_id}}`." items: type: object required: [key, value] properties: key: type: string example: "id" value: type: string example: "{{order_id}}" requestBody: type: string description: "Optional for api_call type. Raw request body as a JSON string. Supports variable templating." example: '{"customer_id": "{{customer_id}}"}' llmParameters: type: array description: "Optional for api_call type. Parameters the LLM can supply dynamically at runtime." items: type: object required: [name, description, type] properties: name: type: string description: Parameter name description: type: string description: What the parameter represents type: type: string enum: [text, number, boolean, enum] values: type: array items: type: string description: "Required when type is `enum`. Allowed values." required: type: boolean default: false responseVariables: type: array description: "Optional for api_call type. Variables to extract from the API response into the agent's variable store." items: type: object required: [variableName, jsonPath] properties: variableName: type: string description: Name to store the extracted value under example: "orderStatus" jsonPath: type: string description: JSON path to extract the value from the response example: "$.data.status" default: [] # ── Dynamic Variable Extraction specific fields ── variablesExtractionSchema: type: array description: "Required for extract_dynamic_variables type. Schema defining variables to extract from the conversation." items: type: object required: [name, description, type] properties: name: type: string description: Name of the variable to extract example: "customer_name" description: type: string description: What this variable represents example: "The customer's full name" type: type: string enum: [text, number, boolean, enum] values: type: array items: type: string description: "Required when type is `enum`. List of possible values." example: ["satisfied", "unsatisfied", "neutral"] minItems: 1 # ── Knowledge Base Search specific fields ── knowledgeBaseId: type: string description: "Required for knowledge_base_search type. ID of the knowledge base to search." example: "60d0fe4f5311236168a109ca" fillerPhrases: type: array description: "Optional for knowledge_base_search type. Phrases spoken while searching." items: type: string default: [] example: ["Let me check that for you", "One moment please"] DispositionMetric: type: object description: | A single disposition metric captured after each call. The metric prompt is evaluated against the call transcript post-call, and the result is returned in the call log under `postCallAnalytics.dispositionMetrics`. required: [identifier, dispositionMetricPrompt, dispositionMetricType] properties: identifier: type: string pattern: "^[a-z0-9_]+$" description: Stable machine identifier. Lowercase letters, digits, and underscores only. example: "call_resolved" dispositionMetricPrompt: type: string description: Natural-language question evaluated against the transcript after the call ends. example: "Was the customer issue resolved by the end of the call?" dispositionMetricType: type: string enum: [STRING, BOOLEAN, INTEGER, ENUM, DATETIME] description: Data type returned by the metric. example: "STRING" choices: type: array description: "Required when `dispositionMetricType = ENUM`. Allowed values." items: type: string example: ["resolved", "escalated", "callback_scheduled", "no_action"] PostCallAnalyticsConfig: type: object description: | Per-agent post-call analytics configuration. Evaluated after each call ends and surfaced in call logs under the `postCallAnalytics` field. properties: dispositionMetrics: type: array description: Structured metrics extracted from each completed call. items: $ref: "#/components/schemas/DispositionMetric" default: [] successMetrics: type: array deprecated: true description: | **Deprecated** — will be removed in a future version. Use `dispositionMetrics` instead. Kept here because the backend still accepts it on writes and returns it on reads. items: type: object required: [identifier, successMetricPrompt, successMetricType] properties: identifier: type: string pattern: "^[a-z0-9_]+$" successMetricPrompt: type: string successMetricType: type: string enum: [NUMERIC_SCALE, PERCENTAGE_SCALE, PASS_FAIL, DESCRIPTIVE_SCALE] default: [] summaryPrompt: type: string deprecated: true description: | **Deprecated** — no longer used in post-call analysis and will be removed in a future version. Kept here because the backend still accepts it on writes and returns it on reads. default: "" useInternalAnalyticsModel: type: boolean default: true description: Use the internal analytics model. When false, falls back to the agent's own LLM. useReasoningModel: type: boolean default: false description: Route analytics evaluation through the reasoning model for higher-quality results at a latency/cost tradeoff. ComplianceApplication: type: object description: A compliance application for a specific country, number type, and user type properties: _id: type: string description: Unique identifier example: "663f1a2b4c5d6e7f8a9b0c1d" organizationId: type: string description: The organization this application belongs to plivoComplianceId: type: string description: Plivo's compliance application identifier alias: type: string description: Auto-generated alias (orgId-countryIso-env) example: "663f1a2b-IN-production" status: type: string enum: [draft, submitted, accepted, rejected, suspended, expired] description: Current status of the compliance application example: "submitted" countryIso: type: string description: ISO 3166-1 alpha-2 country code example: "IN" numberType: type: string enum: [local, mobile, tollfree] example: "local" userType: type: string enum: [individual, business] example: "business" endUserName: type: string description: Legal business or individual name example: "Acme Corp" endUserLastName: type: string nullable: true endUserEmail: type: string nullable: true endUserCountry: type: string nullable: true example: "IN" documentFileNames: type: array items: type: string description: Names of uploaded document files example: ["certificate_of_incorporation.pdf"] rejectionReason: type: string nullable: true description: Reason for rejection, if applicable createdBy: type: string description: User ID of the person who created this application createdAt: type: string format: date-time updatedAt: type: string format: date-time ComplianceRequirement: type: object description: Compliance requirements for a country/numberType/userType combination properties: requirementId: type: string description: Plivo's requirement identifier countryIso: type: string example: "IN" numberType: type: string example: "local" userType: type: string example: "business" documentTypes: type: array description: Required document types. Empty array means no compliance is needed. items: $ref: "#/components/schemas/RequiredDocumentType" RequiredDocumentType: type: object description: A document type required for compliance properties: documentTypeId: type: string description: Identifier to use when submitting this document type example: "dt_certificate_of_incorporation" name: type: string description: Human-readable name example: "Certificate of Incorporation" description: type: string description: Description of what this document should contain example: "A government-issued certificate proving business registration" proofRequired: type: boolean description: Whether a file upload is required for this document type example: true requiredFields: type: array description: Data fields that must be provided alongside the document items: type: object properties: fieldName: type: string example: "business_name" friendlyName: type: string example: "Business Name" helpText: type: string example: "Exact name as on the certificate" fieldType: type: string example: "string" required: type: boolean example: true responses: UnauthorizedError: description: Access token is missing or invalid content: application/json: schema: $ref: "#/components/schemas/ApiResponse" BadRequestError: description: Invalid input content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" ForbiddenError: description: Forbidden access content: application/json: schema: $ref: "#/components/schemas/ApiResponse" UnauthorizedErrorResponse: description: Unauthorized access content: application/json: schema: $ref: "#/components/schemas/UnauthorizedErrorResponse" InternalServerErrorResponse: description: Internal server error content: application/json: schema: $ref: "#/components/schemas/InternalServerErrorResponse" tags: - name: Agent Templates description: Operations related to agent templates - name: Agents description: Operations related to agents # - name: Workflows # DEPRECATED — workflow agents are being sunset - name: Logs description: Operations related to conversation logs, call history, and recordings. Supports filtering by agents, campaigns, call IDs, status, duration, and more. - name: Calls description: Operations related to initiating and managing calls - name: Live Transcripts description: Real-time streaming of call transcript events via Server-Sent Events (SSE). Subscribe to an active call to receive user speech, agent speech, and lifecycle events in real time. - name: Phone Numbers description: Operations related to phone numbers - name: Compliance description: | Regulatory compliance for phone number rentals. Some countries require identity verification and document submission before numbers can be rented. Use these endpoints to check requirements, submit compliance applications, and track approval status. - name: Webhooks description: Operations related to webhooks and webhook subscriptions - name: Audience description: Operations related to audience management and CSV uploads - name: Agent Versioning - Drafts description: Operations for creating, editing, diffing, and publishing agent configuration drafts - name: Agent Versioning - Versions description: Operations for listing, comparing, activating, and testing published agent versions. Published versions (active or inactive) are config-immutable — only metadata (label, description, isPinned) can be updated. To change config, create a draft and publish a new version. - name: Post-Call Analytics description: | Configure disposition metrics that are automatically extracted from each completed call (call resolved, satisfaction score, call outcome, summary, etc.). Post-call analytics is not a standalone endpoint — it is configured through the versioning system by setting the `postCallAnalyticsConfig` field in the body of `PATCH /agent/{id}/drafts/{draftId}/config`, then publishing and activating the draft. See the [Post-Call Metrics guide](/atoms/atoms-platform/features/post-call-metrics) for the full walkthrough. servers: - url: https://api.smallest.ai/atoms/v1 description: Production server