{
  "openapi": "3.1.0",
  "info": {
    "title": "OpenMic v1 External API",
    "description": "API specification for OpenMic v1 External API, providing endpoints for bot management, call handling, and phone number operations.",
    "version": "1.0.0"
  },
  "tags": [
    {
      "name": "Calls",
      "description": "Endpoints related to phone call creation and management."
    },
    {
      "name": "Bots",
      "description": "Endpoints related to bot management and configuration."
    },
    {
      "name": "Phone Numbers",
      "description": "Endpoints related to phone number management and bot linking."
    },
    {
      "name": "Knowledge Bases"
    },
    {
      "name": "FAQs"
    },
    {
      "name": "Campaigns"
    },
    {
      "name": "Tools"
    },
    {
      "name": "Contact Lists"
    },
    {
      "name": "Contacts"
    },
    {
      "name": "Voices",
      "description": "Endpoints for browsing available text-to-speech voices. Voices are read-only and can be filtered by gender, provider, language, and accent."
    },
    {
      "name": "SMS",
      "description": "Endpoints for sending SMS messages."
    }
  ],
  "security": [
    {
      "api_key": []
    }
  ],
  "paths": {
    "/v1/bots": {
      "post": {
        "summary": "Create Bot",
        "description": "Create a new bot with specified configuration.",
        "tags": ["Bots"],
        "requestBody": {
          "description": "Bot configuration details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBotRequest"
              },
              "example": {
                "name": "Customer Support Bot",
                "prompt": "You are a helpful customer support assistant. Be polite, professional, and always try to resolve customer issues.",
                "first_message": "Hello! I'm here to help you with any questions or concerns you may have. How can I assist you today?",
                "knowledge_base_id": 123,
                "voice_provider": "OpenAI",
                "voice": "alloy",
                "voice_model": "tts-1",
                "voice_speed": 1.0,
                "llm_model_name": "gpt-4",
                "llm_model_temperature": 0.7,
                "stt_provider": "Deepgram",
                "stt_model": "nova-2",
                "call_settings": {
                  "max_call_duration": 10,
                  "silence_timeout": 15,
                  "silence_timeout_max_retries": 3,
                  "silence_timeout_message": "I didn't hear anything. Are you still there?",
                  "call_recording_enabled": true,
                  "voicemail_detection_enabled": true,
                  "voicemail_action": "leave_message",
                  "voicemail_message_type": "static",
                  "voicemail_message": "Hey, sorry we couldn't reach you directly. Please give us a callback if you can.",
                  "hipaa_compliance_enabled": false,
                  "pci_compliance_enabled": false
                },
                "advanced_settings": {
                  "agent_personality": "friendly",
                  "humanize_conversation": true,
                  "background_noise_reduction": true,
                  "allow_interruptions": true,
                  "min_interruption_duration": 0.5,
                  "agent_response_length": "normal",
                  "short_pause": 0.3,
                  "long_pause": 1.0
                },
                "post_call_settings": {
                  "summary_prompt": "Provide a brief summary of the customer interaction and any action items.",
                  "success_evaluation_prompt": "Rate the success of this call on a scale of 1-10 based on customer satisfaction.",
                  "success_evaluation_rubric_type": "NUMERIC_SCALE"
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Bot created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BotResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid request format, please check API reference."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      },
      "get": {
        "summary": "List Bots",
        "description": "Retrieve all bots with optional filtering and pagination.",
        "tags": ["Bots"],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of bots to return (1-100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of bots to skip",
            "schema": { "type": "integer", "minimum": 0 }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Filter by bot name (partial match)",
            "schema": { "type": "string" }
          },
          {
            "name": "created_after",
            "in": "query",
            "description": "Filter bots created after this date (ISO 8601 format)",
            "schema": { "type": "string", "format": "date-time" }
          },
          {
            "name": "created_before",
            "in": "query",
            "description": "Filter bots created before this date (ISO 8601 format)",
            "schema": { "type": "string", "format": "date-time" }
          }
        ],
        "responses": {
          "200": {
            "description": "List of bots retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListBotsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid query parameters provided."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/v1/bots/{bot_uid}": {
      "get": {
        "summary": "Get Bot",
        "description": "Retrieve details of a specific bot by its ID.",
        "tags": ["Bots"],
        "parameters": [
          {
            "name": "bot_uid",
            "in": "path",
            "description": "The unique identifier of the bot",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Bot details retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BotResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid organization/account information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Missing or invalid organization information"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "404": {
            "description": "Bot not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Bot with the specified ID was not found."
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      },
      "patch": {
        "summary": "Update Bot",
        "description": "Update an existing bot's configuration.",
        "tags": ["Bots"],
        "parameters": [
          {
            "name": "bot_uid",
            "in": "path",
            "description": "The unique identifier of the bot",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "requestBody": {
          "description": "Updated bot configuration",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateBotRequest"
              },
              "example": {
                "name": "Updated Customer Support Bot",
                "prompt": "You are an advanced customer support assistant with expertise in technical issues.",
                "voice_speed": 1.1,
                "llm_model_temperature": 0.8,
                "call_settings": {
                  "max_call_duration": 15,
                  "silence_timeout": 20,
                  "voicemail_detection_enabled": true,
                  "voicemail_action": "leave_message",
                  "voicemail_message_type": "prompt",
                  "voicemail_message": "Generate a voicemail explaining why I called based on the customer's recent support ticket."
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bot updated successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BotResponse"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Bot not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      },
      "delete": {
        "summary": "Delete Bot",
        "description": "Delete a bot by its ID.",
        "tags": ["Bots"],
        "parameters": [
          {
            "name": "bot_uid",
            "in": "path",
            "description": "The unique identifier of the bot",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "204": {
            "description": "Bot deleted successfully"
          },
          "400": {
            "description": "Bad request - missing or invalid organization/account information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "404": {
            "description": "Bot not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "409": {
            "description": "Conflict - bot is currently in use",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/v1/bots/{bot_uid}/tools": {
      "post": {
        "summary": "Create Tool",
        "description": "Create a new tool for a bot. Tools extend bot capabilities with actions like API calls, call transfers, SMS sending, etc.",
        "tags": ["Tools"],
        "operationId": "createToolExt",
        "parameters": [
          {
            "name": "bot_uid",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The unique identifier of the bot."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateToolRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Tool created successfully.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ToolResponse" }
              }
            }
          },
          "400": {
            "description": "Invalid request (missing fields, validation error)"
          },
          "404": { "description": "Bot not found" }
        }
      },
      "get": {
        "summary": "List Tools",
        "description": "Retrieve a paginated list of tools for a bot.",
        "tags": ["Tools"],
        "operationId": "listToolsExt",
        "parameters": [
          {
            "name": "bot_uid",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The unique identifier of the bot."
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Max tools to return (1-100)."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": { "type": "integer", "minimum": 0, "default": 0 },
            "description": "Number of tools to skip."
          },
          {
            "name": "type",
            "in": "query",
            "schema": { "$ref": "#/components/schemas/ToolType" },
            "description": "Filter by tool type."
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": { "type": "string", "format": "date-time" },
            "description": "Filter tools created after this date."
          },
          {
            "name": "created_before",
            "in": "query",
            "schema": { "type": "string", "format": "date-time" },
            "description": "Filter tools created before this date."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of tools.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ListToolsResponse" }
              }
            }
          },
          "404": { "description": "Bot not found" }
        }
      }
    },
    "/v1/bots/{bot_uid}/tools/{tool_id}": {
      "get": {
        "summary": "Get Tool",
        "description": "Retrieve details of a specific tool.",
        "tags": ["Tools"],
        "operationId": "getToolExt",
        "parameters": [
          {
            "name": "bot_uid",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The unique identifier of the bot."
          },
          {
            "name": "tool_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "The numeric ID of the tool."
          }
        ],
        "responses": {
          "200": {
            "description": "Tool details.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ToolResponse" }
              }
            }
          },
          "400": { "description": "Invalid tool_id" },
          "404": { "description": "Tool or bot not found" }
        }
      },
      "patch": {
        "summary": "Update Tool",
        "description": "Update an existing tool. Only provided fields are updated.",
        "tags": ["Tools"],
        "operationId": "updateToolExt",
        "parameters": [
          {
            "name": "bot_uid",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The unique identifier of the bot."
          },
          {
            "name": "tool_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "The numeric ID of the tool."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UpdateToolRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated tool.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ToolResponse" }
              }
            }
          },
          "400": { "description": "Invalid request" },
          "404": { "description": "Tool or bot not found" }
        }
      },
      "delete": {
        "summary": "Delete Tool",
        "description": "Delete a tool from a bot.",
        "tags": ["Tools"],
        "operationId": "deleteToolExt",
        "parameters": [
          {
            "name": "bot_uid",
            "in": "path",
            "required": true,
            "schema": { "type": "string" },
            "description": "The unique identifier of the bot."
          },
          {
            "name": "tool_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "The numeric ID of the tool."
          }
        ],
        "responses": {
          "204": { "description": "Tool deleted successfully." },
          "404": { "description": "Tool or bot not found" }
        }
      }
    },
    "/v1/create-phone-call": {
      "post": {
        "summary": "Create Phone Call",
        "description": "Create a new outbound phone call.",
        "tags": ["Calls"],
        "requestBody": {
          "description": "Call creation details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCallRequest"
              },
              "example": {
                "from_number": "+1234567890",
                "to_number": "+0987654321",
                "override_agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                "customer_id": "customer_001",
                "dynamic_variables": { "name": "John" },
                "callback_url": "https://example.com/callback"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Call created successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallResponse"
                },
                "example": {
                  "call_type": "phonecall",
                  "from_number": "+1234567890",
                  "to_number": "+0987654321",
                  "direction": "outbound",
                  "call_id": "cmbbvrg8wzi487w02m2bc7dji",
                  "agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                  "call_status": "registered",
                  "customer_id": "customer_001",
                  "dynamic_variables": {
                    "name": "John"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid request format, please check API reference."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "404": {
            "description": "Resource not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Bot with the specified override_agent_id was not found."
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/v1/call/{id}": {
      "get": {
        "summary": "Get Call",
        "description": "Retrieve details of a specific call by its ID.",
        "tags": ["Calls"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "description": "The unique identifier of the call",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Call details retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallResponse"
                },
                "example": {
                  "call_type": "phonecall",
                  "from_number": "+1234567890",
                  "to_number": "+0987654321",
                  "direction": "outbound",
                  "call_id": "cmbbvrg8wzi487w02m2bc7dji",
                  "agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                  "call_status": "ended",
                  "customer_id": "customer_001",
                  "start_timestamp": 1678886400000,
                  "end_timestamp": 1678886700000,
                  "duration_ms": 300000,
                  "transcript": [
                    ["assistant", "Hello! How can I help you today?"],
                    ["user", "I'd like to schedule an appointment."],
                    [
                      "assistant",
                      "I'd be happy to help you schedule an appointment. What type of service are you looking for?"
                    ]
                  ],
                  "recording_url": "https://recordings.openmic.ai/call_98765.mp3",
                  "latency": {
                    "e2e_min_latency": 0.5,
                    "e2e_median_latency": 1.2,
                    "e2e_p90_latency": 2.1,
                    "llm_min_latency": 0.3,
                    "llm_median_latency": 0.8,
                    "llm_p90_latency": 1.5,
                    "tts_min_latency": 0.2,
                    "tts_median_latency": 0.4,
                    "tts_p90_latency": 0.6
                  },
                  "call_analysis": {
                    "summary": "Customer called to schedule an appointment and was successfully assisted.",
                    "is_successful": true,
                    "success_evaluation": "excellent",
                    "extracted_data": null
                  },
                  "call_cost": {
                    "total_cost": 0.0822,
                    "llm_cost": 0.0052548,
                    "tts_cost": 0.0242269,
                    "stt_cost": 0.0527183
                  },
                  "dynamic_variables": {
                    "name": "John"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid organization/account information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Missing or invalid organization information"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "404": {
            "description": "Call not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Call with the specified ID was not found."
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/v1/calls": {
      "get": {
        "summary": "List Calls",
        "description": "Retrieve all calls with optional filtering and pagination.",
        "tags": ["Calls"],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of calls to return (1-100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of calls to skip",
            "schema": { "type": "integer", "minimum": 0 }
          },
          {
            "name": "customer_id",
            "in": "query",
            "description": "Filter by customer ID",
            "schema": { "type": "string" }
          },
          {
            "name": "from_number",
            "in": "query",
            "description": "Filter by originating phone number",
            "schema": { "type": "string" }
          },
          {
            "name": "to_number",
            "in": "query",
            "description": "Filter by destination phone number",
            "schema": { "type": "string" }
          },
          {
            "name": "bot_uid",
            "in": "query",
            "description": "Filter by bot UID",
            "schema": { "type": "string" }
          },
          {
            "name": "from_date",
            "in": "query",
            "description": "Filter calls from this date (ISO 8601 format)",
            "schema": { "type": "string", "format": "date-time" }
          },
          {
            "name": "to_date",
            "in": "query",
            "description": "Filter calls to this date (ISO 8601 format)",
            "schema": { "type": "string", "format": "date-time" }
          },
          {
            "name": "call_status",
            "in": "query",
            "description": "Filter by call status",
            "schema": {
              "type": "string",
              "enum": ["registered", "ongoing", "ended", "error"]
            }
          },
          {
            "name": "call_type",
            "in": "query",
            "description": "Filter by call type",
            "schema": {
              "type": "string",
              "enum": ["phonecall", "webcall"]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "List of calls retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListCallsResponse"
                },
                "example": {
                  "calls": [
                    {
                      "call_type": "phonecall",
                      "from_number": "+1234567890",
                      "to_number": "+0987654321",
                      "direction": "outbound",
                      "call_id": "cmbbvrg8wzi487w02m2bc7dji",
                      "agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                      "call_status": "ended",
                      "customer_id": "customer_001",
                      "start_timestamp": 1678886400000,
                      "end_timestamp": 1678886700000,
                      "duration_ms": 300000,
                      "transcript": [
                        ["assistant", "Hello! How can I help you today?"],
                        ["user", "I'd like to schedule an appointment."]
                      ],
                      "recording_url": "https://recordings.openmic.ai/call_98765.mp3",
                      "latency": {
                        "e2e_min_latency": 0.5,
                        "e2e_median_latency": 1.2,
                        "e2e_p90_latency": 2.1,
                        "llm_min_latency": 0.3,
                        "llm_median_latency": 0.8,
                        "llm_p90_latency": 1.5,
                        "tts_min_latency": 0.2,
                        "tts_median_latency": 0.4,
                        "tts_p90_latency": 0.6
                      },
                      "call_analysis": {
                        "summary": "Customer called to schedule an appointment and was successfully assisted.",
                        "is_successful": true,
                        "success_evaluation": "excellent",
                        "extracted_data": null
                      },
                      "call_cost": {
                        "total_cost": 0.0822,
                        "llm_cost": 0.0052548,
                        "tts_cost": 0.0242269,
                        "stt_cost": 0.0527183
                      },
                      "dynamic_variables": {
                        "name": "John"
                      }
                    }
                  ],
                  "pagination": {
                    "limit": 1,
                    "offset": 0,
                    "total": 1,
                    "has_more": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid query parameters provided."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phone-numbers": {
      "get": {
        "summary": "List Phone Numbers",
        "description": "Retrieve all phone numbers with optional filtering and pagination.",
        "tags": ["Phone Numbers"],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Maximum number of phone numbers to return (1-100)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100
            }
          },
          {
            "name": "offset",
            "in": "query",
            "description": "Number of phone numbers to skip",
            "schema": { "type": "integer", "minimum": 0 }
          },
          {
            "name": "phone_number",
            "in": "query",
            "description": "Filter by phone number (partial match)",
            "schema": { "type": "string" }
          },
          {
            "name": "name",
            "in": "query",
            "description": "Filter by name (partial match)",
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "List of phone numbers retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListPhoneNumbersResponse"
                },
                "example": {
                  "phone_numbers": [
                    {
                      "phone_number_id": "ybhb8wzi487w02m2bc7dh0ev",
                      "phone_number": "+15551112222",
                      "name": "Main Support Line",
                      "inbound_agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                      "outbound_agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                      "created_at": "2023-01-01T12:00:00Z",
                      "updated_at": "2023-01-02T15:30:00Z"
                    }
                  ],
                  "pagination": {
                    "limit": 1,
                    "offset": 0,
                    "total": 1,
                    "has_more": false
                  }
                }
              }
            }
          },
          "400": {
            "description": "Bad request - invalid parameters",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid query parameters provided."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phone-numbers/{uid}": {
      "get": {
        "summary": "Get Phone Number",
        "description": "Retrieve details of a specific phone number by its UID.",
        "tags": ["Phone Numbers"],
        "parameters": [
          {
            "name": "uid",
            "in": "path",
            "description": "The unique identifier of the phone number",
            "required": true,
            "schema": { "type": "string" }
          }
        ],
        "responses": {
          "200": {
            "description": "Phone number details retrieved successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneNumberResponse"
                },
                "example": {
                  "phone_number_id": "ybhb8wzi487w02m2bc7dh0ev",
                  "phone_number": "+15551112222",
                  "name": "Main Support Line",
                  "inbound_agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                  "outbound_agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                  "created_at": "2023-01-01T12:00:00Z",
                  "updated_at": "2023-01-02T15:30:00Z"
                }
              }
            }
          },
          "400": {
            "description": "Bad request - missing or invalid organization/account information",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Missing or invalid organization information"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "404": {
            "description": "Phone number not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Phone number with the specified UID was not found."
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phone-numbers/link-agent": {
      "post": {
        "summary": "Link Bot to Phone Number",
        "description": "Link a bot (agent) to a phone number for inbound/outbound calls.",
        "tags": ["Phone Numbers"],
        "requestBody": {
          "description": "Bot linking details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkBotToPhoneNumberRequest"
              },
              "example": {
                "phone_number_id": "ybhb8wzi487w02m2bc7dh0ev",
                "agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                "direction": "both"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bot linked to phone number successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkBotToPhoneNumberResponse"
                },
                "example": {
                  "phone_number_id": "ybhb8wzi487w02m2bc7dh0ev",
                  "phone_number": "+15551112222",
                  "inbound_agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                  "outbound_agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                  "message": "Bot linked successfully for inbound and outbound calls."
                }
              }
            }
          },
          "400": {
            "description": "Bad request - validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid direction specified. Must be one of 'inbound', 'outbound', 'both'."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "404": {
            "description": "Phone number or bot not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "The specified phone number or bot was not found."
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/v1/phone-numbers/unlink-agent": {
      "post": {
        "summary": "Unlink Bot from Phone Number",
        "description": "Unlink a bot (agent) from a phone number.",
        "tags": ["Phone Numbers"],
        "requestBody": {
          "description": "Bot unlinking details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "phone_number_id": {
                    "type": "string",
                    "description": "The unique identifier of the phone number"
                  },
                  "direction": {
                    "type": "string",
                    "enum": ["inbound", "outbound", "both"],
                    "description": "Direction to unlink (inbound, outbound, or both)"
                  }
                },
                "required": ["phone_number_id", "direction"]
              },
              "example": {
                "phone_number_id": "ybhb8wzi487w02m2bc7dh0ev",
                "direction": "inbound"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Bot unlinked from phone number successfully",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkBotToPhoneNumberResponse"
                },
                "example": {
                  "phone_number_id": "ybhb8wzi487w02m2bc7dh0ev",
                  "phone_number": "+15551112222",
                  "inbound_agent_id": null,
                  "outbound_agent_id": "bvrg8wzi487w02m2bc7dh0ev",
                  "message": "Bot unlinked successfully for inbound calls."
                }
              }
            }
          },
          "400": {
            "description": "Bad request - validation error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Invalid request body."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - missing or invalid API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "404": {
            "description": "Phone number not found",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Phone number with the specified UID was not found."
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "An unexpected error occurred. Please try again later."
                }
              }
            }
          }
        }
      }
    },
    "/v1/contact-lists": {
      "post": {
        "tags": ["Contact Lists"],
        "summary": "Create a contact list",
        "operationId": "createContactList",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContactListRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Contact list created",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ContactListResponse" }
              }
            }
          },
          "400": { "description": "Validation error" }
        }
      },
      "get": {
        "tags": ["Contact Lists"],
        "summary": "List contact lists",
        "operationId": "listContactLists",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": { "type": "integer", "minimum": 0, "default": 0 }
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": { "type": "string", "format": "date-time" }
          },
          {
            "name": "created_before",
            "in": "query",
            "schema": { "type": "string", "format": "date-time" }
          }
        ],
        "responses": {
          "200": {
            "description": "List of contact lists",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListContactListsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/contact-lists/{contact_list_id}": {
      "get": {
        "tags": ["Contact Lists"],
        "summary": "Get a contact list",
        "operationId": "getContactList",
        "parameters": [
          {
            "name": "contact_list_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "responses": {
          "200": {
            "description": "Contact list details",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ContactListResponse" }
              }
            }
          },
          "404": { "description": "Contact list not found" }
        }
      },
      "patch": {
        "tags": ["Contact Lists"],
        "summary": "Update a contact list",
        "operationId": "updateContactList",
        "parameters": [
          {
            "name": "contact_list_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateContactListRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated contact list",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ContactListResponse" }
              }
            }
          },
          "404": { "description": "Contact list not found" }
        }
      },
      "delete": {
        "tags": ["Contact Lists"],
        "summary": "Delete a contact list",
        "operationId": "deleteContactList",
        "parameters": [
          {
            "name": "contact_list_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "responses": {
          "204": { "description": "Contact list deleted" },
          "404": { "description": "Contact list not found" }
        }
      }
    },
    "/v1/contact-lists/{contact_list_id}/contacts": {
      "post": {
        "tags": ["Contacts"],
        "summary": "Add a single contact to a contact list",
        "operationId": "addContact",
        "parameters": [
          {
            "name": "contact_list_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateContactRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Contact created",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ContactResponse" }
              }
            }
          },
          "400": { "description": "Validation error" },
          "404": { "description": "Contact list not found" }
        }
      },
      "get": {
        "tags": ["Contacts"],
        "summary": "List contacts in a contact list",
        "operationId": "listContacts",
        "parameters": [
          {
            "name": "contact_list_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": { "type": "integer", "minimum": 0, "default": 0 }
          }
        ],
        "responses": {
          "200": {
            "description": "List of contacts",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListContactsResponse"
                }
              }
            }
          },
          "404": { "description": "Contact list not found" }
        }
      },
      "delete": {
        "tags": ["Contacts"],
        "summary": "Delete contacts from a contact list",
        "operationId": "deleteContacts",
        "description": "Remove one or more contacts by providing their IDs in the request body.",
        "parameters": [
          {
            "name": "contact_list_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["contact_ids"],
                "properties": {
                  "contact_ids": {
                    "type": "array",
                    "items": { "type": "integer" },
                    "description": "Array of contact IDs to delete."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "204": { "description": "Contacts deleted" },
          "404": { "description": "Some contacts not found or access denied" }
        }
      }
    },
    "/v1/contact-lists/{contact_list_id}/contacts/bulk": {
      "post": {
        "tags": ["Contacts"],
        "summary": "Bulk add contacts to a contact list",
        "operationId": "addContactsBulk",
        "description": "Add up to 1000 contacts in a single request.",
        "parameters": [
          {
            "name": "contact_list_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateContactsBulkRequest"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Contacts created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "count": {
                      "type": "integer",
                      "description": "Number of contacts created."
                    }
                  }
                }
              }
            }
          },
          "400": { "description": "Validation error" },
          "404": { "description": "Contact list not found" }
        }
      }
    },
    "/v1/contact-lists/{contact_list_id}/contacts/{contact_id}": {
      "patch": {
        "tags": ["Contacts"],
        "summary": "Update a contact",
        "operationId": "updateContact",
        "parameters": [
          {
            "name": "contact_list_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          },
          {
            "name": "contact_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UpdateContactRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated contact",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ContactResponse" }
              }
            }
          },
          "404": { "description": "Contact not found" }
        }
      }
    },
    "/v1/campaigns": {
      "post": {
        "tags": ["Campaigns"],
        "summary": "Create a campaign",
        "operationId": "createCampaignExt",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/CreateCampaignRequest" }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Campaign created",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CampaignResponse" }
              }
            }
          },
          "400": { "description": "Validation error" },
          "404": { "description": "Bot or contact list not found" }
        }
      },
      "get": {
        "tags": ["Campaigns"],
        "summary": "List campaigns",
        "operationId": "listCampaignsExt",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "offset",
            "in": "query",
            "schema": { "type": "integer", "minimum": 0, "default": 0 }
          },
          {
            "name": "status",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "Scheduled",
                "Running",
                "Stopped",
                "Completed",
                "Failed",
                "Expired",
                "Paused"
              ]
            },
            "description": "Filter by campaign status."
          },
          {
            "name": "created_after",
            "in": "query",
            "schema": { "type": "string", "format": "date-time" }
          },
          {
            "name": "created_before",
            "in": "query",
            "schema": { "type": "string", "format": "date-time" }
          }
        ],
        "responses": {
          "200": {
            "description": "List of campaigns",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListCampaignsResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/campaigns/{campaign_id}": {
      "get": {
        "tags": ["Campaigns"],
        "summary": "Get a campaign",
        "operationId": "getCampaignExt",
        "parameters": [
          {
            "name": "campaign_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "responses": {
          "200": {
            "description": "Campaign details",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CampaignResponse" }
              }
            }
          },
          "404": { "description": "Campaign not found" }
        }
      },
      "patch": {
        "tags": ["Campaigns"],
        "summary": "Update a campaign",
        "operationId": "updateCampaignExt",
        "parameters": [
          {
            "name": "campaign_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/UpdateCampaignRequest" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Updated campaign",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CampaignResponse" }
              }
            }
          },
          "404": { "description": "Campaign not found" }
        }
      },
      "delete": {
        "tags": ["Campaigns"],
        "summary": "Delete a campaign",
        "operationId": "deleteCampaignExt",
        "parameters": [
          {
            "name": "campaign_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" }
          }
        ],
        "responses": {
          "204": { "description": "Campaign deleted" },
          "404": { "description": "Campaign not found" }
        }
      }
    },
    "/v1/voices": {
      "get": {
        "summary": "List Voices",
        "description": "Retrieve a paginated list of available text-to-speech voices. Use query parameters to filter by gender, provider, language, or accent, and to search by name or description.",
        "tags": ["Voices"],
        "operationId": "listVoicesExt",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            },
            "description": "Maximum number of voices to return (1-100)."
          },
          {
            "name": "offset",
            "in": "query",
            "schema": { "type": "integer", "minimum": 0, "default": 0 },
            "description": "Number of voices to skip for pagination."
          },
          {
            "name": "search",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Search voices by name or description (case-insensitive)."
          },
          {
            "name": "gender",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Filter by gender (e.g. 'male', 'female')."
          },
          {
            "name": "provider",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Filter by TTS provider (e.g. 'elevenlabs', 'deepgram')."
          },
          {
            "name": "language",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Filter by language code (e.g. 'en', 'es')."
          },
          {
            "name": "accent",
            "in": "query",
            "schema": { "type": "string" },
            "description": "Filter by accent (case-insensitive partial match)."
          },
          {
            "name": "sort_by",
            "in": "query",
            "schema": { "type": "string", "enum": ["name", "created_at"] },
            "description": "Field to sort results by."
          },
          {
            "name": "sort_order",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": ["asc", "desc"],
              "default": "asc"
            },
            "description": "Sort direction."
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of voices with available filter values.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ListVoicesResponse" }
              }
            }
          }
        }
      }
    },
    "/v1/voices/{voice_id}": {
      "get": {
        "summary": "Get Voice",
        "description": "Retrieve details of a specific voice by its ID.",
        "tags": ["Voices"],
        "operationId": "getVoiceExt",
        "parameters": [
          {
            "name": "voice_id",
            "in": "path",
            "required": true,
            "schema": { "type": "integer" },
            "description": "The numeric ID of the voice."
          }
        ],
        "responses": {
          "200": {
            "description": "Voice details.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/VoiceResponse" }
              }
            }
          },
          "400": { "description": "Invalid voice_id" },
          "404": { "description": "Voice not found" }
        }
      }
    },
    "/v2/send-sms": {
      "post": {
        "summary": "Send SMS",
        "description": "Send an SMS message to a phone number. Messages are sent via the Surge SMS API and queued for delivery.",
        "tags": ["SMS"],
        "requestBody": {
          "description": "SMS message details",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SendSmsRequest"
              },
              "example": {
                "from_number": "+16625658792",
                "to_number": "+17189153182",
                "message": "Hello from OpenMic! Here is your appointment link: https://example.com/book"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "SMS queued for delivery",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SendSmsResponse"
                },
                "example": {
                  "id": "msg_01kpbgtyntfktvzseh0ykcmqm4",
                  "from_number": "+16625658792",
                  "to_number": "+17189153182",
                  "message": "Hello from OpenMic! Here is your appointment link: https://example.com/book",
                  "status": "queued"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or missing API key",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Unauthorized",
                  "message": "Invalid or expired API key"
                }
              }
            }
          },
          "422": {
            "description": "Validation error - Invalid phone number format or unsupported destination",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "error": "Surge API error (422): phone number must be in E.164 format"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "success": false,
                  "message": "Too many requests",
                  "error": "RATE_LIMIT_EXCEEDED",
                  "retryAfter": 45
                }
              }
            }
          },
          "500": {
            "description": "Internal server error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "SendSmsRequest": {
        "type": "object",
        "required": ["to_number", "message"],
        "properties": {
          "from_number": {
            "type": "string",
            "description": "Sender phone number in E.164 format. Optional — defaults to your account's Surge phone number if not provided.",
            "example": "+16625658792"
          },
          "to_number": {
            "type": "string",
            "description": "Recipient phone number in E.164 format.",
            "example": "+17189153182"
          },
          "message": {
            "type": "string",
            "description": "The text message to send. Must not be empty.",
            "example": "Hello from OpenMic!"
          }
        }
      },
      "SendSmsResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique message identifier.",
            "example": "msg_01kpbgtyntfktvzseh0ykcmqm4"
          },
          "from_number": {
            "type": "string",
            "description": "The phone number the message was sent from.",
            "example": "+16625658792"
          },
          "to_number": {
            "type": "string",
            "description": "The phone number the message was sent to.",
            "example": "+17189153182"
          },
          "message": {
            "type": "string",
            "description": "The message body that was sent.",
            "example": "Hello from OpenMic!"
          },
          "status": {
            "type": "string",
            "description": "The delivery status of the message.",
            "enum": ["queued"],
            "example": "queued"
          }
        }
      },
      "ToolType": {
        "type": "string",
        "description": "The type of tool that determines its behavior and required configuration.",
        "enum": [
          "api_request",
          "function",
          "end_call",
          "transfer_call",
          "dtmf",
          "send_sms",
          "send_email",
          "call_booking",
          "check_calendar_availability",
          "check_working_hours"
        ]
      },
      "CreateToolRequest": {
        "type": "object",
        "required": ["type", "name"],
        "description": "Create a tool for a bot. Each tool type has different required fields and `static_params` structure. See the `x-tool-examples` section for complete examples of each type.",
        "properties": {
          "type": { "$ref": "#/components/schemas/ToolType" },
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Tool name (max 255 characters)."
          },
          "description": {
            "type": "string",
            "description": "Description of what the tool does. This is shown to the AI to help it decide when to use the tool."
          },
          "url": {
            "type": "string",
            "description": "API endpoint URL. **Required for `api_request` type.**"
          },
          "method": {
            "type": "string",
            "enum": ["get", "post"],
            "description": "HTTP method for API requests. Defaults to `get`."
          },
          "api_timeout": {
            "type": "integer",
            "minimum": 1,
            "description": "Request timeout in milliseconds."
          },
          "parameters": {
            "type": "object",
            "description": "JSON schema defining the tool's input parameters. The AI will extract these from the conversation."
          },
          "use_raw_schema": {
            "type": "boolean",
            "description": "If true, `parameters` is used as-is without transformation. This setting takes precedence over the type-derived default. Set to `true` for `function` type tools."
          },
          "static_params": {
            "type": "object",
            "description": "Static configuration that varies by tool type. See examples below for each type's schema."
          },
          "speak_during_execution": {
            "type": "boolean",
            "default": true,
            "description": "If true, bot speaks a filler message while tool executes."
          },
          "speak_after_execution": {
            "type": "boolean",
            "default": true,
            "description": "If true, bot announces the result after execution."
          },
          "async": {
            "type": "boolean",
            "default": false,
            "description": "If true, tool runs asynchronously without blocking the conversation."
          }
        },
        "x-tool-examples": [
          {
            "title": "api_request - Make HTTP requests to external APIs",
            "description": "Use this to call external REST APIs. The bot extracts parameters from the conversation and sends them to your endpoint. **Required: `url`**",
            "value": {
              "type": "api_request",
              "name": "get_order_status",
              "description": "Look up the status of a customer order by order ID",
              "url": "https://api.example.com/orders/status",
              "method": "post",
              "api_timeout": 10000,
              "parameters": {
                "type": "object",
                "properties": {
                  "order_id": {
                    "type": "string",
                    "description": "The order ID to look up"
                  }
                },
                "required": ["order_id"]
              },
              "speak_during_execution": true,
              "speak_after_execution": true
            }
          },
          {
            "title": "function - Custom function with raw JSON schema",
            "description": "Use this when you need full control over the function schema. **Required: `use_raw_schema: true`, `parameters`**",
            "value": {
              "type": "function",
              "name": "calculate_quote",
              "description": "Calculate a price quote based on customer requirements",
              "use_raw_schema": true,
              "parameters": {
                "type": "object",
                "properties": {
                  "service_type": {
                    "type": "string",
                    "enum": ["basic", "premium", "enterprise"]
                  },
                  "quantity": { "type": "integer", "minimum": 1 }
                },
                "required": ["service_type", "quantity"]
              }
            }
          },
          {
            "title": "end_call - Terminate the current call",
            "description": "Ends the call gracefully with an optional goodbye message. **static_params: `{ end_message: string }`**",
            "value": {
              "type": "end_call",
              "name": "end_call",
              "description": "End the call when the customer says goodbye or the conversation is complete",
              "static_params": {
                "end_message": "Thank you for calling. Goodbye!"
              }
            }
          },
          {
            "title": "transfer_call - Transfer the call to another number",
            "description": "Transfers the call to a specified phone number. **static_params: `{ routing_rules, default_transfer_number, transfer_type }`**",
            "value": {
              "type": "transfer_call",
              "name": "transfer_to_sales",
              "description": "Transfer the call to the sales team when customer wants to make a purchase",
              "static_params": {
                "routing_rules": "When customer wants to buy or make a purchase, transfer to +15551234567",
                "default_transfer_number": "+15551234567",
                "transfer_type": "cold"
              },
              "speak_during_execution": false,
              "speak_after_execution": false
            }
          },
          {
            "title": "dtmf - Send DTMF tones (keypad presses)",
            "description": "Sends touch-tone digits during the call, useful for IVR navigation. **static_params: `{ digits: string }`**",
            "value": {
              "type": "dtmf",
              "name": "press_digits",
              "description": "Press keypad digits when navigating phone menus",
              "static_params": {
                "digits": "1"
              }
            }
          },
          {
            "title": "send_sms - Send an SMS message",
            "description": "Sends a text message to a phone number during the call. **static_params: `{ message: string }`**",
            "value": {
              "type": "send_sms",
              "name": "send_confirmation_sms",
              "description": "Send appointment confirmation via SMS when customer books",
              "static_params": {
                "message": "Your appointment has been confirmed for {{appointment_date}} at {{appointment_time}}. Reply CANCEL to cancel."
              },
              "speak_during_execution": true,
              "speak_after_execution": true
            }
          },
          {
            "title": "send_email - Send an email",
            "description": "Sends an email during the call. **static_params: `{ to, subject, body }`**",
            "value": {
              "type": "send_email",
              "name": "send_quote_email",
              "description": "Email a price quote to the customer",
              "static_params": {
                "to": "{{customer_email}}",
                "subject": "Your Price Quote from Acme Corp",
                "body": "Thank you for your interest. Your quote for {{service_type}} is ${{quote_amount}}."
              }
            }
          },
          {
            "title": "call_booking - Book a calendar appointment",
            "description": "Creates a booking in an integrated calendar system (e.g., Clio, Zoho). **static_params: `{ calendar_integration, duration_minutes }`**",
            "value": {
              "type": "call_booking",
              "name": "book_appointment",
              "description": "Book an appointment when customer requests to schedule a meeting",
              "static_params": {
                "calendar_integration": "clio",
                "duration_minutes": 30
              }
            }
          },
          {
            "title": "check_calendar_availability - Check available time slots",
            "description": "Queries the calendar system for available appointment slots. **static_params: `{ calendar_integration, days_ahead }`**",
            "value": {
              "type": "check_calendar_availability",
              "name": "check_availability",
              "description": "Check available appointment times when customer asks about availability",
              "static_params": {
                "calendar_integration": "clio",
                "days_ahead": 14
              }
            }
          },
          {
            "title": "check_working_hours - Check if within business hours",
            "description": "Determines if the current time is within configured working hours. Useful for routing after-hours calls. **static_params: `{ timezone, working_hours }`**",
            "value": {
              "type": "check_working_hours",
              "name": "check_business_hours",
              "description": "Check if calling during business hours to route appropriately",
              "static_params": {
                "timezone": "America/New_York",
                "working_hours": {
                  "monday": { "start": "09:00", "end": "17:00" },
                  "tuesday": { "start": "09:00", "end": "17:00" },
                  "wednesday": { "start": "09:00", "end": "17:00" },
                  "thursday": { "start": "09:00", "end": "17:00" },
                  "friday": { "start": "09:00", "end": "17:00" },
                  "saturday": { "start": "closed", "end": "closed" },
                  "sunday": { "start": "closed", "end": "closed" }
                }
              }
            }
          }
        ]
      },
      "UpdateToolRequest": {
        "type": "object",
        "properties": {
          "type": { "$ref": "#/components/schemas/ToolType" },
          "name": { "type": "string", "maxLength": 255 },
          "description": { "type": "string" },
          "url": { "type": "string" },
          "method": { "type": "string", "enum": ["get", "post"] },
          "api_timeout": { "type": "integer", "minimum": 1 },
          "parameters": { "type": "object" },
          "use_raw_schema": { "type": "boolean" },
          "static_params": { "type": "object" },
          "speak_during_execution": { "type": "boolean" },
          "speak_after_execution": { "type": "boolean" },
          "async": { "type": "boolean" }
        }
      },
      "ToolResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique numeric ID of the tool."
          },
          "type": { "$ref": "#/components/schemas/ToolType" },
          "name": { "type": "string" },
          "description": { "type": "string" },
          "url": { "type": "string" },
          "method": { "type": "string" },
          "api_timeout": { "type": "integer" },
          "parameters": { "type": "object" },
          "use_raw_schema": { "type": "boolean" },
          "static_params": { "type": "object" },
          "speak_during_execution": { "type": "boolean" },
          "speak_after_execution": { "type": "boolean" },
          "async": { "type": "boolean" },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "ListToolsResponse": {
        "type": "object",
        "properties": {
          "tools": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ToolResponse" }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "limit": { "type": "integer" },
              "offset": { "type": "integer" },
              "total": { "type": "integer" },
              "has_more": { "type": "boolean" }
            }
          }
        }
      },
      "CreateBotRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "description": "Name of the bot (max 255 characters)",
            "maxLength": 255
          },
          "prompt": {
            "type": "string",
            "description": "System prompt for the bot"
          },
          "first_message": {
            "type": "string",
            "description": "Initial message the bot will send"
          },
          "knowledge_base_id": {
            "type": "integer",
            "description": "ID of the knowledge base to use"
          },
          "voice_provider": {
            "type": "string",
            "enum": ["OpenAI", "ElevenLabs", "Deepgram"],
            "description": "Voice synthesis provider"
          },
          "voice": {
            "type": "string",
            "description": "Voice ID or name"
          },
          "voice_model": {
            "type": "string",
            "description": "Voice model to use"
          },
          "voice_speed": {
            "type": "number",
            "description": "Speech speed multiplier"
          },
          "llm_model_name": {
            "type": "string",
            "description": "Large language model to use"
          },
          "llm_model_temperature": {
            "type": "number",
            "description": "Temperature setting for the LLM"
          },
          "stt_provider": {
            "type": "string",
            "enum": ["Deepgram"],
            "description": "Speech-to-text provider"
          },
          "stt_model": {
            "type": "string",
            "description": "Speech-to-text model"
          },
          "call_settings": {
            "$ref": "#/components/schemas/CallSettings"
          },
          "advanced_settings": {
            "$ref": "#/components/schemas/AdvancedSettings"
          },
          "post_call_settings": {
            "$ref": "#/components/schemas/PostCallSettings"
          }
        },
        "required": ["name", "prompt"]
      },
      "UpdateBotRequest": {
        "allOf": [
          { "$ref": "#/components/schemas/CreateBotRequest" },
          {
            "type": "object",
            "description": "All fields are optional for updates"
          }
        ]
      },
      "CallSettings": {
        "type": "object",
        "properties": {
          "max_call_duration": {
            "type": "integer",
            "minimum": 2,
            "maximum": 30,
            "description": "Maximum call duration in minutes (2-30)"
          },
          "silence_timeout": {
            "type": "integer",
            "minimum": 5,
            "maximum": 45,
            "description": "Silence timeout in seconds (5-45)"
          },
          "silence_timeout_max_retries": {
            "type": "integer",
            "minimum": 1,
            "maximum": 5,
            "description": "Maximum retries for silence timeout (1-5)"
          },
          "silence_timeout_message": {
            "type": "string",
            "description": "Message to play when silence timeout occurs"
          },
          "call_recording_enabled": {
            "type": "boolean",
            "description": "Whether to record calls"
          },
          "voicemail_detection_enabled": {
            "type": "boolean",
            "description": "Whether to detect voicemail"
          },
          "voicemail_action": {
            "type": "string",
            "enum": ["leave_message", "hangup"],
            "description": "Action to take when voicemail is detected. 'leave_message' will deliver a custom voicemail message, 'hangup' will end the call immediately."
          },
          "voicemail_message_type": {
            "type": "string",
            "enum": ["static", "prompt"],
            "description": "Type of voicemail message. 'static' uses a fixed pre-written message, 'prompt' uses AI-generated messages based on conversation context."
          },
          "voicemail_message": {
            "type": "string",
            "description": "The voicemail message content. Required when voicemail_action is 'leave_message'. For 'static' type, this is the exact message to be delivered. For 'prompt' type, this provides instructions to the AI."
          },
          "hipaa_compliance_enabled": {
            "type": "boolean",
            "description": "Whether HIPAA compliance is enabled"
          },
          "pci_compliance_enabled": {
            "type": "boolean",
            "description": "Whether PCI compliance is enabled"
          }
        }
      },
      "AdvancedSettings": {
        "type": "object",
        "properties": {
          "agent_personality": {
            "type": "string",
            "enum": [
              "casual",
              "humorous",
              "direct",
              "formal",
              "persuasive",
              "friendly"
            ],
            "description": "Personality type for the agent"
          },
          "humanize_conversation": {
            "type": "boolean",
            "description": "Whether to humanize the conversation"
          },
          "background_noise_reduction": {
            "type": "boolean",
            "description": "Whether to reduce background noise"
          },
          "allow_interruptions": {
            "type": "boolean",
            "description": "Whether to allow user interruptions"
          },
          "min_interruption_duration": {
            "type": "number",
            "minimum": 0.2,
            "maximum": 5,
            "multipleOf": 0.1,
            "description": "Minimum interruption duration in seconds (0.2-5, step 0.1)"
          },
          "background_sound": {
            "type": "string",
            "description": "Background sound to play"
          },
          "agent_response_length": {
            "type": "string",
            "enum": ["normal", "short", "concise", "long"],
            "description": "Preferred response length"
          },
          "short_pause": {
            "type": "number",
            "minimum": 0.2,
            "maximum": 2,
            "multipleOf": 0.1,
            "description": "Short pause duration in seconds (0.2-2, step 0.1)"
          },
          "long_pause": {
            "type": "number",
            "minimum": 0.5,
            "maximum": 6,
            "multipleOf": 0.1,
            "description": "Long pause duration in seconds (0.5-6, step 0.1)"
          },
          "filter_phrases": {
            "type": "string",
            "description": "Phrases to filter from speech"
          }
        }
      },
      "PostCallSettings": {
        "type": "object",
        "properties": {
          "summary_prompt": {
            "type": "string",
            "description": "Prompt for generating call summary"
          },
          "success_evaluation_prompt": {
            "type": "string",
            "description": "Prompt for evaluating call success"
          },
          "success_evaluation_rubric_type": {
            "type": "string",
            "enum": [
              "NUMERIC_SCALE",
              "DESCRIPTIVE_SCALE",
              "PERCENTAGE_SCALE",
              "LIKERT_SCALE",
              "PASS_FAIL",
              "SENTIMENT"
            ],
            "description": "Type of success evaluation rubric"
          },
          "structured_extraction_prompt": {
            "type": "string",
            "description": "Prompt for structured data extraction"
          },
          "structured_extraction_json_schema": {
            "type": "object",
            "description": "JSON schema for structured extraction"
          }
        }
      },
      "BotResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique identifier of the bot"
          },
          "name": {
            "type": "string",
            "description": "Name of the bot"
          },
          "prompt": {
            "type": "string",
            "description": "System prompt for the bot"
          },
          "first_message": {
            "type": "string",
            "description": "Initial message the bot will send"
          },
          "knowledge_base_id": {
            "type": "integer",
            "description": "ID of the knowledge base"
          },
          "voice_provider": {
            "type": "string",
            "enum": ["OpenAI", "ElevenLabs", "Deepgram"],
            "description": "Voice synthesis provider"
          },
          "voice": {
            "type": "string",
            "description": "Voice ID or name"
          },
          "voice_model": {
            "type": "string",
            "description": "Voice model being used"
          },
          "voice_speed": {
            "type": "number",
            "description": "Speech speed multiplier"
          },
          "llm_model_name": {
            "type": "string",
            "description": "Large language model being used"
          },
          "llm_model_temperature": {
            "type": "number",
            "description": "Temperature setting for the LLM"
          },
          "stt_provider": {
            "type": "string",
            "enum": ["Deepgram"],
            "description": "Speech-to-text provider"
          },
          "stt_model": {
            "type": "string",
            "description": "Speech-to-text model"
          },
          "call_settings": {
            "$ref": "#/components/schemas/CallSettings"
          },
          "advanced_settings": {
            "$ref": "#/components/schemas/AdvancedSettings"
          },
          "post_call_settings": {
            "$ref": "#/components/schemas/PostCallSettings"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Bot creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Bot last update timestamp"
          }
        },
        "required": ["id", "name", "prompt", "created_at", "updated_at"]
      },
      "ListBotsResponse": {
        "type": "object",
        "properties": {
          "bots": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/BotResponse" }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": ["bots", "pagination"]
      },
      "CreateCallRequest": {
        "type": "object",
        "properties": {
          "from_number": {
            "type": "string",
            "pattern": "^\\+[1-9]\\d{1,14}$",
            "example": "+1234567890",
            "description": "The number you own in E.164 format. Must be a number purchased from OpenMic."
          },
          "to_number": {
            "type": "string",
            "pattern": "^\\+[1-9]\\d{1,14}$",
            "example": "+0987654321",
            "description": "The number you want to call in E.164 format."
          },
          "override_agent_id": {
            "type": "string",
            "example": "bvrg8wzi487w02m2bc7dh0ev",
            "description": "The bot ID to override the default agent."
          },
          "customer_id": {
            "type": "string",
            "example": "customer_001",
            "description": "Customer identifier for tracking"
          },
          "dynamic_variables": {
            "type": "object",
            "example": { "name": "John" },
            "description": "Send dynamic variables in key value pairs to replace in the prompt."
          },
          "callback_url": {
            "type": "string",
            "example": "https://example.com/callback",
            "description": "Callback URL to receive call events."
          }
        },
        "required": ["from_number", "to_number"]
      },
      "CallResponse": {
        "type": "object",
        "properties": {
          "call_type": {
            "type": "string",
            "enum": ["phonecall", "webcall"],
            "description": "Type of call"
          },
          "from_number": {
            "type": "string",
            "description": "Originating phone number"
          },
          "to_number": {
            "type": "string",
            "description": "Destination phone number"
          },
          "direction": {
            "type": "string",
            "enum": ["inbound", "outbound"],
            "description": "Call direction"
          },
          "call_id": {
            "type": "string",
            "description": "Unique call identifier"
          },
          "agent_id": {
            "type": "string",
            "description": "Bot/agent identifier"
          },
          "call_status": {
            "type": "string",
            "enum": ["registered", "ongoing", "ended", "error"],
            "description": "Current call status"
          },
          "customer_id": {
            "type": "string",
            "description": "Customer identifier"
          },
          "telephony_identifier": {
            "type": "object",
            "description": "Telephony system identifiers"
          },
          "start_timestamp": {
            "type": "integer",
            "description": "Call start time (Unix timestamp in milliseconds)"
          },
          "end_timestamp": {
            "type": "integer",
            "description": "Call end time (Unix timestamp in milliseconds)"
          },
          "duration_ms": {
            "type": "integer",
            "description": "Call duration in milliseconds"
          },
          "transcript": {
            "type": "array",
            "items": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "minItems": 2,
              "maxItems": 2,
              "description": "Transcript entry with [speaker, message] format"
            },
            "description": "Call transcript as array of [speaker, message] pairs"
          },
          "recording_url": {
            "type": "string",
            "description": "URL to call recording"
          },
          "latency": {
            "type": "object",
            "properties": {
              "e2e_min_latency": {
                "type": "number",
                "description": "Minimum end-to-end latency in seconds"
              },
              "e2e_median_latency": {
                "type": "number",
                "description": "Median end-to-end latency in seconds"
              },
              "e2e_p90_latency": {
                "type": "number",
                "description": "90th percentile end-to-end latency in seconds"
              },
              "llm_min_latency": {
                "type": "number",
                "description": "Minimum LLM processing latency in seconds"
              },
              "llm_median_latency": {
                "type": "number",
                "description": "Median LLM processing latency in seconds"
              },
              "llm_p90_latency": {
                "type": "number",
                "description": "90th percentile LLM processing latency in seconds"
              },
              "tts_min_latency": {
                "type": "number",
                "description": "Minimum text-to-speech latency in seconds"
              },
              "tts_median_latency": {
                "type": "number",
                "description": "Median text-to-speech latency in seconds"
              },
              "tts_p90_latency": {
                "type": "number",
                "description": "90th percentile text-to-speech latency in seconds"
              }
            },
            "description": "Latency metrics for different components"
          },
          "call_analysis": {
            "type": "object",
            "properties": {
              "summary": {
                "type": "string",
                "description": "AI-generated summary of the call"
              },
              "is_successful": {
                "type": "boolean",
                "description": "Whether the call was deemed successful"
              },
              "success_evaluation": {
                "type": "string",
                "description": "Success evaluation result (e.g., 'good', 'excellent', 'poor')"
              },
              "extracted_data": {
                "type": "object",
                "nullable": true,
                "description": "Structured data extracted from the call based on post-call settings"
              }
            },
            "description": "Post-call analysis results including summary and success metrics"
          },
          "call_cost": {
            "type": "object",
            "properties": {
              "total_cost": {
                "type": "number",
                "description": "Total cost of the call in USD"
              },
              "llm_cost": {
                "type": "number",
                "description": "Cost attributed to LLM usage in USD"
              },
              "tts_cost": {
                "type": "number",
                "description": "Cost attributed to text-to-speech in USD"
              },
              "stt_cost": {
                "type": "number",
                "description": "Cost attributed to speech-to-text in USD"
              }
            },
            "description": "Detailed cost breakdown for the call"
          },
          "dynamic_variables": {
            "type": "object",
            "example": { "name": "John" },
            "description": "Send dynamic variables in key value pairs to replace in the prompt."
          }
        },
        "required": [
          "call_type",
          "from_number",
          "to_number",
          "direction",
          "call_id",
          "agent_id",
          "call_status"
        ]
      },
      "ListCallsResponse": {
        "type": "object",
        "properties": {
          "calls": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/CallResponse" }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": ["calls", "pagination"]
      },
      "PhoneNumberResponse": {
        "type": "object",
        "properties": {
          "phone_number_id": {
            "type": "string",
            "description": "Unique identifier of the phone number"
          },
          "phone_number": {
            "type": "string",
            "description": "Phone number in E.164 format"
          },
          "name": {
            "type": "string",
            "description": "Friendly name for the phone number"
          },
          "inbound_agent_id": {
            "type": "string",
            "description": "Bot ID for inbound calls"
          },
          "outbound_agent_id": {
            "type": "string",
            "description": "Bot ID for outbound calls"
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "description": "Phone number creation timestamp"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "description": "Phone number last update timestamp"
          }
        },
        "required": [
          "phone_number_id",
          "phone_number",
          "created_at",
          "updated_at"
        ]
      },
      "ListPhoneNumbersResponse": {
        "type": "object",
        "properties": {
          "phone_numbers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PhoneNumberResponse"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/Pagination"
          }
        },
        "required": ["phone_numbers", "pagination"]
      },
      "LinkBotToPhoneNumberRequest": {
        "type": "object",
        "properties": {
          "phone_number_id": {
            "type": "string",
            "description": "Unique identifier of the phone number"
          },
          "agent_id": {
            "type": "string",
            "description": "Bot ID to link"
          },
          "direction": {
            "type": "string",
            "enum": ["inbound", "outbound", "both"],
            "description": "Direction for the bot assignment"
          }
        },
        "required": ["phone_number_id", "agent_id", "direction"]
      },
      "LinkBotToPhoneNumberResponse": {
        "type": "object",
        "properties": {
          "phone_number_id": {
            "type": "string",
            "description": "Unique identifier of the phone number"
          },
          "phone_number": {
            "type": "string",
            "description": "Phone number in E.164 format"
          },
          "inbound_agent_id": {
            "type": "string",
            "description": "Bot ID for inbound calls"
          },
          "outbound_agent_id": {
            "type": "string",
            "description": "Bot ID for outbound calls"
          },
          "message": {
            "type": "string",
            "description": "Success message"
          }
        },
        "required": ["phone_number_id", "phone_number", "message"]
      },
      "Pagination": {
        "type": "object",
        "properties": {
          "limit": {
            "type": "integer",
            "description": "Number of items per page"
          },
          "offset": {
            "type": "integer",
            "description": "Number of items skipped"
          },
          "total": {
            "type": "integer",
            "description": "Total number of items"
          },
          "has_more": {
            "type": "boolean",
            "description": "Whether there are more items"
          }
        },
        "required": ["limit", "offset", "total", "has_more"]
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Error message"
          },
          "message": {
            "type": "string",
            "description": "Additional error message (for certain error types)"
          }
        },
        "required": ["error"]
      },
      "CreateContactListRequest": {
        "type": "object",
        "required": ["name"],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Name of the contact list."
          }
        }
      },
      "UpdateContactListRequest": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "New name for the contact list."
          }
        }
      },
      "ContactListResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "description": "Unique identifier." },
          "name": { "type": "string", "description": "Contact list name." },
          "contact_count": {
            "type": "integer",
            "description": "Number of contacts in the list."
          },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "ListContactListsResponse": {
        "type": "object",
        "properties": {
          "contact_lists": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ContactListResponse" }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "limit": { "type": "integer" },
              "offset": { "type": "integer" },
              "total": { "type": "integer" },
              "has_more": { "type": "boolean" }
            }
          }
        }
      },
      "CreateContactRequest": {
        "type": "object",
        "required": ["name"],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Contact's full name."
          },
          "phone_number": {
            "type": "string",
            "description": "Primary phone number (E.164 format recommended, e.g. +14155551234)."
          },
          "phone_number_2": {
            "type": "string",
            "description": "Secondary phone number."
          },
          "phone_number_3": {
            "type": "string",
            "description": "Tertiary phone number."
          },
          "contact_info": {
            "type": "object",
            "description": "Arbitrary JSON metadata for the contact. Use this to store custom fields like email, address, company, or any key-value data your bot or campaign needs (e.g. `{\"email\": \"john@example.com\", \"company\": \"Acme\", \"plan\": \"enterprise\"}`)."
          }
        }
      },
      "UpdateContactRequest": {
        "type": "object",
        "description": "All fields are optional. Only provided fields will be updated.",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Contact's full name."
          },
          "phone_number": {
            "type": "string",
            "description": "Primary phone number."
          },
          "phone_number_2": {
            "type": "string",
            "description": "Secondary phone number."
          },
          "phone_number_3": {
            "type": "string",
            "description": "Tertiary phone number."
          },
          "contact_info": {
            "type": "object",
            "description": "Arbitrary JSON metadata. Pass null to clear."
          }
        }
      },
      "CreateContactsBulkRequest": {
        "type": "object",
        "required": ["contacts"],
        "properties": {
          "contacts": {
            "type": "array",
            "maxItems": 1000,
            "description": "Array of contacts to add. Maximum 1000 per request.",
            "items": { "$ref": "#/components/schemas/CreateContactRequest" }
          }
        }
      },
      "ContactResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "description": "Unique identifier." },
          "name": { "type": "string", "description": "Contact's name." },
          "phone_number": {
            "type": "string",
            "description": "Primary phone number."
          },
          "phone_number_2": {
            "type": "string",
            "description": "Secondary phone number."
          },
          "phone_number_3": {
            "type": "string",
            "description": "Tertiary phone number."
          },
          "contact_info": {
            "type": "object",
            "description": "Custom metadata JSON."
          },
          "contact_list_id": {
            "type": "integer",
            "description": "ID of the parent contact list."
          },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "ListContactsResponse": {
        "type": "object",
        "properties": {
          "contacts": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ContactResponse" }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "limit": { "type": "integer" },
              "offset": { "type": "integer" },
              "total": { "type": "integer" },
              "has_more": { "type": "boolean" }
            }
          }
        }
      },
      "CreateCampaignRequest": {
        "type": "object",
        "required": [
          "name",
          "type",
          "bot_uid",
          "from_number",
          "contact_list_id",
          "time_start",
          "time_end"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Campaign name."
          },
          "type": {
            "type": "string",
            "enum": ["outbound"],
            "description": "Campaign type. Only **outbound** campaigns are supported (dials contacts from a contact list)."
          },
          "bot_uid": {
            "type": "string",
            "description": "UID of the bot that handles calls for this campaign."
          },
          "from_number": {
            "type": "string",
            "description": "Phone number to dial from in E.164 format (e.g. \"+12025551234\")."
          },
          "contact_list_id": {
            "type": "integer",
            "description": "ID of the contact list to dial."
          },
          "time_start": {
            "type": "string",
            "pattern": "^([0-1][0-9]|2[0-3]):[0-5][0-9]$",
            "description": "Start time for the daily calling window in HH:MM format (e.g. \"09:00\")."
          },
          "time_end": {
            "type": "string",
            "pattern": "^([0-1][0-9]|2[0-3]):[0-5][0-9]$",
            "description": "End time for the daily calling window in HH:MM format (e.g. \"17:00\")."
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone for the calling window (e.g. \"America/New_York\"). Defaults to UTC if not specified."
          },
          "days": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday"
              ]
            },
            "description": "Days of week to run the campaign (e.g. [\"Monday\", \"Wednesday\", \"Friday\"]). If not provided, campaign runs as single-day. Valid values: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday."
          }
        }
      },
      "UpdateCampaignRequest": {
        "type": "object",
        "description": "All fields are optional. Only provided fields will be updated.",
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "description": "Campaign name."
          },
          "from_number": {
            "type": "string",
            "description": "Phone number to dial from in E.164 format."
          },
          "time_start": {
            "type": "string",
            "pattern": "^([0-1][0-9]|2[0-3]):[0-5][0-9]$",
            "description": "Start time for the calling window in HH:MM format (e.g. \"09:00\")."
          },
          "time_end": {
            "type": "string",
            "pattern": "^([0-1][0-9]|2[0-3]):[0-5][0-9]$",
            "description": "End time for the calling window in HH:MM format (e.g. \"17:00\")."
          },
          "timezone": {
            "type": "string",
            "description": "IANA timezone for the calling window."
          },
          "contact_list_id": {
            "type": "integer",
            "description": "ID of the contact list to dial."
          },
          "days": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday"
              ]
            },
            "description": "Days of week to run the campaign (e.g. [\"Monday\", \"Wednesday\", \"Friday\"]). **Note:** When setting days, time_start and time_end must also be provided (either in the same request or already set on the campaign)."
          }
        }
      },
      "CampaignResponse": {
        "type": "object",
        "properties": {
          "id": { "type": "integer", "description": "Unique identifier." },
          "name": { "type": "string", "description": "Campaign name." },
          "type": {
            "type": "string",
            "enum": ["outbound"],
            "description": "Campaign type (always outbound)."
          },
          "status": {
            "type": "string",
            "enum": [
              "Scheduled",
              "Running",
              "Stopped",
              "Completed",
              "Failed",
              "Expired",
              "Paused"
            ],
            "description": "Current campaign status."
          },
          "bot_uid": {
            "type": "string",
            "description": "Bot UID for API reference."
          },
          "from_number": {
            "type": "string",
            "description": "Phone number used to dial from (E.164 format)."
          },
          "contact_list_id": {
            "type": "integer",
            "description": "Associated contact list ID."
          },
          "time_start": {
            "type": "string",
            "description": "Daily calling window start time in HH:MM format."
          },
          "time_end": {
            "type": "string",
            "description": "Daily calling window end time in HH:MM format."
          },
          "timezone": {
            "type": "string",
            "description": "Calling window timezone (IANA format)."
          },
          "days": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday"
              ]
            },
            "description": "Days of week the campaign runs on (for recurring campaigns)."
          },
          "schedule_type": {
            "type": "string",
            "enum": ["single", "multi"],
            "description": "Schedule type: single (one-time) or multi (recurring on specific days)."
          },
          "current_index": {
            "type": "integer",
            "description": "Number of contacts already called."
          },
          "total_contacts": {
            "type": "integer",
            "description": "Total number of contacts in the campaign's contact list."
          },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "VoiceResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "description": "Unique numeric ID of the voice."
          },
          "name": {
            "type": "string",
            "description": "Display name of the voice."
          },
          "voice_id": {
            "type": "string",
            "description": "Provider-specific voice identifier used when configuring a bot."
          },
          "sample_url": {
            "type": "string",
            "description": "URL to an audio sample of the voice."
          },
          "provider": {
            "type": "string",
            "description": "TTS provider (e.g. 'elevenlabs', 'deepgram')."
          },
          "gender": {
            "type": "string",
            "description": "Gender of the voice (e.g. 'male', 'female')."
          },
          "language": {
            "type": "string",
            "description": "Primary language code."
          },
          "languages": {
            "type": "array",
            "items": { "type": "string" },
            "description": "All supported language codes."
          },
          "accent": {
            "type": "string",
            "description": "Accent or regional variant, if applicable."
          },
          "age": {
            "type": "string",
            "description": "Approximate age group (e.g. 'young', 'middle-aged')."
          },
          "ethnicity": {
            "type": "string",
            "description": "Ethnicity descriptor, if available."
          },
          "characteristics": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Descriptive tags (e.g. 'warm', 'professional', 'energetic')."
          },
          "description": {
            "type": "string",
            "description": "Free-text description of the voice."
          },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "ListVoicesResponse": {
        "type": "object",
        "properties": {
          "voices": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/VoiceResponse" }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "limit": { "type": "integer" },
              "offset": { "type": "integer" },
              "total": { "type": "integer" },
              "has_more": { "type": "boolean" }
            }
          },
          "filters": {
            "type": "object",
            "description": "Lists of distinct values available for each filter field, useful for building filter UIs.",
            "properties": {
              "available_genders": {
                "type": "array",
                "items": { "type": "string" }
              },
              "available_providers": {
                "type": "array",
                "items": { "type": "string" }
              },
              "available_languages": {
                "type": "array",
                "items": { "type": "string" }
              },
              "available_accents": {
                "type": "array",
                "items": { "type": "string" }
              }
            }
          }
        }
      },
      "ListCampaignsResponse": {
        "type": "object",
        "properties": {
          "campaigns": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/CampaignResponse" }
          },
          "pagination": {
            "type": "object",
            "properties": {
              "limit": { "type": "integer" },
              "offset": { "type": "integer" },
              "total": { "type": "integer" },
              "has_more": { "type": "boolean" }
            }
          }
        }
      }
    },
    "securitySchemes": {
      "api_key": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "API Key",
        "description": "API key authentication. Include your API key in the Authorization header as: `Authorization: Bearer <your-api-key>`"
      }
    }
  },
  "servers": [
    {
      "url": "https://api.openmic.ai",
      "description": "Production Environment"
    }
  ]
}
