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 x-fern-sdk-group-name: agent_templates x-fern-sdk-method-name: list_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: Stable unique identifier for the template (24-character hex string, e.g. `6942a64ac74fc65e7bc94e47`). Surfaced as `object_id` in the generated SDK to keep it distinct from the human-readable `id` slug. x-fern-property-name: object_id id: type: string description: Human-readable slug for the agent template (e.g. `sp-medical-centre-receptionist-in`). Distinct from `_id`. 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: _id: type: string description: Auto-generated unique identifier for the embedded single-prompt config (24-character hex string). Always present when `singlePromptConfig` is set. Surfaced as `object_id` in the generated SDK. x-fern-property-name: object_id prompt: type: string description: The system prompt used by the agent tools: type: array description: Tools available to the agent items: type: object properties: type: type: string description: The tool type — drives runtime dispatch. enum: - end_call - transfer_call - api_call - extract_dynamic_variables - knowledge_base_search 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: post: summary: Create a new agent x-fern-sdk-group-name: agents x-fern-sdk-method-name: create_agent tags: - Agents security: - BearerAuth: [] description: | Create a new agent by passing the agent name in the request body. New agents have versioning enabled by default. To set the prompt, `firstMessage`, tools, or any runtime config, fork a draft from the auto-created initial version, edit it, publish, and activate — see the [Versioning Lifecycle](/atoms/developer-guide/build/agents/versioning-lifecycle) guide for the full flow. The legacy `PATCH /workflow/{workflowId}` endpoint writes directly to the underlying workflow document and bypasses the version lifecycle; edits made that way are not captured as a version and may not propagate to live calls. Use the drafts flow above. 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" get: summary: Get all agents x-fern-sdk-group-name: agents x-fern-sdk-method-name: list_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" /agent/with-ai: post: operationId: createAgentWithAi summary: Create agent with AI x-fern-ignore: true description: | Creates a new agent using AI generation. Accepts either a guided questionnaire (array of Q&A pairs) or a free-text description. The AI generates the agent's prompt and configuration. A security check is run on the generated prompt before the agent is persisted. Deducts credits on success. **Rules:** - Either `questions` (non-empty array) or `description` must be provided — not both. - `emotiveToggle`, `voiceId`, and `voiceModel` must either all be present or all be absent. - When `emotiveToggle=true`, `voiceModel` must be `GPT_REALTIME`. - When `emotiveToggle=false`, `voiceModel` cannot be `GPT_REALTIME`. tags: - Agents security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object properties: name: type: string maxLength: 50 description: Agent name. Auto-generated if omitted. description: type: string maxLength: 15000 description: Free-text description. Required if `questions` not given. questions: type: array description: Guided Q&A pairs. Required if `description` not given. items: type: object required: [question, answer] properties: question: type: string minLength: 1 maxLength: 2000 answer: type: string minLength: 50 maxLength: 15000 type: type: string enum: [single_prompt] description: Workflow type. Only `single_prompt` is supported. emotiveToggle: type: boolean description: Enable emotive (GPT Realtime) mode. Must be given with `voiceId` and `voiceModel`. voiceId: type: string description: Voice ID. Must be given together with `emotiveToggle` and `voiceModel`. voiceModel: type: string description: Voice model. Must be given together with `emotiveToggle` and `voiceId`. knowledgeBaseId: type: string description: Knowledge base to attach (must belong to the organization). responses: "201": description: Agent created — returns the new agent's ObjectId content: application/json: schema: type: object properties: success: type: boolean example: true data: type: string description: MongoDB ObjectId of the created agent "400": description: Invalid request body, or the generated prompt failed the security check content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Organization lacks access to the requested workflow type or model (WORKFLOW_GRAPH, GPT 5.2, Electron Kogta) content: application/json: schema: $ref: "#/components/schemas/ApiResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" "503": description: Security check service temporarily unavailable content: application/json: schema: $ref: "#/components/schemas/ApiResponse" /agent/{id}/duplicate: post: summary: Duplicate agent to another organization x-fern-sdk-group-name: agents x-fern-sdk-method-name: duplicate_agent 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}: get: summary: Get agent by ID x-fern-sdk-group-name: agents x-fern-sdk-method-name: get_agent 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 minLength: 1 description: | Agent identifier (Mongo ObjectId string). Must be non-empty. An empty `id` would resolve to `GET /agent/`, which is the list endpoint — Fern adds the `minLength: 1` guard so the generated SDK raises locally rather than silently calling the wrong route. - 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 x-fern-sdk-group-name: agents x-fern-sdk-method-name: update_agent 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 a cross-field constraint is violated** (for example, `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/prompt-config: get: operationId: getAgentPromptConfig summary: Get AI creation questionnaire config x-fern-ignore: true description: | Returns the questionnaire configuration used by the "Create with AI" flow — the list of guided questions, their types, available options, and pre-filled example answers per label. Only a user token is required; no organization auth needed. tags: - Agents security: - BearerAuth: [] responses: "200": description: Questionnaire configuration content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: questions: type: array description: Ordered list of questions shown in the agent creation wizard items: type: object properties: text: type: string type: type: string description: "Question input type (e.g. `text`, `select`)" options: type: array items: type: string examples: type: object description: Pre-filled sample answers keyed by label. `"default"` is always present. additionalProperties: type: string exampleLabels: type: array description: Labels other than `"default"` that example answer sets exist for items: type: string defaultLabel: type: string example: default "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/widget-config: get: operationId: getAgentWidgetConfig summary: Get widget configuration description: Returns the current web widget configuration for the agent. Also includes `assistantId` (same as the agent ID) as a convenience field for the widget embed code. tags: - Agents security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: Agent ObjectId responses: "200": description: Widget configuration content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object description: All fields may be absent if not yet configured properties: assistantId: type: string description: Same as the agent ID — convenience field for the widget embed code position: type: string enum: [bottom-right, bottom-left, top-right, top-left] size: type: string enum: [tiny, compact, full] borderRadius: type: number mode: type: string enum: [chat, voice] theme: type: string enum: [light, dark] baseColor: type: string accentColor: type: string title: type: string startButtonText: type: string endButtonText: type: string avatarUrl: type: string nullable: true voiceShowTranscript: type: boolean consentRequired: type: boolean "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Agent not found "500": $ref: "#/components/responses/InternalServerErrorResponse" patch: operationId: updateAgentWidgetConfig summary: Update widget configuration description: | Updates the web widget configuration for the agent. Only provided fields are updated (partial update). When `avatarUrl` is changed, the old CDN avatar is automatically deleted from S3. The `avatarUrl` must be a URL from the platform's CDN domain — use `POST /agent/{id}/avatar/presigned-url` to upload first. tags: - Agents security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: Agent ObjectId requestBody: required: true content: application/json: schema: type: object properties: widgetConfig: type: object description: All fields are optional — only provided fields are updated properties: position: type: string enum: [bottom-right, bottom-left, top-right, top-left] size: type: string enum: [tiny, compact, full] borderRadius: type: number minimum: 0 maximum: 50 mode: type: string enum: [chat, voice] theme: type: string enum: [light, dark] baseColor: type: string accentColor: type: string agentBubbleColor: type: string textOnAccentColor: type: string secondaryTextColor: type: string primaryTextColor: type: string title: type: string startButtonText: type: string endButtonText: type: string ctaTitle: type: string nullable: true ctaSubtitle: type: string nullable: true ctaName: type: string nullable: true widgetName: type: string nullable: true avatarUrl: type: string nullable: true description: Must be a platform CDN URL. Use `POST /agent/{id}/avatar/presigned-url` to obtain one. voiceEmptyMessage: type: string nullable: true voiceActiveEmptyMessage: type: string nullable: true chatEmptyMessage: type: string nullable: true chatFirstMessage: type: string nullable: true chatPlaceholder: type: string voiceShowTranscript: type: boolean consentRequired: type: boolean consentTitle: type: string consentContent: type: string consentStorageKey: type: string nullable: true publicKey: type: string allowlist: type: array items: type: string responses: "200": description: Updated widget configuration content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object description: The updated widgetConfig object "400": description: Invalid agent ID or `avatarUrl` is not a valid CDN URL content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Agent not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/avatar/presigned-url: post: operationId: getAgentAvatarPresignedUrl summary: Get avatar upload URL description: | Generates a pre-signed S3 upload URL for the agent's widget avatar image. Upload the image directly to S3 using the returned `presignedUrl`, then save `cdnUrl` as the agent's avatar via `PATCH /agent/{id}/widget-config`. tags: - Agents security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: Agent ObjectId requestBody: required: true content: application/json: schema: type: object required: [fileName, contentType, fileSize] properties: fileName: type: string description: Original file name (used to construct the S3 key) contentType: type: string description: "MIME type — must start with `image/`" fileSize: type: number description: File size in bytes — must be > 0 and ≤ 2 MB (2,097,152 bytes) responses: "200": description: Pre-signed upload URL and CDN URL content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: presignedUrl: type: string description: S3 pre-signed PUT URL (expires in 300 s) cdnUrl: type: string description: Final public CDN URL to save on the agent after upload key: type: string description: S3 object key "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Agent not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/workflow: get: x-fern-ignore: true summary: Get agent workflow deprecated: true x-fern-availability: deprecated 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: x-fern-ignore: true summary: Update workflow configuration deprecated: true x-fern-availability: deprecated x-fern-sdk-group-name: agents x-fern-sdk-method-name: update_workflow_configuration 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" /agent/{id}/call-logs: get: operationId: getAgentCallLogs summary: Get agent call logs description: Returns paginated call logs for a specific agent. tags: - Agents security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: Agent ObjectId - name: page in: query schema: type: integer default: 1 description: Page number (default 1) - name: offset in: query schema: type: integer default: 10 description: Records per page (default 10) responses: "200": description: Paginated call logs content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: callLogs: type: array items: type: object properties: callId: type: string callStatus: type: string callType: type: string fromNumber: type: string toNumber: type: string createdAt: type: string format: date-time callDuration: type: number description: Call duration in milliseconds totalCount: type: number page: type: number offset: type: number "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/archive: delete: operationId: deleteAgent summary: Archive or unarchive an agent x-fern-sdk-group-name: agents x-fern-sdk-method-name: archive_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" /conversation/register-call: post: summary: Register a realtime agent call x-fern-sdk-group-name: realtime x-fern-sdk-method-name: register_call description: | Mint a **short-lived, single-use access token** for opening a realtime [Agent WebSocket](/atoms/api-reference/realtime-agent/realtime-agent) connection. This is the **recommended** way to start a session from a browser or other client-side app: your API key stays server-side, and the browser only ever sees the short-lived token. (Server-side or trusted clients may instead connect to the WebSocket with a raw API key directly.) Flow: 1. Call this endpoint with your API key and the `agent_id` (plus optional `mode` and per-call `variables`). All session configuration is fixed here — it is baked into the returned token. 2. Open a WebSocket to `wss://api.smallest.ai/atoms/v1/agent/connect?token=`. No `agent_id`, `mode`, or `variables` query params are needed on the WebSocket — they come from the token. The token is valid for `expires_in` seconds (30) and can be used for a single connection. Request a fresh token for each connection. tags: - Realtime Agent security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [agent_id] properties: agent_id: type: string description: The Atoms agent to connect to. example: "69da0b4c20c0e03cfa4ee258" mode: type: string enum: [webcall, chat] default: webcall description: | Session mode. `webcall` = full voice pipeline (audio in + audio out). `chat` = text-only pipeline. Defaults to `webcall`. variables: type: object additionalProperties: oneOf: - type: string - type: number - type: boolean description: | Per-call prompt variables that override the agent's `defaultVariables` for this session only. Values must be `string`, `number`, or `boolean`. Reserved system-variable keys (`call_id`, `conversation_type`, `agent_number`, `user_number`, `current_date`, `current_time`, `current_day`, `agent_gender`, `default_language`, `supported_languages`, `timezone`) are populated by the server and stripped if supplied. example: customer_name: "Tanay" account_tier: "gold" responses: "201": description: Access token created. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: access_token: type: string description: | Short-lived, single-use token (prefixed `wct_`). Pass it as the `token` query param when opening the Agent WebSocket. example: "wct_9f8c2b1e-4d5a-4e6f-a7b8-c9d0e1f2a3b4" expires_in: type: integer description: Token lifetime in seconds. example: 30 sample_rate: type: integer description: | Negotiated audio sample rate (Hz) for the session. Echoed back in the WebSocket `session.created` event. example: 24000 "400": description: | Validation failed (e.g. missing `agent_id`), or the organization has no remaining credits. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation: get: summary: Get all conversation logs x-fern-sdk-group-name: calls x-fern-sdk-method-name: list 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 minLatency: type: number description: Minimum turn latency in milliseconds maxLatency: type: number description: Maximum 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 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. 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 x-fern-sdk-group-name: calls x-fern-sdk-method-name: search 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 minLatency: type: number maxLatency: type: number turns: type: number latencies: type: array items: type: number transitions: type: array items: type: object properties: turn: type: number user_end: type: number bot_start: type: number latency: type: number processedAt: type: string format: date-time 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 x-fern-sdk-group-name: calls x-fern-sdk-method-name: get 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: string description: ISO-8601 timestamp of the turn (e.g. 2026-07-28T15:46:12.472Z) 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/{callId}/recording/download-url: get: summary: Get a time-limited recording download URL description: | Returns a presigned S3 URL for the call's recording. Hand the URL straight to the customer or pull bytes server-side. The presigned URL is **time-limited** — typically usable for a few minutes — so don't cache it; request a fresh one each time you need the recording. Returns `404` if the call has no recording (call hasn't started, was cancelled before audio captured, or was deleted by the platform's retention policy). Returns `400 Invalid call ID format` if you pass a Mongo `_id` instead of the `callId` string. tags: - Conversations security: - BearerAuth: [] parameters: - in: path name: callId required: true schema: type: string example: CALL-1781127346211-e765f7 description: The `callId` string for the conversation (e.g. `CALL-1778226705739-7e4c17`). This is the `callId` field returned by `GET /conversation`, **not** the Mongo `_id` — passing `_id` returns `400 Invalid call ID format`. responses: "200": description: Successful response — presigned URL ready to fetch. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: presignedUrl: type: string format: uri description: Time-limited HTTPS URL pointing at the recording in S3. The URL expires after a short window; request a fresh one if needed. "400": description: Invalid call ID format. "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: No recording found for this call. "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation/{callId}/retries: get: summary: List retry attempts for a call x-fern-sdk-group-name: conversations x-fern-sdk-method-name: list_retry_attempts description: | Returns the **parent call** plus every retry attempt that branched from it, ordered by attempt index. Use this when a customer asks "did the platform retry this call?" — typically driven by an outbound agent's auto-retry configuration (`maxRetries`, `retryDelay`). - If the `callId` you pass is the original (parent), the response contains that parent plus all child retries. - If the `callId` you pass is itself a retry, the response still includes the parent and every sibling retry — the API resolves to the family root automatically. Returns `404` if no call exists with that ID in your organization. tags: - Conversations security: - BearerAuth: [] parameters: - in: path name: callId required: true schema: type: string description: Any `callId` in the retry family (parent or any retry). responses: "200": description: Successful response — full retry family. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: retries: type: array description: All calls in the retry family — parent first, then retries in attempt order. Each entry has the same shape as a single call log returned by `GET /conversation`. items: type: object description: A call log entry. Mirrors the per-row shape in `GET /conversation`. "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Access denied — the call belongs to a different organization. "404": description: No call exists with that ID. "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation/cancel: post: summary: Cancel an in-flight call x-fern-sdk-group-name: conversations x-fern-sdk-method-name: cancel description: | Cancels an outbound call that has been queued or is in progress. Use the body form to look the call up by `callId`; the path-param form (`POST /conversation/{callId}/cancel`) is the equivalent for REST conventions, but only handles `IN_QUEUE` calls. Returns `404` if no call with that ID exists in your organization. Returns `400` if the call is already in a terminal state (completed / failed / cancelled). tags: - Conversations security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [callId] properties: callId: type: string description: The `callId` returned by `POST /conversation/outbound` or visible in `GET /conversation`. example: "CALL-1778226705739-7e4c17" reason: type: string description: Optional free-text reason for cancellation. Logged for support / audit. responses: "200": description: Call cancelled. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: callId: type: string status: type: string example: "cancelled" previousStatus: type: string description: The call's status immediately before cancellation (e.g. `queued`, `ringing`, `in-progress`). "400": description: Call is already in a terminal state and cannot be cancelled. "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: No call found with that callId in your organization. "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation/{callId}/cancel: post: summary: Cancel a queued call (path-param form) x-fern-sdk-group-name: conversations x-fern-sdk-method-name: cancel_queued description: | REST-conventional path-param variant of [`POST /conversation/cancel`](#operation/cancelCallByBody). **Behavior differs from the body form.** This path-param endpoint only cancels calls that are still in the `IN_QUEUE` state — calls that have already started dialing or are in progress return `400 Bad Request` with `errors: ["Conversation with ID ... is not in queue and cannot be cancelled"]`. Use the body form (`POST /conversation/cancel`) if you need to cancel an in-progress call. The path param is the `callId` string (e.g. `CALL-1778226705739-7e4c17`), **not** the Mongo `_id`. Passing `_id` returns `404 No conversation found`. tags: - Conversations security: - BearerAuth: [] parameters: - in: path name: callId required: true schema: type: string example: CALL-1781127346211-e765f7 description: The `callId` string for the conversation to cancel. responses: "200": description: Call cancelled. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: callId: type: string status: type: string example: "cancelled" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: No call found with that callId in your organization. "500": $ref: "#/components/responses/InternalServerErrorResponse" /conversation/outbound: post: summary: Start an outbound call x-fern-sdk-group-name: calls x-fern-sdk-method-name: start_outbound_call description: | Initiates an outbound telephony call with a specified agent and phone number. ## Caller-ID resolution When `fromProductId` is omitted **and** the agent has no telephony product attached, the call dispatches from a Smallest-managed Plivo trunk using a default caller-ID number (chosen by destination country). The call still places and the response is still `200 + conversationId`, but the recipient sees the default Smallest number rather than your own. For production traffic, either: - pass `fromProductId` explicitly (look up your owned numbers via `GET /product/phone-numbers`), or - attach a phone-number product to the agent. ## Resolved-config check The call uses the agent's currently-active version. If your most recent prompt change went through `PATCH /workflow/{workflowId}` and the agent has versioning enabled, that change may not have propagated to the active version — and the call will play the platform-default greeting instead of your prompt. Before placing a production call, fetch `GET /agent/{agentId}` and confirm `_resolvedConfig.firstMessage` (and related fields) match what you intended. The [Versioning Lifecycle](/atoms/developer-guide/build/agents/versioning-lifecycle) guide covers the correct edit flow. **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) x-fern-sdk-group-name: live_transcripts x-fern-sdk-method-name: subscribe_to_live_events 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. `tool_call_start`, `pre_call_api`, `agent_log`, metrics) are also sent on this stream. - `call_start` - `call_end` - `turn_latency` - `metrics` - `agent_node_state` - `hopping` - `knowledgebase` - `variable_extraction` - `pre_call_api` - `post_call_api` - `agent_error` - `agent_log` - `tool_call_start` - `tool_call_end` - `tool_call_error` - `call_cancelled` - `call_recording` tags: - Live Transcripts security: - BearerAuth: [] parameters: - name: X-Organization-Id in: header required: false description: Required when using session-cookie auth. API-token auth may infer the organization from the token. schema: type: string - name: callId in: query required: true description: The call ID to subscribe events for. Missing or invalid values return 400. schema: type: string example: "CALL-1758124225863-80752e" x-codeSamples: - lang: Python label: Python requests stream source: | import requests url = "https://api.smallest.ai/atoms/v1/events" headers = { "Authorization": "Bearer YOUR_API_KEY", "Accept": "text/event-stream", } params = {"callId": "CALL-1758124225863-80752e"} with requests.get(url, headers=headers, params=params, stream=True) as response: response.raise_for_status() for line in response.iter_lines(decode_unicode=True): if line: print(line) - lang: JavaScript label: JavaScript fetch stream source: | const response = await fetch( "https://api.smallest.ai/atoms/v1/events?callId=CALL-1758124225863-80752e", { headers: { Authorization: "Bearer YOUR_API_KEY", Accept: "text/event-stream", }, }, ); if (!response.ok) { throw new Error(`SSE request failed: ${response.status}`); } const reader = response.body.getReader(); const decoder = new TextDecoder(); while (true) { const { value, done } = await reader.read(); if (done) break; console.log(decoder.decode(value, { stream: true })); } // Browser EventSource cannot set custom Authorization headers directly. - lang: Go label: Go stream reader source: | req, err := http.NewRequest("GET", "https://api.smallest.ai/atoms/v1/events?callId=CALL-1758124225863-80752e", nil) if err != nil { panic(err) } req.Header.Set("Authorization", "Bearer YOUR_API_KEY") req.Header.Set("Accept", "text/event-stream") resp, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer resp.Body.Close() scanner := bufio.NewScanner(resp.Body) for scanner.Scan() { line := scanner.Text() if line != "" { fmt.Println(line) } } - lang: Ruby label: Ruby line stream source: | require "net/http" require "uri" uri = URI("https://api.smallest.ai/atoms/v1/events?callId=CALL-1758124225863-80752e") request = Net::HTTP::Get.new(uri) request["Authorization"] = "Bearer YOUR_API_KEY" request["Accept"] = "text/event-stream" Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) do |response| response.read_body do |chunk| puts chunk end end end - lang: PHP label: PHP stream source: | $ch = curl_init("https://api.smallest.ai/atoms/v1/events?callId=CALL-1758124225863-80752e"); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer YOUR_API_KEY", "Accept: text/event-stream", ]); curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $chunk) { echo $chunk; return strlen($chunk); }); curl_exec($ch); curl_close($ch); responses: "200": description: SSE event stream established successfully content: text/event-stream: schema: type: object description: | Events are sent as `data: \n\n`. Forwarded runtime events commonly include `event_type`, `event_id`, `timestamp`, and `call_id`. `sse_init` and `sse_close` include `event_type` and `event_time`. properties: event_type: type: string description: The type of event enum: - sse_init - call_start - call_end - turn_latency - user_interim_transcription - user_transcription - tts_completed - metrics - agent_node_state - hopping - knowledgebase - variable_extraction - pre_call_api - post_call_api - agent_error - agent_log - tool_call_start - tool_call_end - tool_call_error - call_cancelled - call_recording - 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 event_time: type: string format: date-time description: Timestamp used by `sse_init` and `sse_close` telephony_id: type: string description: Telephony ID for `call_start` metadata: type: object additionalProperties: true description: Metadata for `call_end`, `agent_error`, or `agent_log` turn_latency: type: number description: Turn latency value for `turn_latency` stt_api_ms: type: number description: STT API latency in milliseconds for `turn_latency` stt_to_llm_ms: type: number description: STT-to-LLM latency in milliseconds for `turn_latency` smart_turn_ms: type: number description: Smart-turn latency in milliseconds for `turn_latency` llm_api_ms: type: number description: LLM API latency in milliseconds for `turn_latency` llm_to_tts_ms: type: number description: LLM-to-TTS latency in milliseconds for `turn_latency` tts_api_ms: type: number description: TTS API latency in milliseconds for `turn_latency` tts_to_audio_ms: type: number description: TTS-to-audio latency in milliseconds for `turn_latency` total_turn_ms: type: number description: Total turn latency in milliseconds for `turn_latency` turn_index: type: integer description: Turn index for `turn_latency` interrupted: type: boolean description: Whether the turn was interrupted for `turn_latency` smart_turn_enabled: type: boolean description: Whether smart turn was enabled for `turn_latency` 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`) metrics: type: array description: | Per-turn metrics payload for `metrics` events. Server emits an **array** of `{processor, model, value}` entries (one per pipeline stage), not a single object. The SDK previously dropped every `metrics` SSE event with a pydantic ValidationError when this was typed as an object (122 events on a 40s call); typing it as an array of objects fixes the decode. items: type: object properties: processor: type: string description: Pipeline stage that produced the metric (e.g. `pulse_stt`, `electron_llm`, `lightning_tts`). model: type: string description: Concrete model/version identifier within the processor (e.g. `pulse-large english_v4.1`). value: type: number description: Metric value — typically milliseconds for latency metrics. node_id: type: string description: Node ID for `agent_node_state` node_name: type: string description: Node name for `agent_node_state` node_type: type: string description: Node type for `agent_node_state` context: type: object additionalProperties: true description: Context payload for agent-node and tool-call events from_node_id: type: string description: Source node ID for `hopping` to_node_id: type: string description: Destination node ID for `hopping` knowledge_base_id: type: string description: Knowledge base ID for `knowledgebase` user_transcript: type: string description: User transcript for `knowledgebase` response: nullable: true description: Response payload for knowledgebase, API, or tool-call events latency: type: number description: Latency for `knowledgebase` or `variable_extraction` error: nullable: true description: Error payload for knowledgebase, variable extraction, API, tool, or agent error events variables: type: object additionalProperties: true description: Variables extracted by `variable_extraction` variable_extraction_prompt: type: string description: Prompt used for `variable_extraction` method: type: string description: HTTP method for `pre_call_api` or `post_call_api` headers: type: object additionalProperties: true description: Headers for `pre_call_api` or `post_call_api` body: nullable: true description: Body for `pre_call_api` or `post_call_api` timeout: type: number description: Timeout for `pre_call_api` or `post_call_api` extracted_variables: type: object additionalProperties: true description: Extracted variables for `pre_call_api` or `post_call_api` next_node_id: type: string description: Next node ID for `pre_call_api` or `post_call_api` success: type: boolean description: Success status for API and tool-call events turn_id: type: string description: Turn ID for tool-call events tool_call_id: type: string description: Tool call ID for tool-call events function_name: type: string description: Function name for tool-call events latency_ms: type: number description: Latency in milliseconds for `tool_call_end` recording_url: type: string description: Recording URL for `call_recording` status: type: string description: Recording status for `call_recording` examples: sse_init: summary: SSE connection initialized value: event_type: sse_init event_time: "2026-03-02T10:00:00.000Z" call_start: summary: Call started value: event_type: call_start event_id: evt_call_start timestamp: "2026-03-02T10:00:00.100Z" call_id: "CALL-1758124225863-80752e" telephony_id: tel_abc123 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?" tool_call_end: summary: Tool call completed value: event_type: tool_call_end event_id: evt_tool_end timestamp: "2026-03-02T10:00:04.100Z" call_id: "CALL-1758124225863-80752e" turn_id: turn_123 tool_call_id: tool_456 function_name: lookup_order latency_ms: 180 success: true response: status: found call_recording: summary: Recording available value: event_type: call_recording event_id: evt_recording timestamp: "2026-03-02T10:04:59.000Z" call_id: "CALL-1758124225863-80752e" recording_url: "https://example.com/recordings/CALL-1758124225863-80752e.wav" status: available sse_close: summary: Stream closed after call_end value: event_type: sse_close event_time: "2026-03-02T10:05:00.000Z" "400": description: Missing or invalid `callId`, missing or invalid organization header, or call is already completed. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "401": description: Missing or invalid bearer token or session. content: application/json: schema: $ref: "#/components/schemas/UnauthorizedErrorResponse" "403": description: User is not a member of the organization or does not have member access. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "404": description: Organization not found, call log not found, or agent not found/org mismatch. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": description: Internal server error. content: application/json: schema: $ref: "#/components/schemas/InternalServerErrorResponse" /campaign: get: summary: Retrieve all campaigns x-fern-sdk-group-name: campaigns x-fern-sdk-method-name: list 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 x-fern-sdk-group-name: campaigns x-fern-sdk-method-name: create 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 x-fern-sdk-group-name: campaigns x-fern-sdk-method-name: get 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 x-fern-sdk-group-name: campaigns x-fern-sdk-method-name: delete 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 x-fern-sdk-group-name: campaigns x-fern-sdk-method-name: start_or_resume 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 x-fern-sdk-group-name: campaigns x-fern-sdk-method-name: pause 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 x-fern-sdk-group-name: knowledge_base x-fern-sdk-method-name: list 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 x-fern-sdk-group-name: knowledge_base x-fern-sdk-method-name: create 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 x-fern-sdk-group-name: knowledge_base x-fern-sdk-method-name: get 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 x-fern-sdk-group-name: knowledge_base x-fern-sdk-method-name: delete 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" post: summary: Update a knowledge base (name + description) description: | Updates the metadata of a knowledge base. **Note**: the platform uses `POST` (not `PATCH`) on this path — preserved here as-is. Only `name` and `description` are mutable through this endpoint. To add or remove content (files, URLs, text snippets), use the items endpoints. tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: id required: true schema: type: string description: 24-char hex ObjectId of the knowledge base. requestBody: required: true content: application/json: schema: type: object required: [name] properties: name: type: string minLength: 1 maxLength: 40 description: Display name. 1–40 characters; trimmed server-side. example: "Q4 Pricing Updates" description: type: string description: Optional free-text description shown in the dashboard. responses: "200": description: Knowledge base updated. 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 in your organization. "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" /knowledgebase/get-presigned-url: post: summary: Get a presigned S3 URL for direct file upload description: | Two-step file upload flow that bypasses Atoms' API for the file bytes themselves — useful when files exceed the multipart upload limit on `POST /knowledgebase/{id}/items/upload-media` or when you want to upload from the browser without round-tripping through your backend. **Step 1**: Call this endpoint with file metadata. Atoms returns a presigned URL + a storage `key`. **Step 2**: `PUT` the file bytes directly to the presigned URL (set `Content-Type` to the same value you sent here). **Step 3**: Call [`POST /knowledgebase/compelete-file-upload`](#operation/completeKnowledgeBaseFileUpload) with the same `key` to commit the upload and start processing. Same end result as `POST /knowledgebase/{id}/items/upload-media`, just without the multipart-through-our-API hop. tags: - Knowledge Base security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [fileName, fileSize, contentType, knowledgeBaseId] properties: fileName: type: string description: Original filename — used for display in the Atoms dashboard. Doesn't have to match the S3 key. example: "company-handbook.pdf" fileSize: type: integer minimum: 1 description: Size in bytes. Atoms uses this to enforce per-file limits before issuing the URL. example: 2457600 contentType: type: string description: MIME type. You must send this EXACT value as `Content-Type` on the subsequent PUT to the presigned URL. example: "application/pdf" knowledgeBaseId: type: string description: 24-char hex ObjectId of the target knowledge base (from `GET /knowledgebase`). example: "6867ca76d0f8f2e0f4201281" responses: "200": description: Presigned URL ready — upload directly to it. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: url: type: string format: uri description: Time-limited presigned URL. PUT the file bytes here with `Content-Type` matching what you sent above. key: type: string description: S3 storage key — pass this back in `POST /knowledgebase/compelete-file-upload`. "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/compelete-file-upload: post: summary: Complete a presigned-URL upload and start processing description: | Step 3 of the presigned-URL upload flow. Commits a file that was uploaded directly to S3 via `POST /knowledgebase/get-presigned-url`, registers it as a knowledge-base item, and triggers async processing. **Note**: The path includes `compelete` (sic) — that's the actual route name on the platform. Don't fix the spelling in your client; it's a stable URL. tags: - Knowledge Base security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [fileName, contentType, knowledgeBaseId, key, fileSize] properties: fileName: type: string description: Filename — pass the same value used in `get-presigned-url`. example: "company-handbook.pdf" contentType: type: string example: "application/pdf" knowledgeBaseId: type: string description: Target knowledge base ID. example: "6867ca76d0f8f2e0f4201281" key: type: string description: S3 storage key returned by `get-presigned-url`. fileSize: type: integer minimum: 1 responses: "200": description: File registered as a knowledge-base item. Processing runs async — poll `GET /knowledgebase/{id}/items` for the item to surface with the desired processing status. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object description: Created knowledge-base item record. "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/get-sitemap-urls: post: summary: Extract URLs from a sitemap.xml x-fern-sdk-group-name: knowledge_base x-fern-sdk-method-name: extract_sitemap_urls description: | Fetches a website's `sitemap.xml`, parses it, and returns the list of URLs inside. Use this before calling `POST /knowledgebase/{id}/scrape-urls` to let the customer pick which URLs they actually want indexed. Returns `422` if the URL doesn't return a fetchable sitemap or if the XML is malformed. tags: - Knowledge Base security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [siteUrl, knowledgeBaseId] properties: siteUrl: type: string format: uri description: URL of the sitemap.xml file (or a homepage that links to one). example: "https://example.com/sitemap.xml" knowledgeBaseId: type: string description: Target knowledge base ID — used for ownership validation only. The endpoint doesn't write any URLs at this stage. example: "6867ca76d0f8f2e0f4201281" responses: "200": description: Extracted URLs, ready to be filtered + passed to `/scrape-urls`. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: urls: type: array items: type: string format: uri description: All URLs discovered in the sitemap. extractedAt: type: string format: date-time "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Knowledge base not found in your organization. "422": description: Could not fetch sitemap, or the sitemap XML is malformed. "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/{id}/scrape-urls: post: summary: Scrape a list of URLs into a knowledge base x-fern-sdk-group-name: knowledge_base x-fern-sdk-method-name: scrape_urls description: | Adds one or more URLs to a knowledge base by scraping each page's content, chunking it, and indexing for retrieval. Typical flow: 1. Discover candidate URLs (`POST /knowledgebase/get-sitemap-urls` or paste your own list). 2. Call this endpoint with the curated list — scraping runs async. 3. Poll `GET /knowledgebase/{id}/scraped-urls` for the per-URL status. Returns `400` if your account's KB billing precheck fails (quota or plan limits). Returns `404` if the KB doesn't belong to your organization. tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: id required: true schema: type: string description: 24-char hex ObjectId of the target knowledge base. requestBody: required: true content: application/json: schema: type: object required: [urls] properties: urls: type: array minItems: 1 items: type: string format: uri example: ["https://example.com/pricing", "https://example.com/faq"] responses: "200": description: Scrape job(s) queued. Poll `/scraped-urls` for per-URL status. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object description: Async job acknowledgement. Inspect `/scraped-urls` for per-URL progress. "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Knowledge base not found in your organization. "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/{id}/scraped-urls: get: summary: List scraped URLs in a knowledge base + their status description: | Returns every URL added to the knowledge base via `POST /knowledgebase/{id}/scrape-urls`, with its current scrape/index status. Poll this after kicking off a scrape job to track progress. tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: id required: true schema: type: string description: 24-char hex ObjectId of the knowledge base. 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 url: type: string format: uri status: type: string description: Current scrape/index status (e.g. `pending`, `scraping`, `indexed`, `failed`). createdAt: type: string format: date-time updatedAt: type: string format: date-time "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /knowledgebase/{knowledgeBaseId}/scraped-urls/{knowledgeBaseScrapedUrlsId}: delete: summary: Delete a scraped URL from a knowledge base description: | Removes a previously-scraped URL (and its indexed content) from the knowledge base. Permanent — there is no undo. tags: - Knowledge Base security: - BearerAuth: [] parameters: - in: path name: knowledgeBaseId required: true schema: type: string description: 24-char hex ObjectId of the knowledge base. - in: path name: knowledgeBaseScrapedUrlsId required: true schema: type: string description: 24-char hex ObjectId of the scraped-URL row to delete (from `GET /{id}/scraped-urls`). responses: "200": description: URL removed. 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 x-fern-sdk-group-name: phone_numbers x-fern-sdk-method-name: list 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/all-numbers: get: summary: List all phone numbers (platform + SIP) description: | Returns every phone number owned by the organization in one response: - `telephonyProducts` — numbers rented via the Atoms platform (Plivo / Twilio). - `customProducts` — numbers imported via [`POST /product/import-phone-number`](#operation/importSipPhoneNumber) with your own SIP trunks. Use this when you need a single combined view (e.g. a "Pick a number" dropdown). To list only platform-rented numbers, use [`GET /product/phone-numbers`](#operation/getAcquiredPhoneNumbers). tags: - Phone Numbers security: - BearerAuth: [] responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: telephonyProducts: type: array items: $ref: "#/components/schemas/Product" customProducts: type: array items: $ref: "#/components/schemas/Product" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/get-available-numbers: get: summary: Search rentable phone numbers in inventory x-fern-sdk-group-name: phone_numbers x-fern-sdk-method-name: search_rentable description: | Searches the telephony provider's inventory for available numbers matching the requested country (and optional area code). Returns up to 5 candidates per call. Use the returned `phoneNumber` value in [`POST /product/rent-number`](#operation/rentPhoneNumber) to actually rent it. tags: - Phone Numbers security: - BearerAuth: [] parameters: - in: query name: countryCode required: true schema: type: string example: "US" description: ISO 3166-1 alpha-2 country code (e.g. `US`, `IN`, `GB`). - in: query name: provider required: true schema: type: string enum: [plivo, twilio] description: Telephony provider to search. - in: query name: areaCode required: false schema: type: string description: Optional area-code / region filter — provider-dependent (US area codes for plivo/twilio, etc.). responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: array items: type: object properties: phoneNumber: type: string description: E.164-style number without the leading `+`. Pass exactly this value to `POST /product/rent-number`. example: "13183747513" countryCode: type: string example: "US" provider: type: string enum: [plivo, twilio] example: "plivo" areaCode: type: string description: Region / state / area-code label returned by the provider. example: "Louisiana" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/proration-amount: get: summary: Preview prorated rental cost for renting a phone number today description: | Returns the immediate prorated charge for renting one phone number from today through the end of the current billing cycle, plus the recurring monthly rate. Use this to show a "you'll be charged $X today" preview before calling [`POST /product/rent-number`](#operation/rentPhoneNumber). Returns `400` if the organization doesn't have the phone-numbers feature configured (contact support) or if the org is currently locked (e.g. unpaid invoices — call [`GET /product/unpaid-invoices`](#operation/getUnpaidInvoices) first to check). tags: - Phone Numbers security: - BearerAuth: [] responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: immediateCharge: type: number format: float description: Amount that will be charged today (USD). example: 5.3 perNumberRecurringAmount: type: number format: float description: Monthly per-number recurring charge after the prorated first period (USD). example: 10 monthlyRate: type: number format: float example: 10 prorationAmount: type: number format: float example: 5.3 daysRemaining: type: integer example: 16 daysInMonth: type: integer example: 30 proratedValue: type: number format: float description: Fraction of the month remaining (`daysRemaining / daysInMonth`). example: 0.53 "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/rent-number: post: summary: Rent a phone number from the telephony inventory x-fern-sdk-group-name: phone_numbers x-fern-sdk-method-name: rent description: | Rents an available number returned by [`GET /product/get-available-numbers`](#operation/searchAvailablePhoneNumbers). Charges the organization the prorated amount returned by [`GET /product/proration-amount`](#operation/getProrationAmount) immediately, then the monthly rate on each billing cycle. Always call `GET /product/proration-amount` first to surface the immediate charge to your customer. The endpoint may return `200` with a body containing `requiresAction: true` when payment requires customer interaction (3-D Secure, etc.) — handle that branch in your client. Released later via [`POST /product/release-number`](#operation/releasePhoneNumber). tags: - Phone Numbers security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [phoneNumber, provider] properties: phoneNumber: type: string description: The number to rent — exactly as returned by `GET /product/get-available-numbers` (no leading `+`). example: "13183747513" provider: type: string enum: [plivo, twilio] responses: "200": description: Rental processed. Inspect `data.requiresAction` to determine whether the customer needs to complete a payment-method action. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: requiresAction: type: boolean description: If `true`, payment requires further customer action (3-D Secure / SCA). Surface the client-secret flow. "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/release-number: post: summary: Release a rented phone number x-fern-sdk-group-name: phone_numbers x-fern-sdk-method-name: release description: | Releases a phone number previously rented via `POST /product/rent-number`. The number goes back into provider inventory and recurring charges stop. Returns `400` if the number is still assigned to an agent — detach it from the agent first (`PATCH /agent/{agentId}` with `productId: null`). tags: - Phone Numbers security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [productId] properties: productId: type: string description: 24-char hex MongoDB ObjectId of the phone-number product to release (the `_id` value returned by `GET /product/phone-numbers`). example: "6969109c84c74bed175f02a7" responses: "200": description: Number released content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: success: type: boolean example: true "400": description: | Number is still assigned to an agent (detach it first), or invalid product ID format. "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/manage-subscription: get: summary: Get Stripe Customer Portal URL description: | Returns a time-limited Stripe Customer Portal URL the user can open to manage their subscription (update payment method, view invoices, etc.). Returns an empty object if the organization isn't on a Stripe-backed plan. tags: - Phone Numbers security: - BearerAuth: [] responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: url: type: string format: uri description: Time-limited Stripe Customer Portal URL. Empty object if not applicable. "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/unpaid-invoices: get: summary: Check whether the organization has unpaid invoices description: | Returns whether the org has unpaid invoices that would block destructive actions (renting numbers, etc.). Call this before any billable mutation to surface the "Pay outstanding balance" flow. tags: - Phone Numbers security: - BearerAuth: [] responses: "200": description: Successful response content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: paymentRequired: type: boolean description: When `true`, the org has at least one unpaid invoice. Surface a "Pay balance" CTA before allowing further billable actions. example: false "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /product/import-phone-number: post: summary: Import a SIP phone number x-fern-sdk-group-name: phone_numbers x-fern-sdk-method-name: import_sip 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: Your SIP provider's termination host — a hostname or IP address, optionally with a port (e.g. "sip.your-provider.com:5060"). Full SIP URIs ("sip:" / "sips:") are also accepted and automatically normalized to the bare host. example: "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: "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. Must be exactly 2 characters (e.g. "IN", "US"). Sending 3+ characters returns 400. 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": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" "502": description: Bad gateway — Plivo's compliance API returned an error or is unavailable content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" /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. Must be exactly 2 characters (e.g. "IN", "US"). Sending 3+ characters returns 400. 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": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" "502": description: Bad gateway — Plivo's compliance API returned an error or is unavailable content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" /compliance/applications: post: summary: Submit a compliance application x-fern-sdk-group-name: compliance x-fern-sdk-method-name: submit 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-stringified end-user details. `name` is required; all other fields are optional but may be required by Plivo depending on country/numberType. Accepted fields: - `name` (required) — full name or business name - `lastName` — last name - `email` — email address - `addressLine1` — street address line 1 - `addressLine2` — street address line 2 - `city` — city - `state` — state or province - `postalCode` — postal/ZIP code - `country` — ISO country code; defaults to `countryIso` if omitted - `registrationNumber` — business registration number (required for some business applications) example: '{"name":"Acme Corp","email":"legal@acme.com","addressLine1":"123 Main St","city":"Mumbai","state":"MH","postalCode":"400001","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, unsupported file type, or file count mismatch (`"Expected X files, got Y"`) content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "409": description: | A compliance application already exists for this country/numberType combination. Exact message: `"A compliance application already exists for {countryIso}/{numberType}. Status: {status}"` content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" "502": description: Bad gateway — Plivo's compliance API returned an error or is unavailable content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" /compliance/applications/{id}: patch: summary: Resubmit a rejected compliance application x-fern-sdk-group-name: compliance x-fern-sdk-method-name: resubmit 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. File/document count must match exactly. Mismatch returns 400 with message `"Expected X files, got Y"`. 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: Application is not in rejected status, file count mismatch, or other validation error content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Application not found or does not belong to this organization content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" "502": description: Bad gateway — Plivo's compliance API returned an error or is unavailable content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" /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 content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" "502": description: Bad gateway — Plivo's compliance API returned an error or is unavailable content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" /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 x-fern-sdk-group-name: webhooks x-fern-sdk-method-name: create 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`. **Delivery.** Sent as an HTTP POST with a 30 second timeout. Non-2xx responses and network errors mark the delivery as failed; there are no retries. Verify the `X-Signature` header before trusting the body. For the full field-level reference, see the [Webhooks guide](/atoms/atoms-platform/features/webhooks). parameters: - in: header name: X-Signature required: true description: | Hex-encoded HMAC-SHA256 of the raw request body, keyed by the webhook's signing secret. See the [Webhooks guide](/atoms/atoms-platform/features/webhooks#verifying-signatures) for verification samples. schema: type: string example: "b0c3a1e4f2..." 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. **Delivery.** Sent as an HTTP POST with a 30 second timeout. Non-2xx responses and network errors mark the delivery as failed; there are no retries. Verify the `X-Signature` header before trusting the body. For the full field-level reference, see the [Webhooks guide](/atoms/atoms-platform/features/webhooks). parameters: - in: header name: X-Signature required: true description: | Hex-encoded HMAC-SHA256 of the raw request body, keyed by the webhook's signing secret. See the [Webhooks guide](/atoms/atoms-platform/features/webhooks#verifying-signatures) for verification samples. schema: type: string example: "b0c3a1e4f2..." 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`. **Delivery.** Sent as an HTTP POST with a 30 second timeout. Non-2xx responses and network errors mark the delivery as failed; there are no retries. Verify the `X-Signature` header before trusting the body. For the full field-level reference, see the [Webhooks guide](/atoms/atoms-platform/features/webhooks). parameters: - in: header name: X-Signature required: true description: | Hex-encoded HMAC-SHA256 of the raw request body, keyed by the webhook's signing secret. See the [Webhooks guide](/atoms/atoms-platform/features/webhooks#verifying-signatures) for verification samples. schema: type: string example: "b0c3a1e4f2..." 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}: patch: summary: Update a webhook x-fern-sdk-group-name: webhooks x-fern-sdk-method-name: update description: | Update a webhook's endpoint URL, description, or custom headers. At least one of the three fields must be present in the request body. **Event subscriptions cannot be changed here.** To add or remove an agent's subscription to this webhook, use `POST /agent/{agentId}/webhook-subscriptions` and `DELETE /agent/{agentId}/webhook-subscriptions`. **Custom `headers` behavior** - Send a non-empty object to replace all custom headers on the webhook. - Send an empty object (`{}`) to clear all custom headers. - Omit the field to leave existing custom headers untouched. Custom header limits: at most 10 headers per webhook, values up to 1024 characters, header names must match RFC 7230 token syntax. The following names are reserved and rejected: `x-signature`, `host`, `content-length`, `content-type`, `connection`, `transfer-encoding`. tags: - Webhooks security: - BearerAuth: [] parameters: - in: path name: id required: true description: The ID of the webhook to update. schema: type: string requestBody: required: true content: application/json: schema: type: object minProperties: 1 properties: endpoint: type: string format: uri description: New endpoint URL. Must be a valid URL. example: "https://example.com/webhook" description: type: string description: New human-readable label. example: "Debt Collection Agent's Endpoint" headers: type: object additionalProperties: type: string description: | Map of custom header names to values. Non-empty object replaces all existing headers; empty object clears them. example: x-api-key: "your-gateway-key" responses: "200": description: Webhook updated successfully. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: string description: The ID of the updated webhook. example: "60d0fe4f5311236168a109ca" "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" delete: summary: Delete a webhook x-fern-sdk-group-name: webhooks x-fern-sdk-method-name: delete 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 x-fern-sdk-group-name: audience x-fern-sdk-method-name: list 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 x-fern-sdk-group-name: audience x-fern-sdk-method-name: get 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 deprecated: true x-fern-availability: deprecated x-fern-sdk-group-name: agent_versioning_drafts x-fern-sdk-method-name: create_draft description: | **Deprecated on the v2 branch model.** Migrate to `PUT /agent/{id}/branches/{branchId}/draft`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). Create a new draft from an existing published version or another draft. At least one of sourceVersionId or sourceDraftId is required (both may be sent simultaneously). 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" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent not found "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" get: summary: List active drafts deprecated: true x-fern-availability: deprecated description: | **Deprecated on the v2 branch model.** Migrate to `GET /agent/{id}/branches (`openDraftId` / `hasOpenDraft`)`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). 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" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent not found "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}: get: deprecated: true x-fern-availability: deprecated summary: Get draft detail description: | **Deprecated.** By-id reads are kept working during the v1 coexistence window (~1 month). A v1 `draftId` remains resolvable. Migrate to `GET /agent/{id}/branches/{branchId}/draft`. Will be removed at the sunset date. 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" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent or draft not found "500": $ref: "#/components/responses/InternalServerErrorResponse" patch: summary: Rename a draft deprecated: true x-fern-availability: deprecated x-fern-sdk-group-name: agent_versioning_drafts x-fern-sdk-method-name: rename_draft description: | **Deprecated on the v2 branch model.** Migrate to `PUT /agent/{id}/branches/{branchId}/draft`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). | 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 minLength: 1 maxLength: 100 description: New name for the draft (1–100 characters) 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" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent or draft not found "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: summary: Discard a draft deprecated: true x-fern-availability: deprecated x-fern-sdk-group-name: agent_versioning_drafts x-fern-sdk-method-name: discard_draft description: | **Deprecated on the v2 branch model.** Migrate to `DELETE /agent/{id}/branches/{branchId}/draft`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). 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" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: | Forbidden. Returned in two cases: - The caller is not the draft creator or an org admin - The agent uses workflow_graph and the org lacks conversational agents access content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "404": description: Agent or draft not found "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}/diff: get: deprecated: true x-fern-availability: deprecated summary: Get draft diff description: | **Deprecated.** Kept working during the v1 coexistence window (~1 month). Migrate to `GET /agent/{id}/diff?a=:draft&b=`. Will be removed at the sunset date. 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 properties: sections: type: object description: Keyed by config section name. Each entry shows the before/after state of that section. additionalProperties: type: object properties: before: nullable: true description: Section value in the comparison target (null if section did not exist) after: nullable: true description: Section value in the draft (null if section was removed) changed: type: boolean description: Whether the section differs between the draft and the comparison target hasChanges: type: boolean description: True if at least one section differs "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent or draft not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}/publish: post: summary: Publish a draft deprecated: true x-fern-availability: deprecated x-fern-sdk-group-name: agent_versioning_drafts x-fern-sdk-method-name: publish_draft description: | **Deprecated on the v2 branch model.** Migrate to `POST /agent/{id}/branches/{branchId}/draft/publish`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). 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" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent or draft not found "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}/test-call: post: deprecated: true x-fern-availability: deprecated summary: Test call with draft config description: | **Deprecated.** Test-calls are exempt from the v1 write-block and remain functional. Migrate to `POST /agent/{id}/branches/{branchId}/test-call` with `includeDraft: true`. Will be removed at the sunset date. 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 properties: callId: type: string description: The call ID of the initiated test call. Use with GET /conversation/{id} to fetch the call log. "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent or draft not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/drafts/{draftId}/config: patch: summary: Edit draft config (prompt, tools, post-call metrics, voice, etc.) deprecated: true x-fern-availability: deprecated x-fern-sdk-group-name: agent_versioning_drafts x-fern-sdk-method-name: update_draft_config description: | **Deprecated on the v2 branch model.** Migrate to `PUT /agent/{id}/branches/{branchId}/draft`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). | 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" "403": $ref: "#/components/responses/ForbiddenError" "404": description: Agent or draft not found "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" # ── Agent Versioning: Published Versions ─────────────────────────────── /agent/{id}/versions: get: summary: List published versions deprecated: true x-fern-availability: deprecated description: | **Deprecated on the v2 branch model.** Migrate to `GET /agent/{id}/branches/{branchId}/revisions`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). | List published versions for an agent with pagination and optional pin filter. The `total` value currently represents the total number of published versions for the agent, not necessarily the filtered count when `isPinned` is used. 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 activatedByName: type: string nullable: true description: Display name of the user who activated the version total: type: integer description: Total published versions for the agent. When `isPinned` is used, this may not equal the filtered result count. "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/WorkflowGraphAgentAccessForbiddenError" "404": description: Agent not found content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/diff: get: deprecated: true x-fern-availability: deprecated summary: Diff two versions description: | **Deprecated.** Kept working during the v1 coexistence window (~1 month). Migrate to `GET /agent/{id}/diff?a=&b=`. Will be removed at the sunset date. Compare two version or draft revision records side-by-side by their IDs. The implementation tries published versions first and can fall back to the latest draft revision. 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: $ref: "#/components/schemas/AgentVersionDiff" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/WorkflowGraphAgentAccessForbiddenError" "404": description: Agent or version not found content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/{versionId}: get: deprecated: true x-fern-availability: deprecated summary: Get version detail description: | **Deprecated.** By-id reads are kept working during the v1 coexistence window (~1 month). A v1 `versionId` equals its migrated `revisionId`, so this continues to resolve across branches. Migrate to `GET /agent/{id}/branches/{branchId}/revisions/{revisionId}`. Will be removed at the sunset date. | 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" resolvedConfig: type: object description: Resolved agent configuration keyed by config section. additionalProperties: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/WorkflowGraphAgentAccessForbiddenError" "404": description: Agent or version not found content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" patch: summary: Update version metadata (label, description, pin only) deprecated: true x-fern-availability: deprecated x-fern-sdk-group-name: agent_versioning_versions x-fern-sdk-method-name: update_version_metadata description: | **Deprecated on the v2 branch model.** Migrate to `Metadata edits removed on v2. Set `label` at publish via `POST /agent/{id}/branches/{branchId}/draft/publish`.`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). | 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" "403": $ref: "#/components/responses/WorkflowGraphAgentAccessForbiddenError" "404": description: Agent or version not found content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/{versionId}/activate: patch: summary: Activate a version deprecated: true x-fern-availability: deprecated x-fern-sdk-group-name: agent_versioning_versions x-fern-sdk-method-name: activate_version description: | **Deprecated on the v2 branch model.** Migrate to `POST /agent/{id}/branches/{branchId}/live or POST /agent/{id}/branches/{branchId}/revisions/{revisionId}/restore`. When `ENABLE_BRANCH_MODEL` is on, this endpoint returns `409 versioning_v2_migration_required` with the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). | 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. Activation is idempotent: if the version is already active, the endpoint returns that version without changing config. 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" "403": $ref: "#/components/responses/WorkflowGraphAgentAccessForbiddenError" "404": description: Agent or version not found content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "409": $ref: "#/components/responses/VersioningV2MigrationRequired" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/versions/{versionId}/test-call: post: deprecated: true x-fern-availability: deprecated summary: Test call with version config description: | **Deprecated.** Test-calls are exempt from the v1 write-block and remain functional. Migrate to `POST /agent/{id}/branches/{branchId}/test-call` with `revisionId`. Will be removed at the sunset date. | Initiate a test call using a specific published version's configuration. The response always includes `conversationId` and `callId`. For `webcall` and `chat`, it also includes `token`, `roomName`, and `host`. Those fields are omitted for `telephony`. 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 required: - conversationId - callId properties: conversationId: type: string description: Conversation ID created for the test call callId: type: string description: Call ID created for the test call token: type: string description: Returned for webcall and chat modes only roomName: type: string description: Returned for webcall and chat modes only host: type: string description: Returned for webcall and chat modes only "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/WorkflowGraphAgentAccessForbiddenError" "404": description: Agent or version not found content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" # ══════════════════════════════════════════════════════════════════════ # Agent Versioning v2: Branches, Drafts, Revisions # Base: /agent/{id}/branches # Feature-gated behind ENABLE_BRANCH_MODEL. See the migration guide at # /voice-agents/deprecations/agent-versioning-migration for the mapping # from v1 Drafts/Versions endpoints. # ══════════════════════════════════════════════════════════════════════ /agent/{id}/branches: post: operationId: createBranch summary: Create a branch x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: create_branch description: | Fork a new branch from an existing branch. The source branch must have at least one committed revision. Branch names are unique per agent; the name `Main` is reserved for the default branch. Creating from a branch whose latest draft is still `scanning` returns `409 source_scanning`. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/CreateBranchRequest" responses: "201": description: Branch created. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/Branch" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "409": $ref: "#/components/responses/ConflictErrorResponse" "423": $ref: "#/components/responses/LockedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" get: operationId: listBranches summary: List branches x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: list description: List all non-archived branches for an agent, with per-branch draft and revision counts. tags: - Agent Versioning - Branches 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: object properties: branches: type: array items: $ref: "#/components/schemas/BranchSummary" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}: get: operationId: getBranch summary: Get branch x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: get description: Return a single branch summary, including draft state (`openDraftId`, `hasOpenDraft`) and head revision. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" responses: "200": description: Successful response. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/BranchSummary" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" patch: operationId: renameBranch summary: Rename a branch x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: rename description: Rename a non-default, non-archived branch. `Main` cannot be renamed; a name that is already in use on this agent returns `409 branch_name_exists`. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/RenameBranchRequest" responses: "200": description: Renamed. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/Branch" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Forbidden. Attempting to rename `Main`, or the caller lacks write access. content: application/json: schema: $ref: "#/components/schemas/ApiResponse" "404": $ref: "#/components/responses/NotFoundErrorResponse" "409": $ref: "#/components/responses/ConflictErrorResponse" "423": $ref: "#/components/responses/LockedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/archive: post: operationId: archiveBranch summary: Archive a branch x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: archive description: | Archive a branch. `Main` cannot be archived. The live branch cannot be archived; make another branch live first. Archived branches are hidden from list views but their revisions remain queryable by ID. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" responses: "200": description: Archived. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: archived: type: boolean example: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Forbidden. `Main` cannot be archived, the live branch cannot be archived, or the caller lacks write access. content: application/json: schema: $ref: "#/components/schemas/ApiResponse" "404": $ref: "#/components/responses/NotFoundErrorResponse" "423": $ref: "#/components/responses/LockedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/live: post: operationId: makeBranchLive summary: Make a branch live x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: make_live description: | Make this branch the live branch. Its `headRevisionId` becomes the config that serves production traffic. The previously-live branch becomes not-live automatically. The branch must be non-archived, must have at least one `committed` (security-passed) revision, and its head revision must have passed the security scan. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" responses: "200": description: Branch is now live. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/BranchSummary" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Forbidden. Branch is archived, security scan has not passed on the head revision, or the caller lacks write access. content: application/json: schema: $ref: "#/components/schemas/ApiResponse" "404": $ref: "#/components/responses/NotFoundErrorResponse" "409": $ref: "#/components/responses/ConflictErrorResponse" "423": $ref: "#/components/responses/LockedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/draft: put: operationId: updateBranchDraft summary: Write to draft x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: update_draft description: | Upsert the open draft on this branch. If no draft is open, one is created automatically. The request body is an agent config partial in the same camelCase shape as `GET /agent/{id}` (`globalPrompt`, `firstMessage`, `synthesizer`, `language`, `voiceDetectionConfig`, `smartTurnConfig`, ...) and must contain at least one recognized field; the server merges it into the existing draft and returns the resulting draft as a revision-shaped snapshot. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/UpdateBranchDraftRequest" responses: "200": description: Draft updated. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/Revision" "400": description: Bad request. Empty body, no recognized field, or validation error on the config partial. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "409": description: >- Conflict. One of three flavors: v1 endpoint used under branch mode (`error_type: "versioning_v2_migration_required"`); stale `expectedRevision` (`DraftConflictError` with `data.conflict.{expectedRevision, latestRevision, diffs}`); or `base_revision_unavailable` (the `expectedRevision` references a revision this branch does not have). Discriminate on `error_type` or on body shape. content: application/json: schema: oneOf: - $ref: "#/components/schemas/VersioningV2MigrationRequiredResponse" - $ref: "#/components/schemas/DraftConflictError" - $ref: "#/components/schemas/ConflictErrorResponse" "423": $ref: "#/components/responses/LockedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" get: operationId: getBranchDraft summary: Get open draft x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: get_draft description: Return the currently-open draft on this branch, including per-edit history. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" responses: "200": description: Successful response. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/DraftDetail" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: No open draft on this branch, or the branch does not exist. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: operationId: discardBranchDraft summary: Discard open draft x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: discard_draft description: Discard the open draft on this branch. Any unpublished edits are lost. The last committed revision remains the branch head. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" responses: "200": description: Discarded. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: discarded: type: boolean example: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": description: No open draft on this branch, or the branch does not exist. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/draft/publish: post: operationId: publishBranchDraft summary: Publish draft x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: publish_draft description: | Publish the open draft on this branch as a new revision. The response is `200` with `state: "committed"` when the security scan finishes synchronously, and `202` with `state: "scanning"` when the scan is deferred. A `scanning` revision is visible in history but cannot be restored or made live until it becomes `committed`. If the scan fails, the revision is left in `scanning` state and this endpoint returns `409` on subsequent publishes until the scan is retried. Publishing on the live branch pushes to production immediately. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/PublishBranchDraftRequest" responses: "200": description: Draft committed synchronously. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/PublishResult" "202": description: Security scan queued. Poll `GET /agent/{id}/branches/{branchId}/revisions` until the returned revision transitions to `committed`. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/PublishResult" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Forbidden. Branch is archived or the caller lacks write access. content: application/json: schema: $ref: "#/components/schemas/ApiResponse" "404": description: No open draft on this branch, or the branch does not exist. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "409": $ref: "#/components/responses/ConflictErrorResponse" "423": $ref: "#/components/responses/LockedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/draft/publish/cancel: post: operationId: cancelBranchDraftPublish summary: Cancel in-flight publish x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: cancel_publish description: Cancel a publish that is currently scanning. Idempotent. Returns `200` even if no scan is active. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" responses: "200": description: Cancel processed. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: cancelled: type: boolean example: true "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/revisions: get: operationId: listBranchRevisions summary: List revisions on a branch x-fern-sdk-group-name: agent_versioning_revisions x-fern-sdk-method-name: list description: Paginated list of committed and scanning revisions on this branch, newest first. tags: - Agent Versioning - Revisions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" - name: limit in: query required: false schema: type: integer minimum: 1 maximum: 100 default: 20 - name: skip in: query required: false schema: type: integer minimum: 0 default: 0 responses: "200": description: Successful response. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: revisions: type: array items: $ref: "#/components/schemas/Revision" total: type: integer "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/revisions/{revisionId}: get: operationId: getRevision summary: Get revision x-fern-sdk-group-name: agent_versioning_revisions x-fern-sdk-method-name: get description: Return a single revision plus its `resolvedConfig` (the fully-merged agent config at that revision). tags: - Agent Versioning - Revisions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" - $ref: "#/components/parameters/RevisionId" responses: "200": description: Successful response. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: revision: $ref: "#/components/schemas/Revision" resolvedConfig: type: object description: Fully-merged agent config at this revision. additionalProperties: true "400": description: Bad request. Invalid ID, or the revision does not belong to this branch. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/revisions/{revisionId}/history: get: operationId: getRevisionHistory summary: Get revision publish trail x-fern-sdk-group-name: agent_versioning_revisions x-fern-sdk-method-name: get_history description: | Return the publish trail for a revision: who published it, and the ordered list of prior revisions on this branch with the sections that changed at each step. tags: - Agent Versioning - Revisions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" - $ref: "#/components/parameters/RevisionId" responses: "200": description: Successful response. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: revision: $ref: "#/components/schemas/Revision" publishedBy: type: string trail: type: array items: type: object properties: revision: $ref: "#/components/schemas/Revision" changedSections: type: array items: type: string "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/revisions/{revisionId}/restore: post: operationId: restoreRevision summary: Restore a revision x-fern-sdk-group-name: agent_versioning_revisions x-fern-sdk-method-name: restore description: | Republish an older revision as a new revision at the head of this branch. Restore does not overwrite history; the older revision keeps its ID, and a new revision is committed on top. The response mirrors `POST /agent/{id}/branches/{branchId}/draft/publish`: `200 committed` if the scan is synchronous, `202 scanning` if deferred. Only one publish or restore can be in flight per branch at a time. tags: - Agent Versioning - Revisions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" - $ref: "#/components/parameters/RevisionId" responses: "200": description: Restored synchronously. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/PublishResult" "202": description: Security scan queued. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/PublishResult" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Forbidden. Source revision has not passed its security scan, or the caller lacks write access. content: application/json: schema: $ref: "#/components/schemas/ApiResponse" "404": $ref: "#/components/responses/NotFoundErrorResponse" "409": $ref: "#/components/responses/ConflictErrorResponse" "423": $ref: "#/components/responses/LockedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/branches/{branchId}/test-call: post: operationId: branchTestCall summary: Start a test call against a branch x-fern-sdk-group-name: agent_versioning_branches x-fern-sdk-method-name: test_call description: | Start a test call using the branch's current config. Send `includeDraft: true` to test the open draft, or send `revisionId` to test a specific committed revision on the branch. Sending both is a validation error. The response always includes `conversationId` and `callId`. For `webcall` and `chat`, it also includes `token`, `roomName`, and `host`. Those fields are omitted for `telephony`. tags: - Agent Versioning - Branches security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - $ref: "#/components/parameters/BranchId" requestBody: required: false content: application/json: schema: $ref: "#/components/schemas/TestCallV2Request" responses: "200": description: Test call initiated. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/TestCallResult" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/WorkflowGraphAgentAccessForbiddenError" "404": description: "Branch, agent, or referenced revision not found. Also returned when `includeDraft: true` is sent and no draft is open." content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" "409": description: The branch has no committed revision to test against. content: application/json: schema: $ref: "#/components/schemas/ConflictErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /agent/{id}/diff: get: operationId: diffRefs summary: Diff two revisions or drafts x-fern-sdk-group-name: agent_versioning_revisions x-fern-sdk-method-name: diff description: | Compare any two references on this agent and return per-section diffs. Each side (`a` and `b`) is either a `revisionId` or the string `:draft` to reference the open draft on a branch. Sides may cross branches. Both references must resolve to configs on the same agent. tags: - Agent Versioning - Revisions security: - BearerAuth: [] parameters: - $ref: "#/components/parameters/AgentId" - name: a in: query required: true description: Left-hand side. Either a `revisionId` (24-hex ObjectId) or the token `:draft`. schema: type: string minLength: 1 maxLength: 64 - name: b in: query required: true description: Right-hand side. Either a `revisionId` (24-hex ObjectId) or the token `:draft`. schema: type: string minLength: 1 maxLength: 64 responses: "200": description: Successful response. content: application/json: schema: type: object properties: status: type: boolean example: true data: $ref: "#/components/schemas/DiffResult" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": $ref: "#/components/responses/ForbiddenError" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" # ══════════════════════════════════════════════════════════════════════ # end v2 branch model # ══════════════════════════════════════════════════════════════════════ # ── 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. /prompt-scoring/score: post: summary: Score a prompt description: | Scores an agent's prompt across 11 quality dimensions using Gemini-based analysis. Requires the prompt to have changed since the last scoring. **Input:** Provide exactly one of `versionId` (published agent version) or `draftId` (agent draft). Providing both or neither returns a 400. **Credit usage:** 1 credit is deducted per successful call. **Idempotency:** Re-submitting the same prompt without changes returns a 400 — retrieve the cached score via the GET agent endpoint instead. **Supported agent types:** Only `single_prompt` agents are supported. Workflow-graph agents return a 400. **Scoring model:** Two sequential Gemini calls — a Platform Analyst pass followed by a Rubric Judge pass. ### Scored Dimensions | Tier | Dimension | Notes | |------|-----------|-------| | 1 | Role & Objective | | | 1 | Personality & Voice | | | 1 | Conversation Structure | | | 1 | Tool Integration | | | 1 | Constraints & Safety | | | 2 | Conversational Naturalness | | | 2 | Failure-Mode Coverage | | | 3 | Information Integrity | Gating — if Weak/Missing, score capped at 70 | | 3 | Variable & Tool Hygiene | Gating — if Weak/Missing, score capped at 50 | | 3 | Internal Consistency | | | 3 | Density | Computed from token analysis | tags: - Prompt Scoring security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object description: Exactly one of `versionId` or `draftId` must be provided. oneOf: - required: [versionId] properties: versionId: type: string description: Published agent version ID (MongoDB ObjectId). example: "6a1589b75e048394eb37bc47" - required: [draftId] properties: draftId: type: string description: Agent draft ID (MongoDB ObjectId). example: "6a1589b75e048394eb37bc48" responses: "200": description: Prompt scored successfully content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: overall_score: type: integer description: 0–100 quality score. example: 82 overall_grade: type: string description: Human-readable grade. enum: ["Excellent", "Good", "Needs Work", "Poor"] example: "Good" band: type: string description: | Token density band based on prompt length: - `lean` — fewer than 4K tokens - `normal` — 4K–9.9K tokens - `heavy` — 10K–14.9K tokens - `overweight` — 15K or more tokens enum: ["lean", "normal", "heavy", "overweight"] example: "normal" estimated_ttft_overhead_ms: type: number description: Estimated first-token latency overhead in milliseconds introduced by the prompt length. example: 420 dimensions: type: array description: Per-dimension scoring results across 11 quality dimensions. items: type: object properties: tier: type: integer description: "Priority tier: 1 (highest), 2, or 3." enum: [1, 2, 3] example: 1 level: type: string description: Quality level for this dimension. enum: ["Strong", "Adequate", "Weak", "Missing", "Not Applicable"] example: "Strong" evidence_span: type: string description: Quote from the prompt supporting the assessment. Empty string if no relevant content was found. example: "You are a helpful support agent..." title: type: string description: Short dimension name. example: "Role & Objective" description: type: string description: Explanation of the score for this dimension. example: "Prompt clearly defines the agent's role and primary objective." example: status: true data: overall_score: 56 overall_grade: "Needs Work" band: "lean" estimated_ttft_overhead_ms: 12.9 dimensions: - tier: 1 level: "Adequate" evidence_span: "You are a friendly and helpful weather assistant. Your role is to provide accurate, real-time weather information to users." title: "Clear but basic role definition" description: "The role is clearly defined but lacks specific success criteria or scope boundaries." - tier: 1 level: "Weak" evidence_span: "Use the get_weather function to fetch real-time data" title: "Undeclared tool reference" description: "The 'get_weather' tool is referenced but not defined, and failure paths are missing." - tier: 2 level: "Missing" evidence_span: "no relevant content found" title: "No failure mode coverage" description: "The prompt contains no instructions for handling errors, tool failures, or unclear user input." "400": description: | Bad request. Possible reasons: - Neither or both of `versionId`/`draftId` provided - Organization has no credits available - Agent is a conversational/workflow-graph type (not supported) - Prompt unchanged since last scoring — retrieve the existing score via GET agent - No prompt found on the version or draft content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Prompt has not changed since last scoring — retrieve the existing score via GET agent"] "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Not a member of the organization or insufficient role (minimum Member required). content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["You are not a member of this organization"] "404": description: Version or draft not found. content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Version not found"] "429": description: Rate limit exceeded. content: application/json: schema: type: object properties: message: type: string example: "Rate limit exceeded" rateLimit: type: object properties: routeClass: type: string example: "prompt-scoring" limit: type: integer example: 10 retryAfterSec: type: integer description: Seconds to wait before retrying. example: 60 "500": description: Gemini scoring failed after retries. content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Prompt scoring failed"] /analytics/call-counts-log: get: operationId: getCallCountsLog summary: List call records description: Paginated listing of call records for the organization, with optional filtering by agent, campaign, call type, and date range. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) - name: page in: query schema: type: integer default: 1 description: Page number (default 1) - name: limit in: query schema: type: integer default: 10 description: Records per page (default 10) responses: "200": description: Paginated call records content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: calls: type: array items: type: object properties: orgId: type: string callId: type: string agentId: type: string agentName: type: string campaignId: type: string campaignName: type: string callType: type: string timestamp: type: string format: date-time callDurationMs: type: number callLatencyMs: type: number costSpent: type: number disconnectionReason: type: string source: type: string recordingUrl: type: string callStatus: type: string fromNumber: type: string toNumber: type: string totalCalls: type: number totalPages: type: number currentPage: type: number limit: type: number "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/call-counts-by-day: get: operationId: getCallCountsByDay summary: Call counts by day description: Returns call counts aggregated per calendar day, suitable for bar chart visualizations. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Daily call counts content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string callCountsByDay: type: array items: type: object properties: day: type: string format: date count: type: number "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/conversation-details/{callId}: get: operationId: getConversationDetails summary: Get conversation details description: Returns the full transcript and event stream for a specific call, reconstructed from ClickHouse event data. tags: - Analytics security: - BearerAuth: [] parameters: - name: callId in: path required: true schema: type: string description: Unique identifier for the call responses: "200": description: Call transcript and events content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string callId: type: string agentName: type: string workflowType: type: string transcript: type: array items: type: object properties: role: type: string text: type: string timestamp: type: string format: date-time events: type: array items: type: object properties: eventType: type: string timestamp: type: string format: date-time fromNumber: type: string toNumber: type: string callDurationMs: type: number "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Call log not found or does not belong to the organization "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/usage/timeseries: get: operationId: getUsageTimeseries summary: Credit usage timeseries description: Returns daily credit usage over a date range. tags: - Analytics security: - BearerAuth: [] parameters: - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Daily credit usage content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: dateRange: type: object properties: from: type: string format: date to: type: string format: date dayWiseCredits: type: array items: type: object properties: date: type: string format: date credits: type: number totalCredits: type: number "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/dashboard: get: operationId: getDashboard summary: Full dashboard data description: | Batched endpoint that fetches all dashboard panels in a single request by running six sub-queries in parallel. Equivalent to calling `summary`, `call-volume-timeseries`, `call-outcomes-timeseries`, `pickup-rate-by-number`, `hourly-performance`, and `duration-stats` individually. Each field may be absent if that sub-query failed; partial data is still returned. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: All dashboard panel data content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: summary: type: object description: "See GET /analytics/summary" callVolumeTimeseries: type: object description: "See GET /analytics/call-volume-timeseries" callOutcomesTimeseries: type: object description: "See GET /analytics/call-outcomes-timeseries" pickupRateByNumber: type: object description: "See GET /analytics/pickup-rate-by-number" hourlyPerformance: type: object description: "See GET /analytics/hourly-performance" durationStats: type: object description: "See GET /analytics/duration-stats" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/summary: get: operationId: getAnalyticsSummary summary: Dashboard summary KPIs description: Returns high-level KPI metrics with current period value, previous period value, and percent change for trend comparison. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: KPI summary content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string totalCalls: $ref: "#/components/schemas/AnalyticsTrendMetric" pickupRate: $ref: "#/components/schemas/AnalyticsTrendMetric" avgDurationMs: $ref: "#/components/schemas/AnalyticsTrendMetric" medianDurationMs: type: number totalDurationMs: $ref: "#/components/schemas/AnalyticsTrendMetric" uniqueUsersReached: $ref: "#/components/schemas/AnalyticsTrendMetric" totalCost: $ref: "#/components/schemas/AnalyticsTrendMetric" period: $ref: "#/components/schemas/AnalyticsDateRange" previousPeriod: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/call-volume-timeseries: get: operationId: getCallVolumeTimeseries summary: Call volume timeseries description: Returns daily call volume broken down by outcome (answered, no-answer, failed, cancelled) over the selected period. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Daily call volume by outcome content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string dataPoints: type: array items: type: object properties: date: type: string format: date totalCalls: type: number answeredCalls: type: number noAnswerCalls: type: number failedCalls: type: number cancelledCalls: type: number totalDurationMs: type: number period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/pickup-rate-by-number: get: operationId: getPickupRateByNumber summary: Pickup rate by phone number description: Returns pickup rate and call volume broken down per originating phone number. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Per-number pickup rate and call volume content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string numbers: type: array items: type: object properties: phoneNumber: type: string totalCalls: type: number answeredCalls: type: number pickupRate: type: number lastActiveDate: type: string format: date period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/phone-number-trends: get: operationId: getPhoneNumberTrends summary: Phone number trends description: Returns per-phone-number call volume and pickup rate as a daily timeseries, useful for spotting number-level degradation over time. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Per-number daily timeseries content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string trends: type: array items: type: object properties: phoneNumber: type: string dataPoints: type: array items: type: object properties: date: type: string format: date totalCalls: type: number answeredCalls: type: number pickupRate: type: number period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/hourly-performance: get: operationId: getHourlyPerformance summary: Hourly performance description: Returns call volume and performance metrics broken down by hour of day (0–23), aggregated across the selected date range. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Hourly performance breakdown content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string hours: type: array items: type: object properties: hour: type: integer minimum: 0 maximum: 23 description: Hour of day (0–23) totalCalls: type: number answeredCalls: type: number pickupRate: type: number totalDurationMs: type: number avgDurationMs: type: number period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/call-outcomes-timeseries: get: operationId: getCallOutcomesTimeseries summary: Call outcomes timeseries description: Returns a daily breakdown of call outcomes (answered, no-answer, failed, cancelled) over time, plus totals for the entire period. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Daily call outcomes and period totals content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string dataPoints: type: array items: type: object properties: date: type: string format: date answered: type: number noAnswer: type: number failed: type: number cancelled: type: number total: type: number totals: type: object properties: answered: type: number noAnswer: type: number failed: type: number cancelled: type: number total: type: number period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/duration-stats: get: operationId: getDurationStats summary: Call duration statistics description: Returns call duration statistics including average, median, p90, p95 percentiles, and the proportion of short vs. long calls. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Duration statistics content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string avgDurationMs: type: number medianDurationMs: type: number p90DurationMs: type: number p95DurationMs: type: number shortCallsPercent: type: number longCallsPercent: type: number totalCalls: type: number totalDurationMs: type: number period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/weekly-trends: get: operationId: getWeeklyTrends summary: Weekly call trends description: Returns per-week call performance metrics including volume, pickup rate, and duration percentiles (p50, p90). Each week starts on Monday. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Weekly performance metrics content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string weeks: type: array items: type: object properties: weekStart: type: string format: date description: Monday that starts this week totalCalls: type: number answeredCalls: type: number pickupRate: type: number avgDuration: type: number description: Average call duration in seconds medianDuration: type: number description: Median call duration in seconds p90Duration: type: number description: p90 call duration in seconds shortCallsPercent: type: number longCallsPercent: type: number period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/agent-performance: get: operationId: getAgentPerformance summary: Agent performance description: Returns per-agent call performance metrics. Supports sorting and limiting results. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) - name: sortBy in: query schema: type: string description: "Field to sort by (e.g. `totalCalls`, `pickupRate`, `avgDuration`)" - name: sortOrder in: query schema: type: string enum: [asc, desc] description: Sort direction - name: limit in: query schema: type: integer description: Maximum number of agents to return responses: "200": description: Per-agent performance metrics content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string agents: type: array items: type: object properties: agentId: type: string totalCalls: type: number answeredCalls: type: number pickupRate: type: number avgDuration: type: number description: Average call duration in seconds totalCost: type: number period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/concurrency: get: operationId: getAnalyticsConcurrency summary: Concurrent call counts description: Returns minute-by-minute concurrent call counts for a specific day. Optionally broken down per agent. tags: - Analytics security: - BearerAuth: [] parameters: - name: date in: query required: true schema: type: string format: date description: "Date to query (YYYY-MM-DD)" - name: agentId in: query schema: type: string description: Filter to a specific agent - name: includeAgents in: query schema: type: string enum: ["true", "false"] description: Pass `true` to include a per-agent breakdown in the response responses: "200": description: Minute-level concurrency data content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: date: type: string format: date dataPoints: type: array items: type: object properties: minute: type: string description: "Time in HH:MM format" concurrentCalls: type: number peakConcurrent: type: number avgConcurrent: type: number totalMinutes: type: number byAgent: type: array description: Only present when `includeAgents=true` items: type: object properties: agentId: type: string peakConcurrent: type: number avgConcurrent: type: number totalCalls: type: number "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/call-start-distribution: get: operationId: getCallStartDistribution summary: Call start distribution description: Returns the distribution of call start times as minute-level buckets for a specific day, showing when calls were initiated throughout the day. tags: - Analytics security: - BearerAuth: [] parameters: - name: date in: query required: true schema: type: string format: date description: "Date to query (YYYY-MM-DD)" - name: agentId in: query schema: type: string description: Filter to a specific agent responses: "200": description: Minute-level call start distribution content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: date: type: string format: date dataPoints: type: array items: type: object properties: minute: type: string description: "Time in HH:MM format" callCount: type: number totalCalls: type: number "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/daily-call-summary: get: operationId: getDailyCallSummary summary: Daily call summary description: Returns an aggregate call summary for a specific day. Live in-progress and in-queue counts are merged from real-time data on top of the historical data. tags: - Analytics security: - BearerAuth: [] parameters: - name: date in: query required: true schema: type: string format: date description: "Date to query (YYYY-MM-DD)" - name: agentId in: query schema: type: string description: Filter to a specific agent responses: "200": description: Daily call summary content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: date: type: string format: date totalCalls: type: number answeredCalls: type: number unansweredCalls: type: number failedCalls: type: number pickupRate: type: number inProgressCalls: type: number inQueueCalls: type: number totalDurationMs: type: number "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /analytics/attempt-cohort: get: operationId: getAttemptCohort summary: Attempt cohort analysis description: Returns cohort analysis of call attempt numbers, showing how pickup rate changes across the 1st, 2nd, 3rd (etc.) attempts to reach the same number, including cumulative rates and marginal gain per additional attempt. tags: - Analytics security: - BearerAuth: [] parameters: - name: agentId in: query schema: type: string description: Comma-separated agent IDs to filter results - name: campaignId in: query schema: type: string description: Campaign ID to filter results - name: callType in: query schema: type: string description: "Type of call to filter (e.g. `inbound`, `outbound`)" - name: dateFrom in: query schema: type: string format: date-time description: Start of date range (ISO 8601) - name: dateTo in: query schema: type: string format: date-time description: End of date range (ISO 8601) responses: "200": description: Attempt cohort data content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgId: type: string cohorts: type: array items: type: object properties: attemptNumber: type: number totalCalls: type: number answeredCalls: type: number pickupRate: type: number cumulativeAnswered: type: number cumulativeRate: type: number marginalGain: type: number totalUniqueNumbers: type: number maxAttemptsSeen: type: number avgAttemptsToPickup: type: number period: $ref: "#/components/schemas/AnalyticsDateRange" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /call-actions: post: operationId: createCallAction summary: Create a call action description: | Creates a new call action for an agent. Call actions define automated behaviors that fire at specific points in a call lifecycle. - **`trigger`** actions fire to initiate an outbound call and require `config.phoneNumberFieldName`. - **`post-call`** actions fire after a call ends (e.g. to update a CRM record). tags: - Call Actions security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [agentId, category, provider, config] properties: agentId: type: string description: Agent this action belongs to (ObjectId) category: type: string enum: [trigger, post-call] description: When the action fires provider: type: string description: "Integration provider (e.g. `hubspot`, `salesforce`)" action_type: type: string enum: [create, update] description: The operation to perform on the provider object object: type: string description: "Provider object type to act on (e.g. `contact`, `deal`)" config: type: object required: [] properties: phoneNumberFieldName: type: string description: "Provider field name that contains the phone number. Required when `category` is `trigger`." conditions: type: array description: Filter conditions — action only fires when all conditions match items: $ref: "#/components/schemas/CallActionCondition" body: type: string description: Request body template or payload for the provider action responses: "201": description: Call action created content: application/json: schema: type: object properties: success: type: boolean example: true data: $ref: "#/components/schemas/CallAction" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" get: operationId: listCallActions summary: List call actions description: Returns a paginated list of call actions for the organization, filtered by agent. Optionally filter by category or provider. tags: - Call Actions security: - BearerAuth: [] parameters: - name: agentId in: query required: true schema: type: string description: Filter by agent (ObjectId) - name: page in: query schema: type: integer default: 1 description: Page number (default 1) - name: limit in: query schema: type: integer default: 10 description: Records per page (default 10) - name: category in: query schema: type: string enum: [trigger, post-call] description: Filter by category - name: provider in: query schema: type: string description: Filter by provider name responses: "200": description: Paginated list of call actions content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: callActions: type: array items: $ref: "#/components/schemas/CallAction" totalCount: type: number page: type: number limit: type: number "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /call-actions/{id}: get: operationId: getCallAction summary: Get a call action description: Returns a single call action by ID. Scoped to the authenticated organization. tags: - Call Actions security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: Call action ObjectId responses: "200": description: Call action content: application/json: schema: type: object properties: success: type: boolean example: true data: $ref: "#/components/schemas/CallAction" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Call action not found "500": $ref: "#/components/responses/InternalServerErrorResponse" put: operationId: updateCallAction summary: Update a call action description: Updates an existing call action. All body fields are optional — only provided fields are updated. tags: - Call Actions security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: Call action ObjectId requestBody: required: true content: application/json: schema: type: object properties: category: type: string enum: [trigger, post-call] description: Change when the action fires provider: type: string description: Change the integration provider action_type: type: string enum: [create, update] description: Change the operation type object: type: string description: Change the provider object type config: type: object properties: phoneNumberFieldName: type: string description: Update the phone number field mapping conditions: type: array description: Replace the full conditions array items: $ref: "#/components/schemas/CallActionCondition" body: type: string description: Update the payload body responses: "200": description: Updated call action content: application/json: schema: type: object properties: success: type: boolean example: true data: $ref: "#/components/schemas/CallAction" "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Call action not found "500": $ref: "#/components/responses/InternalServerErrorResponse" delete: operationId: deleteCallAction summary: Delete a call action description: Permanently deletes a call action. Scoped to the authenticated organization. tags: - Call Actions security: - BearerAuth: [] parameters: - name: id in: path required: true schema: type: string description: Call action ObjectId responses: "200": description: Call action deleted content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: message: type: string example: Call action deleted successfully "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Call action not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /integration/modify-webengage-integration: post: operationId: modifyWebEngageIntegration summary: Create or update WebEngage integration description: | Creates or updates the WebEngage integration for the organization. Replaces the existing integration configuration with the provided credential set(s). **Note:** This endpoint returns a direct JSON response — not the standard `{ success, data }` wrapper used by other endpoints. tags: - Integrations security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [integrationSets] properties: integrationSets: type: array minItems: 1 description: One or more WebEngage credential sets items: $ref: "#/components/schemas/WebEngageIntegrationSet" responses: "200": description: Integration created or updated content: application/json: schema: type: object properties: message: type: string example: Integration created successfully data: type: object description: Integration details object "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Organization not found "500": $ref: "#/components/responses/InternalServerErrorResponse" /integration/get-webengage-details: get: operationId: getWebEngageDetails summary: Get WebEngage integration details description: | Returns the current WebEngage integration configuration for the organization. **Note:** This endpoint returns a direct JSON response — not the standard `{ success, data }` wrapper used by other endpoints. tags: - Integrations security: - BearerAuth: [] responses: "200": description: WebEngage integration details content: application/json: schema: type: object properties: message: type: string example: Integration details retrieved successfully data: type: object description: Integration details object "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /concurrency: get: operationId: getConcurrency summary: Get concurrency limits description: | Returns the organization's overall concurrency limit, how much is reserved across all agents, the remaining unreserved pool, and the per-agent reservation breakdown per call channel. tags: - Concurrency security: - BearerAuth: [] responses: "200": description: Concurrency overview content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: orgLimit: type: number description: Total concurrent calls allowed for this organization totalReserved: type: number description: Sum of all agent reservations across all channels unreservedPool: type: number description: orgLimit minus totalReserved — capacity available to any agent agents: type: array items: type: object properties: agentId: type: string description: Agent ObjectId agentName: type: string avatarUrl: type: string nullable: true webcall: type: number description: Reserved webcall slots outbound: type: number description: Reserved outbound call slots inbound: type: number description: Reserved inbound call slots chat: type: number description: Reserved chat slots "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /concurrency/reservations: put: operationId: updateConcurrencyReservations summary: Update concurrency reservations description: | Updates concurrency reservations for one or more agents in a single request. Replaces the existing reservation values for each specified agent. **Admin role required.** tags: - Concurrency security: - BearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: [reservations] properties: reservations: type: array minItems: 1 description: Array of agent reservations to update items: type: object required: [agentId, webcall, outbound, inbound, chat] properties: agentId: type: string description: Agent ObjectId webcall: type: integer minimum: 0 description: Reserved webcall slots outbound: type: integer minimum: 0 description: Reserved outbound call slots inbound: type: integer minimum: 0 description: Reserved inbound call slots chat: type: integer minimum: 0 description: Reserved chat slots responses: "200": description: Reservations updated content: application/json: schema: type: object properties: success: type: boolean example: true data: type: object properties: updated: type: number description: Count of agent reservations updated "400": $ref: "#/components/responses/BadRequestError" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "403": description: Admin role required content: application/json: schema: $ref: "#/components/schemas/ApiResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /disposition-metric-templates: get: operationId: listDispositionMetricTemplates summary: List disposition metric templates description: | Returns all available disposition metric templates. These reusable definitions are used to populate the post-call analytics metric picker when configuring an agent's `postCallAnalyticsConfig`. Only a user token is required — no organization context needed. tags: - Disposition Metric Templates security: - BearerAuth: [] responses: "200": description: Array of disposition metric templates content: application/json: schema: type: object properties: success: type: boolean example: true data: type: array items: type: object properties: identifier: type: string description: Unique snake_case key (lowercase letters, digits, and underscores only) example: call_resolved dispositionMetricPrompt: type: string description: AI prompt used to extract this metric from the call transcript dispositionMetricType: type: string enum: [STRING, BOOLEAN, INTEGER, ENUM, DATETIME] description: | How the extracted value is interpreted: - `STRING` — free-text output - `BOOLEAN` — true/false outcome - `INTEGER` — whole number value - `ENUM` — one of a predefined set of choices - `DATETIME` — a date/time value "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /dnc: get: summary: List DNC entries for the organization x-fern-sdk-group-name: dnc x-fern-sdk-method-name: list description: | Lists Do-Not-Call entries for the caller's organization with pagination, search, and sort. Optionally scope to a single agent via `agentId`. Each entry records a phone number that was flagged (via call outcome or manual upload) as not-to-be-called for either the org or a specific agent. tags: - DNC security: - BearerAuth: [] parameters: - name: agentId in: query required: false schema: type: string description: | Optional 24-character hex agent ID. When present, restricts results to entries for this agent. Returns 400/404 if the ID isn't valid or doesn't belong to the caller's org. - name: search in: query required: false schema: type: string description: Free-text search across phone numbers. - name: sortField in: query required: false schema: type: string enum: [createdAt, phoneNumber] default: createdAt - name: sortOrder in: query required: false schema: type: string enum: [asc, desc] default: desc - name: page in: query required: false schema: type: string default: "1" description: Page number (string-encoded positive integer, ≥ 1). - name: offset in: query required: false schema: type: string default: "50" description: Page size (string-encoded; server clamps to 1–500). responses: "200": description: Paginated DNC entries. content: application/json: schema: type: object properties: status: type: boolean example: true data: type: object properties: entries: type: array items: type: object properties: id: type: string agentId: type: string orgId: type: string phoneNumber: type: string source: type: string detectedInCallId: type: string nullable: true createdAt: type: string format: date-time updatedAt: type: string format: date-time pagination: type: object properties: page: type: integer offset: type: integer total: type: integer totalPages: type: integer hasMore: type: boolean "400": $ref: "#/components/responses/BadRequestErrorResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": $ref: "#/components/responses/NotFoundErrorResponse" "500": $ref: "#/components/responses/InternalServerErrorResponse" /payment/v1/credits/balance: get: summary: Get credit balance operationId: getCreditBalance x-fern-sdk-group-name: billing x-fern-sdk-method-name: get_balance description: | Returns the organization's current credit balance in USD plus the current plan identifier. Organization is resolved from the API key, so no `X-Organization-Id` header is required. tags: - Billing security: - BearerAuth: [] servers: - url: https://api.smallest.ai description: Production x-fern-server-name: payment responses: "200": description: Current balance for the caller's organization. content: application/json: schema: $ref: "#/components/schemas/BillingBalanceResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" /payment/v1/credits/ledger: get: summary: List credit ledger operationId: getCreditLedger x-fern-sdk-group-name: billing x-fern-sdk-method-name: get_ledger description: | Paginated credit-ledger transaction history. Ledger reads are served from ClickHouse; a rare storage-tier outage returns an empty `transactions` array rather than a 5xx. **Window rules** - `from` defaults to `to - 7 days`, `to` defaults to now. - The span between `from` and `to` cannot exceed **90 days**. A wider span returns 400. Page through longer periods by making multiple calls with shifted `from`/`to`. - `from` cannot be earlier than **2026-03-02T00:00:00Z**. Older historical data is not available via API; contact support for bulk exports. - `from > to` returns 400. **Filters** - `type` filters to a single transaction type. `PAYMENTS` is a virtual filter that returns both `CREDIT_PURCHASE` and `AUTO_RELOAD` rows. - `scope` filters `USAGE_DEDUCTION` rows by product category. tags: - Billing security: - BearerAuth: [] servers: - url: https://api.smallest.ai description: Production x-fern-server-name: payment parameters: - in: query name: limit description: Page size (1–100). schema: type: integer minimum: 1 maximum: 100 default: 50 - in: query name: offset description: Offset for pagination. schema: type: integer minimum: 0 default: 0 - in: query name: from description: | Lower bound of the query window (ISO 8601, `Z`-suffixed UTC recommended). Defaults to seven days before `to`. Cannot be earlier than `2026-03-02T00:00:00Z`. schema: type: string format: date-time example: "2026-07-01T00:00:00Z" - in: query name: to description: Upper bound of the query window (ISO 8601, `Z`-suffixed UTC recommended). Defaults to now. schema: type: string format: date-time example: "2026-07-28T00:00:00Z" - in: query name: type description: Filter to a single transaction type. `PAYMENTS` is a virtual filter that returns purchase-related rows (`CREDIT_PURCHASE` + `AUTO_RELOAD`). schema: type: string enum: - SIGNUP_BONUS - CREDIT_PURCHASE - AUTO_RELOAD - USAGE_DEDUCTION - ADMIN_ADJUSTMENT - COUPON_CREDIT - MIGRATION - PAYMENTS - in: query name: scope description: Filter by spend category. Applies only to `USAGE_DEDUCTION` rows. schema: type: string enum: - platform - voice_ai - voice_models responses: "200": description: Paginated ledger with summary + query window echo. content: application/json: schema: $ref: "#/components/schemas/BillingLedgerResponse" "400": description: | Query-window validation failed. Common cases: - `from` earlier than `2026-03-02T00:00:00Z`. - Span between `from` and `to` exceeds 90 days. - `from > to`. - Malformed date string in `from` or `to`. content: application/json: schema: type: object properties: success: type: boolean example: false error: type: object properties: code: type: string example: validation_error message: type: string examples: spanTooWide: summary: Range exceeds 90 days value: success: false error: code: validation_error message: "Date range cannot exceed 90 days. Please narrow your range or contact support for bulk exports." beforeCutoff: summary: Range starts before the data-availability cutoff value: success: false error: code: validation_error message: "Date range starts before 2026-03-02. Usage data before this date is not available via API. Please contact support for historical exports." malformedDate: summary: Unparseable date string value: success: false error: code: validation_error message: "from: Invalid date; to: Invalid date" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" /payment/v1/credits/usage/breakdown: get: summary: Get usage breakdown operationId: getCreditUsageBreakdown x-fern-sdk-group-name: billing x-fern-sdk-method-name: get_usage_breakdown description: | Total credits spent so far, split across the three product scopes. The window is a cumulative snapshot from **2026-03-02T00:00:00Z** (the platform's usage-tracking start date) up to the current instant. Served from ClickHouse. No query parameters. tags: - Billing security: - BearerAuth: [] servers: - url: https://api.smallest.ai description: Production x-fern-server-name: payment responses: "200": description: Spend split by scope. content: application/json: schema: $ref: "#/components/schemas/BillingUsageBreakdownResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" /payment/v1/invoices: get: summary: List invoices operationId: listInvoices x-fern-sdk-group-name: billing x-fern-sdk-method-name: list_invoices description: | Returns up to 20 of the most recent Stripe invoices for the caller's organization. Each item is the raw Stripe `Invoice` object; use the canonical Stripe reference at [stripe.com/docs/api/invoices/object](https://stripe.com/docs/api/invoices/object) for field-level semantics. Organizations that have never been charged (free-tier only) return an empty array. tags: - Billing security: - BearerAuth: [] servers: - url: https://api.smallest.ai description: Production x-fern-server-name: payment responses: "200": description: Up to 20 recent Stripe invoices for the caller's organization. content: application/json: schema: $ref: "#/components/schemas/BillingInvoiceListResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" /payment/v1/invoices/{invoiceId}/pdf: get: summary: Get invoice PDF URL operationId: getInvoicePdf x-fern-sdk-group-name: billing x-fern-sdk-method-name: get_invoice_pdf description: | Returns a Stripe-hosted PDF URL for the invoice. The URL is short-lived; fetch fresh when you need to hand it to a user. Requesting an invoice that does not belong to the caller's organization returns 404 (not 403), so a foreign invoice ID cannot be confirmed to exist. tags: - Billing security: - BearerAuth: [] servers: - url: https://api.smallest.ai description: Production x-fern-server-name: payment parameters: - in: path name: invoiceId required: true description: Stripe invoice ID (e.g. `in_1THiCSRwh8g1U6dfOcUtTdq9`). schema: type: string responses: "200": description: Stripe-hosted PDF URL for the invoice. content: application/json: schema: $ref: "#/components/schemas/BillingInvoicePdfResponse" "401": $ref: "#/components/responses/UnauthorizedErrorResponse" "404": description: Invoice not found, or does not belong to the caller's organization. content: application/json: schema: type: object properties: success: type: boolean example: false error: type: object properties: code: type: string example: not_found message: type: string example: "Invoice not found: in_1THiCSRwh8g1U6dfOcUtTdq9" 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 pattern: "^[a-f\\d]{24}$" 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}$" BranchId: name: branchId in: path required: true description: The branch ID. schema: type: string pattern: "^[a-f\\d]{24}$" RevisionId: name: revisionId in: path required: true description: The revision ID. Equal to the v1 `versionId` for revisions that were migrated from the v1 model. schema: type: string pattern: "^[a-f\\d]{24}$" schemas: WebEngageIntegrationSet: type: object description: A single WebEngage credential set required: [licenseCode, environment, apiKey] properties: licenseCode: type: string description: WebEngage license code environment: type: string description: WebEngage environment identifier apiKey: type: string description: WebEngage API key CallActionCondition: type: object description: A filter condition evaluated against provider record fields required: [field, operator, value] properties: field: type: string description: Provider record field name operator: type: string enum: [eq, neq, gt, gte, lt, lte, in, nin, contains, notContains, startsWith, endsWith] description: Comparison operator value: type: string description: Value to compare against CallAction: type: object description: A call action that fires automatically at a specific point in the call lifecycle properties: _id: type: string description: MongoDB ObjectId organization: type: string description: Organization ObjectId agentId: type: string description: Agent ObjectId this action belongs to category: type: string enum: [trigger, post-call] description: When the action fires provider: type: string description: "Integration provider (e.g. `hubspot`, `salesforce`)" action_type: type: string enum: [create, update] description: The operation performed on the provider object object: type: string description: "Provider object type (e.g. `contact`, `deal`)" config: type: object properties: phoneNumberFieldName: type: string description: "Provider field that contains the phone number (required for `trigger` actions)" conditions: type: array items: $ref: "#/components/schemas/CallActionCondition" body: type: string description: Request body template or payload for the provider action createdAt: type: string format: date-time updatedAt: type: string format: date-time AnalyticsTrendMetric: type: object description: A metric value with current and previous period values and percent change properties: current: type: number previous: type: number percentChange: type: number AnalyticsDateRange: type: object properties: from: type: string format: date to: type: string format: date ApiResponse: type: object properties: status: type: boolean data: type: object WidgetConfig: type: object description: | Configuration for the embeddable web widget. Used by `GET /agent/{id}/widget-config` (returned with `assistantId` injected) and `PATCH /agent/{id}/widget-config` (merge-patched). Every field is optional — only the fields present in a PATCH request body are written, so partial updates are safe. properties: position: type: string enum: [bottom-right, bottom-left, top-right, top-left] size: type: string enum: [tiny, compact, full] borderRadius: type: number minimum: 0 maximum: 50 mode: type: string enum: [chat, voice] theme: type: string enum: [light, dark] baseColor: type: string accentColor: type: string agentBubbleColor: type: string textOnAccentColor: type: string secondaryTextColor: type: string primaryTextColor: type: string title: type: string startButtonText: type: string minLength: 1 endButtonText: type: string minLength: 1 ctaTitle: type: string nullable: true ctaSubtitle: type: string nullable: true ctaName: type: string nullable: true widgetName: type: string nullable: true avatarUrl: type: string nullable: true description: | Must start with the CDN distribution domain prefix configured for the organization. Submit a non-CDN URL and the server returns 400. voiceEmptyMessage: type: string nullable: true voiceActiveEmptyMessage: type: string nullable: true chatEmptyMessage: type: string nullable: true chatFirstMessage: type: string nullable: true chatPlaceholder: type: string minLength: 1 voiceShowTranscript: type: boolean consentRequired: type: boolean consentTitle: type: string minLength: 1 consentContent: type: string minLength: 1 consentStorageKey: type: string nullable: true publicKey: type: string assistantId: type: string description: Injected by `GET /agent/{id}/widget-config` (equals the agent ID). allowlist: type: array items: type: string description: List of origins (domains) authorized to embed this widget. Product: type: object description: 'A phone-number product owned by the organization — either a platform-rented number (`productType: telephony`) or a SIP-imported number (`productType: custom-telephony`).' properties: _id: type: string description: 24-char MongoDB ObjectId. Use this as `productId` when releasing, or assign to an agent via `PATCH /agent/{agentId}`. example: "6969109c84c74bed175f02a7" productType: type: string enum: [telephony, custom-telephony] description: | - `telephony` — number rented via the Atoms platform (Plivo/Twilio). - `custom-telephony` — number imported via `POST /product/import-phone-number` with the customer's own SIP trunk. example: "telephony" isActive: type: boolean description: Whether the number is currently billable / serving traffic. example: true attributes: type: object description: Provider-specific number metadata. properties: provider: type: string enum: [plivo, twilio] phoneNumber: type: string description: E.164 format including `+`. example: "+912268093636" agentId: type: string nullable: true description: 24-char MongoDB ObjectId of the agent this number is assigned to, if any. `null` when unassigned. example: "69edad34780a67ce987d3f42" createdAt: type: string format: date-time updatedAt: type: string format: date-time 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. Model `waves_lightning_v3_1` validates `voiceId` against the Waves API. `gpt-realtime` and `gpt-realtime-mini` accept any voiceId. Cloned voices are regular voiceIds. Use them with a compatible Waves model. properties: voiceConfig: type: object description: Voice configuration for the synthesizer. properties: model: type: string enum: - waves_lightning_v3_1 - gpt-realtime - gpt-realtime-mini default: waves_lightning_v3_1 description: | The TTS model to use. Use `waves_lightning_v3_1` for the recommended Waves voice path (default), or `gpt-realtime` / `gpt-realtime-mini` for OpenAI realtime models (require `workflowType: single_prompt`). 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_v3_1 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: type: object description: | Config payload for editing a draft via `PATCH /agent/{id}/drafts/{draftId}/config`. All fields are optional — only the fields provided are updated. A subset of config fields from `CreateAgentRequest` is accepted, plus two versioning-era fields. **Fields NOT accepted here** (use `PATCH /agent/{id}` instead): - `name` — agent metadata, not a config field; sending it alone returns 400 "No recognized config fields" - `telephonyProductId` — agent metadata, not a config field properties: singlePromptConfig: $ref: "#/components/schemas/SinglePromptConfig" postCallAnalyticsConfig: $ref: "#/components/schemas/PostCallAnalyticsConfig" language: type: object description: Language configuration. See CreateAgentRequest for full shape. synthesizer: type: object description: Synthesizer (TTS) configuration. See CreateAgentRequest for full shape. slmModel: type: string enum: - electron - electron-kogta - electron-kogta-v2 - gpt-4o - gpt-4.1 - gpt-5.2 - gpt-realtime - gpt-realtime-mini description: LLM model for this draft transcriberType: type: string description: STT engine to use for this draft customLLMWebSocketUrl: type: string description: Custom LLM WebSocket URL (overrides slmModel) widgetConfig: type: object description: Widget configuration for chat-mode agents defaultVariables: type: object description: Default prompt variables preCallAPI: type: object description: Pre-call API configuration. See CreateAgentRequest for full shape. globalPrompt: type: string maxLength: 4000 description: Global prompt for workflow_graph agents (max 4000 characters) globalKnowledgeBaseId: type: string description: Knowledge base ID to attach to this draft firstMessage: type: string description: Opening message for this draft allowInterruptions: type: boolean waitForUserToSpeakFirst: type: boolean muteUserUntilFirstBotResponse: type: boolean interruptionBackoffTimer: type: number minimum: 0 maximum: 10 backgroundSound: type: string enum: ["", "office", "cafe", "call_center", "static"] smartTurnConfig: type: object voiceDetectionConfig: type: object voiceMailDetectionConfig: type: object denoisingConfig: type: object redactionConfig: type: object pronunciationDicts: type: array items: type: object llmIdleTimeoutConfig: type: object sessionTimeoutConfig: type: object workflowType: $ref: "#/components/schemas/WorkflowType" timezone: type: object callDispositionConfig: type: string enableStyleGuide: type: boolean speechFormatting: type: boolean 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 TTS model of the synthesizer. Use `waves_lightning_v3_1` for the recommended Waves voice path (default), or `gpt-realtime` / `gpt-realtime-mini` for OpenAI realtime models. enum: - waves_lightning_v3_1 - gpt-realtime - gpt-realtime-mini default: waves_lightning_v3_1 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 activeVersionId: type: string description: ID of the currently-active published version. Matches `versionId`. versionId: type: string description: Alias for `activeVersionId`. allowInboundCall: type: boolean default: true description: Whether the agent accepts inbound calls. phoneNumber: type: array items: type: string description: | Phone numbers attached to this agent (E.164 strings). Only present when the agent has been linked to one or more telephony products. visibleToEveryone: type: boolean default: false description: Whether the agent is visible to all members of the organization (vs. only the creator). speechFormatting: type: boolean description: | Apply LLM-side speech formatting (e.g. expanding "$100" to "one hundred dollars") before passing text to the synthesizer. Boolean; no default — when unset the platform applies the per-organization default. muteUserUntilFirstBotResponse: type: boolean default: false description: When true, the user microphone is muted until the agent has spoken its first response. interruptionBackoffTimer: type: number description: Seconds to wait after an interruption before the agent resumes speaking. enableStyleGuide: type: boolean default: true description: Whether to apply the platform's style-guide post-processing on agent responses. callDispositionConfig: type: string default: "" description: Free-form prompt used for call disposition classification (separate from `postCallAnalyticsConfig.dispositionMetrics`). voiceMailDetectionConfig: type: object description: Voicemail detection settings. properties: enabled: type: boolean default: false endText: type: string default: "Terminating call, you can call us back anytime. Thank you for calling." description: Text spoken before the call is terminated when voicemail is detected. smartTurnConfig: type: object description: Smart end-of-turn detection settings. properties: isEnabled: type: boolean waitTimeInSecs: type: number minimum: 0 maximum: 10 voiceDetectionConfig: type: object description: VAD (voice activity detection) tuning. properties: confidence: type: number minimum: 0 maximum: 1 minVolume: type: number minimum: 0 maximum: 1 triggerTimeInSecs: type: number minimum: 0 maximum: 10 releaseTimeInSecs: type: number minimum: 0 maximum: 10 denoisingConfig: type: object description: Audio denoising settings. properties: isEnabled: type: boolean redactionConfig: type: object description: PII/PCI redaction settings applied to transcripts. properties: isEnabled: type: boolean pronunciationDicts: type: array description: Custom pronunciation dictionary applied before synthesis. items: type: object required: [word, pronunciation] properties: word: type: string pronunciation: type: string llmIdleTimeoutConfig: type: object description: | Per-channel idle timeouts (seconds) after which the LLM is nudged when the user stops speaking. `maxRetries` bounds how many nudges before the call ends. properties: chatTimeoutTimeInSecs: type: number webcallTimeoutTimeInSecs: type: number telephonyTimeoutTimeInSecs: type: number maxRetries: type: number sessionTimeoutConfig: type: object description: Maximum session duration before the call is automatically ended. properties: timeoutTimeInSecs: type: number timezone: type: object description: Agent timezone — used for time-of-day-sensitive prompts and analytics bucketing. properties: label: type: string default: "(GMT+0:00) UTC" offset: type: number default: 0 postCallAnalyticsConfig: $ref: "#/components/schemas/PostCallAnalyticsConfig" widgetConfig: type: object description: | Chat-widget rendering configuration (theme, copy, consent prompt). Only relevant when the agent is exposed via the embeddable widget; ignored by voice-only agents. properties: position: type: string enum: [bottom-right, bottom-left, top-right, top-left] default: bottom-right size: type: string enum: [tiny, compact, full] default: full mode: type: string enum: [chat, voice] default: chat theme: type: string enum: [light, dark] default: light baseColor: type: string default: "#ffffff" accentColor: type: string default: "#2d9d9f" agentBubbleColor: type: string default: "#f3f4f6" textOnAccentColor: type: string default: "#FFFFFF" secondaryTextColor: type: string default: "#6b7280" primaryTextColor: type: string default: "#111827" startButtonText: type: string default: Start endButtonText: type: string default: End ctaName: type: string default: Talk to Atoms widgetName: type: string default: Atoms avatarUrl: type: string nullable: true chatPlaceholder: type: string default: "Type your message..." consentRequired: type: boolean default: false consentTitle: type: string default: "Privacy Agreement" consentContent: type: string description: Long-form consent body shown before the user can interact. assistantId: type: string nullable: true allowlist: type: array items: type: string description: Allowed origin hostnames for widget embedding. _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 publishedAt: type: string format: date-time nullable: true description: When this version was published activatedBy: type: string nullable: true description: User ID of who activated this version activatedAt: type: string format: date-time nullable: true description: When this version was activated 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 AgentVersionDiff: type: object description: Section-by-section diff between two version or draft revision records. properties: unchangedSections: type: array description: Config sections that did not change. items: type: string diffs: type: array description: Config sections with one or more changes. items: type: object properties: section: type: string description: Config section name. changes: type: array items: type: object properties: path: type: string description: Path to the changed value within the section. oldValue: nullable: true description: Previous value. Can be any JSON value or null. oneOf: - type: string - type: number - type: boolean - type: object additionalProperties: true - type: array items: {} newValue: nullable: true description: New value. Can be any JSON value or null. oneOf: - type: string - type: number - type: boolean - type: object additionalProperties: true - type: array items: {} AgentVersionMetrics: type: object properties: orgId: type: string agentId: type: string versionId: type: string totalCalls: type: number answeredCalls: type: number avgDurationMs: type: number completionRate: type: number totalCost: type: number hangupSourceDistribution: type: object additionalProperties: type: number period: type: object description: Date range used for the metric aggregation. additionalProperties: true AgentVersionMetricsComparison: type: object properties: configDiff: $ref: "#/components/schemas/AgentVersionDiff" metrics: type: object properties: versionA: $ref: "#/components/schemas/AgentVersionMetrics" versionB: $ref: "#/components/schemas/AgentVersionMetrics" deltas: type: object properties: totalCalls: type: number answeredCalls: type: number avgDurationMs: type: number completionRate: type: number totalCost: type: number 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. Must be a valid MongoDB ObjectId (24-char hex). Sending a non-ObjectId format returns 400. sourceDraftId: type: string description: ID of an existing draft to branch from draftName: type: string minLength: 1 maxLength: 100 description: Optional name for the draft (1–100 characters) 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. Defaults to `webcall` when omitted. toPhone: type: string description: | Phone number to call. Required only when `mode` is `telephony`. Omit for `webcall` and `chat`. # ── v2 branch model schemas ───────────────────────────────────────── Branch: type: object description: An `AgentBranch` document. An editable copy of an agent with its own draft slot and revision chain. properties: _id: type: string description: Branch ID (24-character ObjectId). agent: type: string description: ID of the agent this branch belongs to. name: type: string minLength: 1 maxLength: 100 description: Branch name (unique per agent among active branches). `main` is reserved for the default branch. isDefault: type: boolean description: "True for the seeded `main` branch. The default branch cannot be renamed or archived." sourceBranchId: type: string nullable: true description: Head of the source branch at fork time. `null` for `main`. sourceRevisionId: type: string nullable: true description: Revision the branch was forked from. `null` for `main`. headRevisionId: type: string nullable: true description: ID of the branch's latest committed revision. `null` until the first commit. openDraftId: type: string nullable: true description: ID of the branch's single open draft. `null` when no draft is open. status: type: string enum: [active, archived] description: Archived branches are hidden from list views and cannot receive draft edits or be made live. createdBy: type: string updatedBy: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time BranchSummary: type: object description: Branch document plus derived fields used by list and detail views. properties: branch: $ref: "#/components/schemas/Branch" isLive: type: boolean description: True when the agent's live config points at this branch. hasOpenDraft: type: boolean revisionsCount: type: integer headRevisionNumber: type: integer nullable: true VersionBlocks: type: object description: ObjectId references to the `AgentConfigBlock` docs that make up a revision, one per config section. 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 playbooks: type: string description: Only present on revisions created after multi-agent playbooks shipped. PromptScore: type: object nullable: true description: Result of the prompt-scoring pass, if any. properties: overall_score: type: number overall_grade: type: string band: type: string estimated_ttft_overhead_ms: type: number scoredAt: type: string format: date-time dimensions: type: array items: type: object properties: tier: type: integer level: type: string evidence_span: type: string title: type: string description: type: string Revision: type: object description: | An `AgentVersion` document. Represents either a committed revision (`status: published`, with `branch` + `revisionNumber`) or an in-progress draft revision (`status: draft`, with `draftId` + `draftRevision`). Fields that do not apply to a given row are `null`. properties: _id: type: string agent: type: string status: type: string enum: [published, draft, archived] branch: type: string nullable: true description: Owning branch (v2). `null` on legacy rows until backfilled. revisionNumber: type: integer nullable: true description: Monotonic per-branch commit number. Only set on committed rows. versionNumber: type: integer nullable: true description: Legacy v1 published-version number. `null` for branch revisions and drafts. label: type: string nullable: true description: type: string nullable: true isPinned: type: boolean publishedBy: type: string nullable: true publishedAt: type: string format: date-time nullable: true publishedByName: type: string nullable: true description: Display name of the publisher. `null` when unresolvable. restoredFromLabel: type: string nullable: true description: On a commit produced by restore, the label of the revision it copied. draftId: type: string nullable: true draftName: type: string nullable: true draftRevision: type: integer nullable: true sourceVersionId: type: string nullable: true blocks: $ref: "#/components/schemas/VersionBlocks" workflowType: type: string description: The `WorkflowType` enum for this revision. parentVersion: type: string nullable: true isActive: type: boolean activatedBy: type: string nullable: true activatedAt: type: string format: date-time nullable: true securityCheck: type: object nullable: true description: Populated after publish. `null` on pre-feature versions. properties: status: type: string description: The `SecurityCheckStatus` enum. reason: type: string nullable: true triggeredAt: type: string format: date-time nullable: true completedAt: type: string format: date-time nullable: true pendingPublish: type: object nullable: true description: Set while a publish is armed against this draft revision. properties: state: type: string enum: [active, cancelled] startedBy: type: string startedAt: type: string format: date-time restoredFromRevisionId: type: string nullable: true description: On a commit produced by restore, the revision it copied. sourceDraftId: type: string nullable: true promptScore: $ref: "#/components/schemas/PromptScore" promptScoreStale: type: boolean createdBy: type: string createdAt: type: string format: date-time updatedAt: type: string format: date-time DraftDetail: type: object description: Returned by `GET /agent/{id}/branches/{branchId}/draft`. properties: latest: $ref: "#/components/schemas/Revision" editCount: type: integer editHistory: type: array items: type: object properties: revision: $ref: "#/components/schemas/Revision" changedSections: type: array items: type: string editorName: type: string nullable: true description: Display name of the editor who made this draft edit. `null` when the editor's display name is not resolvable. DiffChange: type: object properties: path: type: string description: Dot-path to the changed leaf field. oldValue: nullable: true newValue: nullable: true DiffSection: type: object properties: section: type: string changes: type: array items: $ref: "#/components/schemas/DiffChange" DiffResult: type: object description: Returned by `GET /agent/{id}/diff`. properties: unchangedSections: type: array items: type: string diffs: type: array items: $ref: "#/components/schemas/DiffSection" TestCallResult: type: object description: Returned by `POST /agent/{id}/branches/{branchId}/test-call`. required: - conversationId - callId properties: conversationId: type: string callId: type: string token: type: string description: LiveKit access token. Returned for `webcall` and `chat` modes only. roomName: type: string description: Returned for `webcall` and `chat` modes only. host: type: string description: Returned for `webcall` and `chat` modes only. CreateBranchRequest: type: object required: - sourceBranchId - name properties: sourceBranchId: type: string pattern: "^[a-f\\d]{24}$" description: Branch to fork from. Its head revision must exist. name: type: string minLength: 1 maxLength: 100 description: New branch name. Unique per agent among active branches. `main` is reserved. RenameBranchRequest: type: object required: - name properties: name: type: string minLength: 1 maxLength: 100 UpdateBranchDraftRequest: type: object description: | Agent config partial. Send the same camelCase field names you see on the `GET /agent/{id}` response body. The server routes each field into the correct internal config-block section (`workflow_prompt`, `llm`, `voice`, `language`, `call_handling`, `detection`, `analytics`, `timeouts`, `audio`, `privacy`, `widget`, `playbooks`) for you. Sending an internal section name at the top level returns `400 "No recognized config fields in request body"`. The request must carry at least one recognized config field. Every property below is optional. Send only the subset you want to change. For the exact shape of complex nested objects (`synthesizer`, `language`, `preCallAPI`, `smartTurnConfig`, etc.) see the matching field on `CreateAgentRequest` — the accepted shape is the same. `additionalProperties: true` remains on so callers can send new fields the platform adds later without a spec bump, but the typed fields below are the stable public surface for SDK method signatures. additionalProperties: true properties: expectedRevision: type: integer minimum: 0 description: | Optimistic-concurrency control. The `draftRevision` the client's edit was based on. When present, the server runs a field-level conflict check and rejects with `409 DraftConflictError` if the same field was changed by another edit since. Omit for last-write-wins semantics (which is also how a client force-overwrites after a `409`). Referencing a non-existent base revision returns `409 { errors: ["base_revision_unavailable"] }`. globalPrompt: type: string description: Top-level system prompt shown to the agent every turn. firstMessage: type: string description: The agent's opening line at call start. slmModel: type: string enum: [electron, electron-kogta, electron-kogta-v2, gpt-4o, gpt-4.1, gpt-5.2, gpt-realtime, gpt-realtime-mini] description: LLM model powering the agent. See `CreateAgentRequest.slmModel` for org-level access notes. backgroundSound: type: string enum: ["", office, cafe, call_center, static] description: Ambient background sound during calls. timezone: type: string description: IANA timezone identifier used for date/time interpretation in prompts and tool calls. globalKnowledgeBaseId: type: string description: Knowledge base attached to the agent for retrieval-augmented responses. muteUserUntilFirstBotResponse: type: boolean allowInterruptions: type: boolean waitForUserToSpeakFirst: type: boolean interruptionBackoffTimer: type: number enableStyleGuide: type: boolean synthesizer: type: object description: TTS (voice) configuration. Same shape as `CreateAgentRequest.synthesizer`. language: type: object description: Language configuration. Same shape as `CreateAgentRequest.language`. defaultVariables: type: object description: Default variables injected into prompts and tool calls. preCallAPI: type: object description: Pre-call API webhook config. Same shape as `CreateAgentRequest.preCallAPI`. smartTurnConfig: type: object voiceDetectionConfig: type: object voiceMailDetectionConfig: type: object denoisingConfig: type: object redactionConfig: type: object pronunciationDicts: type: object llmIdleTimeoutConfig: type: object sessionTimeoutConfig: type: object callDispositionConfig: type: object speechFormatting: type: object PublishBranchDraftRequest: type: object properties: label: type: string maxLength: 200 nullable: true description: Optional label saved on the committed revision. PublishResult: type: object description: | Result of publish or restore. - `state: "committed"` (HTTP `200`) is returned when the commit is synchronous. This happens for restore (the source revision has already been scanned) and for publishes whose content does not need a fresh scan. The response includes the new revision object under `revision`. - `state: "scanning"` (HTTP `202`) is returned when a security scan is deferred. In this case the response body carries only `state`. `revision` is absent, and clients must list the branch's revisions newest-first (`GET /agent/{id}/branches/{branchId}/revisions?limit=1`) to obtain the new revision ID. Then poll `GET /agent/{id}/branches/{branchId}/revisions/{revisionId}` until `revision.status` flips from any transient value to `"published"`. On the revision doc the lifecycle field is `status` (not `state`), and the security-scan sub-lifecycle is on the nested `securityCheck.status`. properties: state: type: string enum: [scanning, committed] revision: nullable: true description: "The newly committed revision. Populated when `state` is `committed`, absent when `state` is `scanning`." allOf: - $ref: "#/components/schemas/Revision" TestCallV2Request: type: object description: | Body for `POST /agent/{id}/branches/{branchId}/test-call`. When both `includeDraft` and `revisionId` are omitted, the branch's committed head is used. properties: includeDraft: type: boolean default: false description: When `true`, the test call uses the branch's open draft. Mutually exclusive with `revisionId`. revisionId: type: string pattern: "^[a-f\\d]{24}$" description: "Test against a specific committed revision on the branch. Mutually exclusive with `includeDraft: true`." mode: type: string enum: [webcall, chat, telephony] default: webcall toPhone: type: string description: E.164-formatted number. Required when `mode` is `telephony`. Omit for `webcall` and `chat`. ConflictErrorResponse: type: object description: | Generic conflict body. `error_type` is a stable machine-readable discriminator (for example `branch_name_exists`, `source_has_no_commit`, `source_scanning`, `publish_in_progress`, `no_committed_revision`). properties: status: type: boolean example: false error_type: type: string errors: type: array items: type: string DraftConflictError: type: object description: | Returned by `PUT /agent/{id}/branches/{branchId}/draft` when `expectedRevision` was sent and another edit changed one of the same leaf fields since. `errors` lists the conflicting leaf field paths. `data.conflict` carries the resolution context: the client's expected revision, the current draft revision, and per-field diffs. required: - status - errors properties: status: type: boolean example: false errors: type: array items: type: string data: type: object properties: conflict: type: object properties: expectedRevision: type: integer latestRevision: type: integer diffs: type: array items: type: object additionalProperties: true LockedErrorResponse: type: object description: | Config-freeze body. Returned on write endpoints during a maintenance window (`AGENT_CONFIG_FROZEN`). Reads and test-calls pass. properties: status: type: boolean example: false error_type: type: string enum: [config_freeze_active] errors: type: array items: type: string VersioningV2MigrationRequiredResponse: type: object description: | Returned by deprecated v1 versioning writes and list reads when `ENABLE_BRANCH_MODEL` is on. Response header carries `Deprecation: true`. The `error_type` value is a stable discriminator. properties: status: type: boolean example: false error_type: type: string enum: [versioning_v2_migration_required] errors: type: array items: type: string # ── end v2 branch model schemas ───────────────────────────────────── 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. Returned by both `GET /webhook` (list) and `GET /webhook?webhookId=` (single). Use as the HMAC-SHA256 key when verifying the `X-Signature` header on incoming webhook deliveries. 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 BillingBalanceResponse: type: object required: [success, data] properties: success: type: boolean example: true data: type: object required: [creditBalance, planId, isEnterprise] properties: creditBalance: type: number description: Current credit balance in USD. May be negative if the account has spent past its balance and is on a plan that permits overdraw. example: 15 planId: type: string description: Identifier for the plan the organization is on. example: plan_standard isEnterprise: type: boolean description: True when the organization is on an enterprise plan (billed offline). example: false BillingLedgerEntry: type: object required: [id, transactionType, amount, balanceAfter, createdAt] properties: id: type: string description: Ledger row identifier. transactionType: type: string enum: - SIGNUP_BONUS - CREDIT_PURCHASE - AUTO_RELOAD - USAGE_DEDUCTION - ADMIN_ADJUSTMENT - COUPON_CREDIT - MIGRATION amount: type: number description: Signed credit delta in USD. Positive for additions (`CREDIT_PURCHASE`, `AUTO_RELOAD`, `COUPON_CREDIT`, `SIGNUP_BONUS`), negative for spend (`USAGE_DEDUCTION`). balanceAfter: type: number description: Balance after this row was applied. featureId: type: string nullable: true description: Product feature that triggered the row (e.g. `tts.generate`, `waves.stt`). Only set on `USAGE_DEDUCTION`. referenceId: type: string nullable: true description: External reference tying this row to a purchase, coupon, or admin action. description: type: string nullable: true createdAt: type: string format: date-time callId: type: string nullable: true description: Associated call ID, when the row was produced by a call. agentId: type: string nullable: true requestId: type: string nullable: true BillingLedgerResponse: type: object required: [success, data] properties: success: type: boolean example: true data: type: object required: [transactions, total, hasMore, summary, period] properties: transactions: type: array items: $ref: "#/components/schemas/BillingLedgerEntry" total: type: integer description: Total row count matching the filters (across all pages). hasMore: type: boolean description: True when more rows exist beyond `offset + limit`. summary: type: object required: [totalCreditsConsumed, totalCreditsAdded] properties: totalCreditsConsumed: type: number description: Sum of `USAGE_DEDUCTION` magnitudes across the window. totalCreditsAdded: type: number description: Sum of positive rows (purchases, auto-reloads, coupon credits, signup bonuses) across the window. period: type: object required: [from, to] properties: from: type: string format: date-time description: Echo of the effective lower bound (defaults to seven days before `to` when not supplied). to: type: string format: date-time description: Echo of the effective upper bound (defaults to server-now when not supplied). BillingUsageBreakdownResponse: type: object required: [success, data] properties: success: type: boolean example: true data: type: object required: [platform, voiceAi, voiceModels] properties: platform: type: number description: Credits spent on Atoms platform features (phone rental, telephony minutes, etc.). voiceAi: type: number description: Credits spent on voice-agent runtime (LLM + TTS combined during voice calls). voiceModels: type: number description: Credits spent on standalone Waves model calls (Lightning TTS, Pulse STT, Electron LLM used outside the voice-agent pipeline). BillingInvoiceListResponse: type: object required: [success, data] properties: success: type: boolean example: true data: type: array description: | Up to 20 recent Stripe `Invoice` objects for the caller's organization. Fields follow the canonical Stripe shape. Keys most callers use: `id`, `status`, `amount_paid`, `amount_due`, `currency`, `created`, `hosted_invoice_url`, `invoice_pdf`, `number`. items: type: object additionalProperties: true BillingInvoicePdfResponse: type: object required: [success, data] properties: success: type: boolean example: true data: type: object required: [pdfUrl] properties: pdfUrl: type: string format: uri description: Stripe-hosted URL to the invoice PDF. Short-lived; refetch when you need to hand it to a user. 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" WorkflowGraphAgentAccessForbiddenError: description: Forbidden. Returned for workflow_graph agents when the organization lacks conversational agents 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" BadRequestErrorResponse: description: Bad request — validation failed or required field missing. content: application/json: schema: $ref: "#/components/schemas/BadRequestErrorResponse" NotFoundErrorResponse: description: Resource not found. The referenced ID does not exist or does not belong to the caller's organization. content: application/json: schema: type: object properties: status: type: boolean example: false errors: type: array items: type: string example: ["Resource not found"] ConflictErrorResponse: description: Conflict. The request cannot be completed because of the current state of the resource (name already exists, another publish or restore is in progress, the source draft failed its security scan, or a similar in-flight collision). content: application/json: schema: $ref: "#/components/schemas/ConflictErrorResponse" LockedErrorResponse: description: Locked. A configuration freeze is active on this agent, or the resource is temporarily locked for another write. Retry after the freeze window ends. content: application/json: schema: $ref: "#/components/schemas/LockedErrorResponse" VersioningV2MigrationRequired: description: | The v1 versioning endpoint is deprecated on the branch model and will not process this request. The response body carries `error_type: "versioning_v2_migration_required"` and the response includes the `Deprecation: true` header. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration) for the v2 equivalent. headers: Deprecation: description: Always `true` for deprecated endpoints. schema: type: string example: "true" content: application/json: schema: $ref: "#/components/schemas/VersioningV2MigrationRequiredResponse" tags: - name: DNC description: Do-Not-Call registry entries scoped to the organization (optionally further scoped to a single agent). Entries are added automatically from call outcomes or manually via CSV upload. - name: Integrations description: Third-party platform integrations. Currently supports WebEngage — a customer engagement platform. Credentials are stored per organization as one or more integration sets. - name: Concurrency description: Manage organization-wide concurrency limits and per-agent call slot reservations across webcall, outbound, inbound, and chat channels. - name: Disposition Metric Templates description: Reusable post-call analytics metric definitions. Each template specifies an identifier, an AI extraction prompt, and a value type (STRING, BOOLEAN, INTEGER, ENUM, DATETIME). - name: Call Actions description: Automated behaviors that fire at specific points in the call lifecycle — trigger actions initiate outbound calls, post-call actions update CRM records after a call ends. - name: Analytics description: Analytics and reporting endpoints for call metrics, trends, usage, and dashboard data. - name: Prompt Scoring description: Score and analyse agent prompts across quality dimensions - 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: Realtime Agent description: Start a realtime voice or chat session with an agent over a WebSocket. Use `POST /conversation/register-call` to mint a short-lived access token, then open the Agent WebSocket with it. - 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 - Branches description: | Manage editable copies of an agent. Every editable copy is a branch. Each agent has a `Main` branch by default; you can create more branches from any branch that has at least one committed revision. Exactly one branch per agent is **live** and serves production traffic. `Main` cannot be renamed or deleted; the live branch cannot be deleted or archived until another branch is made live. Requires `ENABLE_BRANCH_MODEL`. - name: Agent Versioning - Revisions description: | Read and restore committed revisions on a branch. A revision is an immutable snapshot of an agent's configuration created when a draft is published. Revisions belong to exactly one branch. Restoring a revision republishes it as a new revision on the same branch. Requires `ENABLE_BRANCH_MODEL`. - name: Agent Versioning - Drafts description: | **Deprecated on the v2 branch model.** Use `PUT`/`GET`/`DELETE /agent/{id}/branches/{branchId}/draft` and `POST /agent/{id}/branches/{branchId}/draft/publish`. When `ENABLE_BRANCH_MODEL` is on, list + write endpoints under this tag return `409 versioning_v2_migration_required` with `Deprecation: true`. See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). - name: Agent Versioning - Versions description: | **Deprecated on the v2 branch model.** Under the branch model, `activate` is gone (a branch is made live via `POST /agent/{id}/branches/{branchId}/live`) and only `label` (set at publish) is metadata-editable. When `ENABLE_BRANCH_MODEL` is on, list + write endpoints under this tag return `409 versioning_v2_migration_required` with `Deprecation: true`. By-id reads and test-calls are kept unchanged and resolve across branches (a v1 `versionId` equals its migrated `revisionId`). See the [migration guide](/voice-agents/deprecations/agent-versioning-migration). - 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. - name: Billing description: | Read-only access to your organization's credit balance, ledger, usage breakdown, and invoices. Authenticate with your user API key (`Authorization: Bearer `); the organization is resolved from the key itself, no `X-Organization-Id` header is required. Only these read endpoints accept the API key. Purchase, auto-reload, and payment-method routes remain UI-only. **Base URL for this section is `https://api.smallest.ai` (not `/atoms/v1`).** servers: - url: https://api.smallest.ai/atoms/v1 description: Production server