{
  "openapi": "3.1.0",
  "info": {
    "title": "Vocily API",
    "description": "Public REST API for Vocily. Build and configure an agent, publish a version and put it live, place outbound calls, and read back calls, chats and what the agent remembered. Authenticate with a workspace API key as a Bearer token.\n\nSome things stay in the dashboard, by design: creating an API key, buying or connecting a phone number, setting an agent's webhook URL, connecting WhatsApp and its templates, building HTTP tools, and running batch campaigns.",
    "version": "v1"
  },
  "paths": {
    "/v1/agents": {
      "get": {
        "tags": [
          "agents"
        ],
        "summary": "List agents",
        "description": "List your workspace's agents (`id` and `name`) so you can pick an `agent_id` for `POST /v1/calls`.",
        "operationId": "list_agents_v1_agents_get",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page",
              "title": "Cursor"
            },
            "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum records to return in one page."
          }
        ],
        "responses": {
          "200": {
            "description": "The workspace's agents. A summary \u2014 configuration lives behind get-by-id, so listing stays cheap.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PublicAgentSummary"
                      },
                      "description": "The rows on this page."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page exists. `false` on the last."
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pass back as `?cursor=` for the next page; `null` on the last one. **Opaque** \u2014 do not parse or construct one. A cursor from a differently sorted list is refused with `invalid_cursor` rather than silently returning page 1."
                    }
                  },
                  "required": [
                    "data",
                    "has_more"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "id": "00000005-0000-4000-8000-000000000005",
                      "name": "Support line",
                      "is_live": false,
                      "live_version": null,
                      "latest_version": 0,
                      "inbound_phone": null,
                      "created_at": "2026-09-16T19:38:03.767024Z",
                      "updated_at": "2026-09-16T19:38:03.767024Z"
                    },
                    {
                      "id": "00000008-0000-4000-8000-000000000008",
                      "name": "Acme COD Confirmation",
                      "is_live": false,
                      "live_version": null,
                      "latest_version": 2,
                      "inbound_phone": null,
                      "created_at": "2026-09-15T21:38:38.254381Z",
                      "updated_at": "2026-09-16T17:14:20.605104Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "post": {
        "tags": [
          "agents"
        ],
        "summary": "Create Agent",
        "description": "Create an agent, fully configured, in one request \u2014 prompt, voice, model, built-in tools, transfer numbers, variables, memory and numbers.\n\nThe agent is created as an unpublished **draft, version 0**. It answers no call until you publish a version and make it live.\n\nCustom tools are built in the dashboard, not here: this body neither accepts nor returns them, and a prompt that arms one the agent does not have is refused.",
        "operationId": "create_agent_v1_agents_post",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicAgentCreate"
              },
              "example": {
                "name": "Acme COD Confirmation",
                "system_prompt": "## Agent Purpose\nYou confirm cash-on-delivery orders for Acme Store.\n\n## Response Style\nWarm, brief, one question at a time.\n\n## Call Flow\n1. Greet {{callee_name}}.\n2. Read back the order.\n3. Ask whether they will accept delivery.",
                "greeting": {
                  "message": "Namaste {{callee_name}}, main Acme Store se bol rahi hoon."
                },
                "language": {
                  "default": "hi-IN",
                  "additional": [
                    "en-IN"
                  ]
                },
                "voice": {
                  "provider": "vocily",
                  "voice_id": "hi-IN-aman",
                  "speed": 1.0
                },
                "model": {
                  "model": "gpt-5.4-nano",
                  "temperature": 0.4
                },
                "transcriber": {
                  "provider": "sarvam",
                  "model": "saaras:v4",
                  "keywords": [
                    "Acme",
                    "COD"
                  ]
                },
                "call": {
                  "max_duration_minutes": 5,
                  "recording_enabled": true
                },
                "builtin_tools": {
                  "transfer_call": {
                    "enabled": true,
                    "numbers": [
                      {
                        "number": "+919876543210",
                        "priority": 1,
                        "start_hour": 9,
                        "end_hour": 20,
                        "timezone": "Asia/Kolkata"
                      }
                    ]
                  }
                },
                "variables": [
                  {
                    "key": "order_id",
                    "default_value": null
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created agent, at its V0 draft. It answers no calls until a version is published and made live.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicAgentDetail"
                },
                "example": {
                  "id": "00000005-0000-4000-8000-000000000005",
                  "name": "Support line",
                  "version": 0,
                  "version_id": "00000006-0000-4000-8000-000000000006",
                  "is_published": false,
                  "is_live": false,
                  "live_version": null,
                  "latest_version": 0,
                  "document_revision": 1,
                  "label": null,
                  "notes": null,
                  "blocked_reasons": [],
                  "created_at": "2026-09-16T19:38:03.767024Z",
                  "updated_at": "2026-09-16T19:38:03.767024Z",
                  "system_prompt": "## Agent Purpose\nYou confirm cash-on-delivery orders for Acme Store.\n\n## Response Style\nWarm, brief, one question at a time.\n\n## Call Flow\n1. Greet {{callee_name}}.\n2. Read back order {{order_id}}.\n3. Ask whether they accept delivery.\n4. Close politely.",
                  "greeting": {},
                  "language": {
                    "default": "hi-IN",
                    "additional": [
                      "en-IN"
                    ],
                    "switch_trigger": "requested_or_auto"
                  },
                  "transcriber": {
                    "provider": "sarvam",
                    "model": "saaras:v4",
                    "keywords": [
                      "Acme",
                      "COD"
                    ],
                    "fallback": {
                      "provider": "deepgram",
                      "model": "nova-3-general"
                    }
                  },
                  "model": {
                    "provider": "openai",
                    "model": "gpt-5.4-nano",
                    "temperature": 0.4,
                    "max_tokens": 128,
                    "fallback": {
                      "provider": "gemini",
                      "model": "gemini-3.5-flash-lite"
                    }
                  },
                  "voice": {
                    "provider": "vocily",
                    "model": "v2",
                    "voice_id": "hi-IN-aman",
                    "speed": 1,
                    "emotion": null,
                    "fallback": {
                      "provider": "sarvam",
                      "model": "bulbul:v3",
                      "voice_id": "shubh"
                    }
                  },
                  "conversation": {
                    "interruption_sensitivity": 0.5,
                    "response_eagerness": 0.75,
                    "noise_handling": {
                      "mode": "standard",
                      "level": 50
                    },
                    "silence_reminder": {
                      "enabled": true,
                      "seconds": 15
                    }
                  },
                  "call": {
                    "max_duration_minutes": 5,
                    "end_on_silence_seconds": 25,
                    "recording_enabled": true,
                    "custom_analysis_enabled": true,
                    "max_duration_message": {
                      "mode": "default",
                      "prompt": "The call has reached its maximum allowed duration and must end now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: the maximum call time has been reached, so the call is ending now. Keep it to one short sentence, with an optional brief thank-you. Do not ask a question. Do not offer more help, a callback, next steps, or reopen the conversation.",
                      "text": ""
                    },
                    "end_on_silence_message": {
                      "mode": "default",
                      "prompt": "The caller has been silent for too long and the call is ending now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: you could not hear anything on the line, so you are ending the call now. Keep it to one short sentence, with an optional brief thank-you. Do not ask a question. Do not offer more help, a callback, next steps, or reopen the conversation.",
                      "text": ""
                    }
                  },
                  "builtin_tools": {
                    "end_call": {
                      "enabled": true
                    },
                    "hold_call": {
                      "enabled": true,
                      "max_seconds": 90,
                      "follow_up_seconds": 45,
                      "acknowledgement_message": {
                        "mode": "default",
                        "prompt": "Write one short sentence to say to the caller as you start waiting, in the language you have been speaking \u2014 confirming you heard them and will wait. Do not ask a question and do not guess why they need the moment.",
                        "text": ""
                      },
                      "follow_up_message": {
                        "mode": "default",
                        "prompt": "You agreed to wait while the caller stepped away for a moment (they may be fetching a card, a document, or checking something). Generate one very short, gentle check-in in the same language and tone as the conversation above. Keep it to one short sentence, e.g. asking if they are back or reassuring them you are still on the line. Do not say goodbye. Do not say the call is ending. Do not repeat earlier content or ask new questions.",
                        "text": ""
                      },
                      "timeout_message": {
                        "mode": "default",
                        "prompt": "You agreed to wait while the caller stepped away, but they have not returned and the call is ending now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: you waited but could not reach them, so you are ending the call; they are welcome to call back. Keep it to one short sentence. Do not ask a question.",
                        "text": ""
                      }
                    },
                    "transfer_call": {
                      "enabled": true,
                      "numbers": [
                        {
                          "number": "+919876543210",
                          "priority": 1,
                          "start_hour": 9,
                          "end_hour": 20,
                          "timezone": "Asia/Kolkata",
                          "max_concurrent_calls": 1
                        }
                      ],
                      "busy_message": {
                        "mode": "default",
                        "prompt": "You tried to transfer the caller to a human teammate, but nobody is available. Generate one short line in the same language and tone as the conversation above, saying the team is busy right now and asking them to try again a little later. Do not ask a question and do not promise a callback.",
                        "text": ""
                      },
                      "intro_message": {
                        "mode": "custom",
                        "prompt": "You are about to transfer the caller to a human teammate. Generate one short line in the same language and tone as the conversation above, telling them to hold while you connect them. Do not ask a question and do not promise a specific person, a wait time or a callback.",
                        "text": "Ek minute, main aapko connect karti hoon."
                      }
                    },
                    "send_whatsapp_template": {
                      "enabled": false,
                      "allowed_templates": [],
                      "phone_number_id": ""
                    }
                  },
                  "variables": [
                    {
                      "key": "callee_name",
                      "default_value": null,
                      "system_defined": true,
                      "deletable": false
                    },
                    {
                      "key": "callee_number",
                      "default_value": null,
                      "system_defined": true,
                      "deletable": false
                    }
                  ],
                  "knowledge_base_ids": [],
                  "analysis_group_ids": [
                    "00000007-0000-4000-8000-000000000007"
                  ],
                  "memory": {
                    "enabled": true,
                    "channels": [
                      "outbound",
                      "whatsapp"
                    ],
                    "allow_ai_labels": true,
                    "label_instructions": "Record anything about the caller worth knowing next time, even when it is not one of the fields above: who they are, other ways to reach them, how they prefer to be dealt with, their standing with the business, or anything situational. Only what will still be true later; nothing said in passing.",
                    "max_facts": 150,
                    "transcript_turns": 12,
                    "fields": [
                      {
                        "key": "delivery_pincode",
                        "label": "Delivery PIN code",
                        "type": "string",
                        "enum_values": null,
                        "description": "The PIN code the caller wants deliveries sent to.",
                        "category": "contact"
                      }
                    ]
                  },
                  "numbers": null,
                  "dashboard_url": "https://app.vocily.ai/agents/00000005-0000-4000-8000-000000000005",
                  "inbound": {
                    "business_hours_closed_message": {
                      "mode": "default",
                      "prompt": "This inbound call arrived outside business hours. Generate one short line telling the caller we are closed right now and inviting them to call back during business hours. Keep it to one sentence. Do not ask a question and do not invent the opening hours.",
                      "text": ""
                    },
                    "fallback_message": {
                      "mode": "default",
                      "prompt": "This inbound call cannot be handled right now. Generate one short, apologetic line asking the caller to try again later. Keep it to one sentence. Do not ask a question and do not explain the technical reason.",
                      "text": ""
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          },
          "400": {
            "description": "The configuration cannot work as sent, and nothing is created or changed. `voice_not_found`: `voice.voice_id` \u2014 or a backup's \u2014 is not a voice that provider offers for the agent's language; `GET /v1/voices` lists them. `voice_config_invalid`: the voice block itself cannot work \u2014 an unknown or withdrawn provider, a provider that cannot speak a configured language, or a backup that could never be used. `document_invalid`: the field is real and the value well-formed, and the agent still cannot use it \u2014 a number in `numbers` this workspace does not hold (`GET /v1/numbers` and `GET /v1/whatsapp/numbers` list them), a hold check-in that lands after the hold ends, an emotion no provider speaks. `invalid_request`: the request itself is malformed \u2014 a `?version=` that is neither `live` nor a number, or an `If-Match` that is not a `document_revision`. Every message names the field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "examples": {
                  "voice_not_found": {
                    "value": {
                      "detail": {
                        "code": "voice_not_found",
                        "message": "`no-such-voice` is not a voice `vocily` offers for `hi-IN`. GET /v1/voices?provider=vocily&language=hi-IN lists the ones that are.",
                        "param": "voice.voice_id"
                      },
                      "code": "BAD_REQUEST"
                    }
                  },
                  "number_not_held": {
                    "value": {
                      "detail": {
                        "code": "document_invalid",
                        "message": "+919876543210 is not a number in this workspace. Choose one of the workspace's own numbers (GET /v1/numbers lists them)."
                      },
                      "code": "BAD_REQUEST"
                    }
                  }
                },
                "example": {
                  "detail": {
                    "code": "voice_config_invalid"
                  },
                  "code": "BAD_REQUEST"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}": {
      "patch": {
        "tags": [
          "agents"
        ],
        "summary": "Patch Agent",
        "description": "Change any setting on the agent's working draft \u2014 or on any version, with `?version=`.\n\nMerge-patch: objects merge, lists replace whole, `null` clears. Only what you name changes \u2014 everything else is left as it is.\n\n**Where the change lands.** `?version=3` changes that version, mirroring `GET /v1/agents/{agent_id}?version=3`. Without it the change goes to the agent's working draft: a new draft is branched from the live version when the newest version is published, an open draft is used when there is exactly one, and several open drafts are refused rather than guessed at \u2014 the error names every candidate.\n\nConfiguration lands on a draft and answers nothing until you publish it and make it live. A published version's configuration is refused with `version_immutable`: it is frozen, which is what makes rolling back to it exact.\n\n**Renaming.** `label` and `notes` name the version the change lands on, and are not configuration \u2014 so `?version=3` with `{\"label\": \"Holiday hours\"}` renames a published version too.",
        "operationId": "patch_agent_v1_agents__agent_id__patch",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "version",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Which version to change, by number \u2014 e.g. `3`. Omit to change the agent's working draft. A published version is refused: its configuration is frozen.",
              "title": "Version"
            },
            "description": "Which version to change, by number \u2014 e.g. `3`. Omit to change the agent's working draft. A published version is refused: its configuration is frozen."
          },
          {
            "name": "If-Match",
            "in": "header",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "The `document_revision` this change was composed against. Omit to write against whatever the draft holds now.",
              "title": "If-Match"
            },
            "description": "The `document_revision` this change was composed against. Omit to write against whatever the draft holds now."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicAgentUpdate"
              },
              "example": {
                "voice": {
                  "speed": 1.2
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The version the change landed on, after it \u2014 the working draft, or the one `?version=` named.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicAgentDetail"
                },
                "example": {
                  "id": "00000005-0000-4000-8000-000000000005",
                  "name": "Support line",
                  "version": 0,
                  "version_id": "00000006-0000-4000-8000-000000000006",
                  "is_published": false,
                  "is_live": false,
                  "live_version": null,
                  "latest_version": 0,
                  "document_revision": 2,
                  "label": null,
                  "notes": null,
                  "blocked_reasons": [],
                  "created_at": "2026-09-16T19:38:03.767024Z",
                  "updated_at": "2026-09-16T19:38:03.919698Z",
                  "system_prompt": "## Agent Purpose\nYou confirm cash-on-delivery orders for Acme Store.\n\n## Response Style\nWarm, brief, one question at a time.\n\n## Call Flow\n1. Greet {{callee_name}}.\n2. Read back order {{order_id}}.\n3. Ask whether they accept delivery.\n4. Close politely.",
                  "greeting": {},
                  "language": {
                    "default": "hi-IN",
                    "additional": [
                      "en-IN"
                    ],
                    "switch_trigger": "requested_or_auto"
                  },
                  "transcriber": {
                    "provider": "sarvam",
                    "model": "saaras:v4",
                    "keywords": [
                      "Acme",
                      "COD"
                    ],
                    "fallback": {
                      "provider": "deepgram",
                      "model": "nova-3-general"
                    }
                  },
                  "model": {
                    "provider": "openai",
                    "model": "gpt-5.4-nano",
                    "temperature": 0.4,
                    "max_tokens": 128,
                    "fallback": {
                      "provider": "gemini",
                      "model": "gemini-3.5-flash-lite"
                    }
                  },
                  "voice": {
                    "provider": "vocily",
                    "model": "v2",
                    "voice_id": "hi-IN-aman",
                    "speed": 1.3,
                    "emotion": null,
                    "fallback": {
                      "provider": "sarvam",
                      "model": "bulbul:v3",
                      "voice_id": "shubh"
                    }
                  },
                  "conversation": {
                    "interruption_sensitivity": 0.5,
                    "response_eagerness": 0.75,
                    "noise_handling": {
                      "mode": "standard",
                      "level": 50
                    },
                    "silence_reminder": {
                      "enabled": true,
                      "seconds": 15
                    }
                  },
                  "call": {
                    "max_duration_minutes": 5,
                    "end_on_silence_seconds": 25,
                    "recording_enabled": true,
                    "custom_analysis_enabled": true,
                    "max_duration_message": {
                      "mode": "default",
                      "prompt": "The call has reached its maximum allowed duration and must end now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: the maximum call time has been reached, so the call is ending now. Keep it to one short sentence, with an optional brief thank-you. Do not ask a question. Do not offer more help, a callback, next steps, or reopen the conversation.",
                      "text": ""
                    },
                    "end_on_silence_message": {
                      "mode": "default",
                      "prompt": "The caller has been silent for too long and the call is ending now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: you could not hear anything on the line, so you are ending the call now. Keep it to one short sentence, with an optional brief thank-you. Do not ask a question. Do not offer more help, a callback, next steps, or reopen the conversation.",
                      "text": ""
                    }
                  },
                  "builtin_tools": {
                    "end_call": {
                      "enabled": true
                    },
                    "hold_call": {
                      "enabled": true,
                      "max_seconds": 90,
                      "follow_up_seconds": 45,
                      "acknowledgement_message": {
                        "mode": "default",
                        "prompt": "Write one short sentence to say to the caller as you start waiting, in the language you have been speaking \u2014 confirming you heard them and will wait. Do not ask a question and do not guess why they need the moment.",
                        "text": ""
                      },
                      "follow_up_message": {
                        "mode": "default",
                        "prompt": "You agreed to wait while the caller stepped away for a moment (they may be fetching a card, a document, or checking something). Generate one very short, gentle check-in in the same language and tone as the conversation above. Keep it to one short sentence, e.g. asking if they are back or reassuring them you are still on the line. Do not say goodbye. Do not say the call is ending. Do not repeat earlier content or ask new questions.",
                        "text": ""
                      },
                      "timeout_message": {
                        "mode": "default",
                        "prompt": "You agreed to wait while the caller stepped away, but they have not returned and the call is ending now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: you waited but could not reach them, so you are ending the call; they are welcome to call back. Keep it to one short sentence. Do not ask a question.",
                        "text": ""
                      }
                    },
                    "transfer_call": {
                      "enabled": true,
                      "numbers": [
                        {
                          "number": "+919876543210",
                          "priority": 1,
                          "start_hour": 9,
                          "end_hour": 20,
                          "timezone": "Asia/Kolkata",
                          "max_concurrent_calls": 1
                        }
                      ],
                      "busy_message": {
                        "mode": "default",
                        "prompt": "You tried to transfer the caller to a human teammate, but nobody is available. Generate one short line in the same language and tone as the conversation above, saying the team is busy right now and asking them to try again a little later. Do not ask a question and do not promise a callback.",
                        "text": ""
                      },
                      "intro_message": {
                        "mode": "custom",
                        "prompt": "You are about to transfer the caller to a human teammate. Generate one short line in the same language and tone as the conversation above, telling them to hold while you connect them. Do not ask a question and do not promise a specific person, a wait time or a callback.",
                        "text": "Ek minute, main aapko connect karti hoon."
                      }
                    },
                    "send_whatsapp_template": {
                      "enabled": false,
                      "allowed_templates": [],
                      "phone_number_id": ""
                    }
                  },
                  "variables": [
                    {
                      "key": "callee_name",
                      "default_value": null,
                      "system_defined": true,
                      "deletable": false
                    },
                    {
                      "key": "callee_number",
                      "default_value": null,
                      "system_defined": true,
                      "deletable": false
                    }
                  ],
                  "knowledge_base_ids": [],
                  "analysis_group_ids": [
                    "00000007-0000-4000-8000-000000000007"
                  ],
                  "memory": {
                    "enabled": true,
                    "channels": [
                      "outbound",
                      "whatsapp"
                    ],
                    "allow_ai_labels": true,
                    "label_instructions": "Record anything about the caller worth knowing next time, even when it is not one of the fields above: who they are, other ways to reach them, how they prefer to be dealt with, their standing with the business, or anything situational. Only what will still be true later; nothing said in passing.",
                    "max_facts": 150,
                    "transcript_turns": 12,
                    "fields": [
                      {
                        "key": "delivery_pincode",
                        "label": "Delivery PIN code",
                        "type": "string",
                        "enum_values": null,
                        "description": "The PIN code the caller wants deliveries sent to.",
                        "category": "contact"
                      }
                    ]
                  },
                  "numbers": null,
                  "dashboard_url": "https://app.vocily.ai/agents/00000005-0000-4000-8000-000000000005",
                  "inbound": {
                    "business_hours_closed_message": {
                      "mode": "default",
                      "prompt": "This inbound call arrived outside business hours. Generate one short line telling the caller we are closed right now and inviting them to call back during business hours. Keep it to one sentence. Do not ask a question and do not invent the opening hours.",
                      "text": ""
                    },
                    "fallback_message": {
                      "mode": "default",
                      "prompt": "This inbound call cannot be handled right now. Generate one short, apologetic line asking the caller to try again later. Keep it to one sentence. Do not ask a question and do not explain the technical reason.",
                      "text": ""
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                },
                "example": {
                  "detail": {
                    "code": "validation_error",
                    "errors": [
                      {
                        "field": "voice.pitch",
                        "type": "extra_forbidden"
                      }
                    ]
                  },
                  "code": "VALIDATION_ERROR"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          },
          "409": {
            "description": "`version_immutable`: `?version=` named a published version and the body changes its configuration, which is frozen once published \u2014 `label` and `notes` still apply. `multiple_drafts`: this agent has more than one unpublished draft, so which one to change is ambiguous. Name it \u2014 `PATCH /v1/agents/{agent_id}?version=2` \u2014 or publish or delete the ones you do not want. The body lists every candidate.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "multiple_drafts",
                    "message": "This agent has more than one unpublished draft, so it is not clear which one to change.",
                    "drafts": [
                      {
                        "version": 2,
                        "label": "Transfer hours"
                      },
                      {
                        "version": 1,
                        "label": "New greeting"
                      }
                    ]
                  },
                  "code": "CONFLICT"
                }
              }
            }
          },
          "400": {
            "description": "The configuration cannot work as sent, and nothing is created or changed. `voice_not_found`: `voice.voice_id` \u2014 or a backup's \u2014 is not a voice that provider offers for the agent's language; `GET /v1/voices` lists them. `voice_config_invalid`: the voice block itself cannot work \u2014 an unknown or withdrawn provider, a provider that cannot speak a configured language, or a backup that could never be used. `document_invalid`: the field is real and the value well-formed, and the agent still cannot use it \u2014 a number in `numbers` this workspace does not hold (`GET /v1/numbers` and `GET /v1/whatsapp/numbers` list them), a hold check-in that lands after the hold ends, an emotion no provider speaks. `invalid_request`: the request itself is malformed \u2014 a `?version=` that is neither `live` nor a number, or an `If-Match` that is not a `document_revision`. Every message names the field.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "examples": {
                  "voice_not_found": {
                    "value": {
                      "detail": {
                        "code": "voice_not_found",
                        "message": "`no-such-voice` is not a voice `vocily` offers for `hi-IN`. GET /v1/voices?provider=vocily&language=hi-IN lists the ones that are.",
                        "param": "voice.voice_id"
                      },
                      "code": "BAD_REQUEST"
                    }
                  },
                  "number_not_held": {
                    "value": {
                      "detail": {
                        "code": "document_invalid",
                        "message": "+919876543210 is not a number in this workspace. Choose one of the workspace's own numbers (GET /v1/numbers lists them)."
                      },
                      "code": "BAD_REQUEST"
                    }
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "get": {
        "tags": [
          "agents"
        ],
        "summary": "Get Agent",
        "description": "One agent's full configuration.\n\nReturns its LATEST version by default \u2014 what you last wrote. `?version=live` returns the version currently answering, and `?version=3` a specific one. Latest rather than live, so an agent you have just created reads back as you created it, before anything has been published.",
        "operationId": "get_agent_v1_agents__agent_id__get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "version",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "`live`, or a version number like `3`. Omit for the latest version.",
              "title": "Version"
            },
            "description": "`live`, or a version number like `3`. Omit for the latest version."
          }
        ],
        "responses": {
          "200": {
            "description": "The agent at the requested version \u2014 latest by default.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicAgentDetail"
                },
                "example": {
                  "id": "00000005-0000-4000-8000-000000000005",
                  "name": "Support line",
                  "version": 0,
                  "version_id": "00000006-0000-4000-8000-000000000006",
                  "is_published": false,
                  "is_live": false,
                  "live_version": null,
                  "latest_version": 0,
                  "document_revision": 1,
                  "label": null,
                  "notes": null,
                  "blocked_reasons": [],
                  "created_at": "2026-09-16T19:38:03.767024Z",
                  "updated_at": "2026-09-16T19:38:03.767024Z",
                  "system_prompt": "## Agent Purpose\nYou confirm cash-on-delivery orders for Acme Store.\n\n## Response Style\nWarm, brief, one question at a time.\n\n## Call Flow\n1. Greet {{callee_name}}.\n2. Read back order {{order_id}}.\n3. Ask whether they accept delivery.\n4. Close politely.",
                  "greeting": {},
                  "language": {
                    "default": "hi-IN",
                    "additional": [
                      "en-IN"
                    ],
                    "switch_trigger": "requested_or_auto"
                  },
                  "transcriber": {
                    "provider": "sarvam",
                    "model": "saaras:v4",
                    "keywords": [
                      "Acme",
                      "COD"
                    ],
                    "fallback": {
                      "provider": "deepgram",
                      "model": "nova-3-general"
                    }
                  },
                  "model": {
                    "provider": "openai",
                    "model": "gpt-5.4-nano",
                    "temperature": 0.4,
                    "max_tokens": 128,
                    "fallback": {
                      "provider": "gemini",
                      "model": "gemini-3.5-flash-lite"
                    }
                  },
                  "voice": {
                    "provider": "vocily",
                    "model": "v2",
                    "voice_id": "hi-IN-aman",
                    "speed": 1,
                    "emotion": null,
                    "fallback": {
                      "provider": "sarvam",
                      "model": "bulbul:v3",
                      "voice_id": "shubh"
                    }
                  },
                  "conversation": {
                    "interruption_sensitivity": 0.5,
                    "response_eagerness": 0.75,
                    "noise_handling": {
                      "mode": "standard",
                      "level": 50
                    },
                    "silence_reminder": {
                      "enabled": true,
                      "seconds": 15
                    }
                  },
                  "call": {
                    "max_duration_minutes": 5,
                    "end_on_silence_seconds": 25,
                    "recording_enabled": true,
                    "custom_analysis_enabled": true,
                    "max_duration_message": {
                      "mode": "default",
                      "prompt": "The call has reached its maximum allowed duration and must end now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: the maximum call time has been reached, so the call is ending now. Keep it to one short sentence, with an optional brief thank-you. Do not ask a question. Do not offer more help, a callback, next steps, or reopen the conversation.",
                      "text": ""
                    },
                    "end_on_silence_message": {
                      "mode": "default",
                      "prompt": "The caller has been silent for too long and the call is ending now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: you could not hear anything on the line, so you are ending the call now. Keep it to one short sentence, with an optional brief thank-you. Do not ask a question. Do not offer more help, a callback, next steps, or reopen the conversation.",
                      "text": ""
                    }
                  },
                  "builtin_tools": {
                    "end_call": {
                      "enabled": true
                    },
                    "hold_call": {
                      "enabled": true,
                      "max_seconds": 90,
                      "follow_up_seconds": 45,
                      "acknowledgement_message": {
                        "mode": "default",
                        "prompt": "Write one short sentence to say to the caller as you start waiting, in the language you have been speaking \u2014 confirming you heard them and will wait. Do not ask a question and do not guess why they need the moment.",
                        "text": ""
                      },
                      "follow_up_message": {
                        "mode": "default",
                        "prompt": "You agreed to wait while the caller stepped away for a moment (they may be fetching a card, a document, or checking something). Generate one very short, gentle check-in in the same language and tone as the conversation above. Keep it to one short sentence, e.g. asking if they are back or reassuring them you are still on the line. Do not say goodbye. Do not say the call is ending. Do not repeat earlier content or ask new questions.",
                        "text": ""
                      },
                      "timeout_message": {
                        "mode": "default",
                        "prompt": "You agreed to wait while the caller stepped away, but they have not returned and the call is ending now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: you waited but could not reach them, so you are ending the call; they are welcome to call back. Keep it to one short sentence. Do not ask a question.",
                        "text": ""
                      }
                    },
                    "transfer_call": {
                      "enabled": true,
                      "numbers": [
                        {
                          "number": "+919876543210",
                          "priority": 1,
                          "start_hour": 9,
                          "end_hour": 20,
                          "timezone": "Asia/Kolkata",
                          "max_concurrent_calls": 1
                        }
                      ],
                      "busy_message": {
                        "mode": "default",
                        "prompt": "You tried to transfer the caller to a human teammate, but nobody is available. Generate one short line in the same language and tone as the conversation above, saying the team is busy right now and asking them to try again a little later. Do not ask a question and do not promise a callback.",
                        "text": ""
                      },
                      "intro_message": {
                        "mode": "custom",
                        "prompt": "You are about to transfer the caller to a human teammate. Generate one short line in the same language and tone as the conversation above, telling them to hold while you connect them. Do not ask a question and do not promise a specific person, a wait time or a callback.",
                        "text": "Ek minute, main aapko connect karti hoon."
                      }
                    },
                    "send_whatsapp_template": {
                      "enabled": false,
                      "allowed_templates": [],
                      "phone_number_id": ""
                    }
                  },
                  "variables": [
                    {
                      "key": "callee_name",
                      "default_value": null,
                      "system_defined": true,
                      "deletable": false
                    },
                    {
                      "key": "callee_number",
                      "default_value": null,
                      "system_defined": true,
                      "deletable": false
                    }
                  ],
                  "knowledge_base_ids": [],
                  "analysis_group_ids": [
                    "00000007-0000-4000-8000-000000000007"
                  ],
                  "memory": {
                    "enabled": true,
                    "channels": [
                      "outbound",
                      "whatsapp"
                    ],
                    "allow_ai_labels": true,
                    "label_instructions": "Record anything about the caller worth knowing next time, even when it is not one of the fields above: who they are, other ways to reach them, how they prefer to be dealt with, their standing with the business, or anything situational. Only what will still be true later; nothing said in passing.",
                    "max_facts": 150,
                    "transcript_turns": 12,
                    "fields": [
                      {
                        "key": "delivery_pincode",
                        "label": "Delivery PIN code",
                        "type": "string",
                        "enum_values": null,
                        "description": "The PIN code the caller wants deliveries sent to.",
                        "category": "contact"
                      }
                    ]
                  },
                  "numbers": null,
                  "dashboard_url": "https://app.vocily.ai/agents/00000005-0000-4000-8000-000000000005",
                  "inbound": {
                    "business_hours_closed_message": {
                      "mode": "default",
                      "prompt": "This inbound call arrived outside business hours. Generate one short line telling the caller we are closed right now and inviting them to call back during business hours. Keep it to one sentence. Do not ask a question and do not invent the opening hours.",
                      "text": ""
                    },
                    "fallback_message": {
                      "mode": "default",
                      "prompt": "This inbound call cannot be handled right now. Generate one short, apologetic line asking the caller to try again later. Keep it to one sentence. Do not ask a question and do not explain the technical reason.",
                      "text": ""
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "delete": {
        "tags": [
          "agents"
        ],
        "summary": "Delete Agent",
        "description": "Delete an agent. Past calls keep the name it had, so your history stays readable.",
        "operationId": "delete_agent_v1_agents__agent_id__delete",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/versions": {
      "get": {
        "tags": [
          "agent-versions"
        ],
        "summary": "List Versions",
        "description": "Every version of an agent, newest first.\n\nDrafts and published versions share one number line, so read `is_published` to tell them apart rather than splitting by number.",
        "operationId": "list_versions_v1_agents__agent_id__versions_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page",
              "title": "Cursor"
            },
            "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum records to return in one page."
          }
        ],
        "responses": {
          "200": {
            "description": "Every version, newest first. Drafts and published versions share one number line \u2014 split them by `is_published`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PublicVersionSummary"
                      },
                      "description": "The rows on this page."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page exists. `false` on the last."
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pass back as `?cursor=` for the next page; `null` on the last one. **Opaque** \u2014 do not parse or construct one. A cursor from a differently sorted list is refused with `invalid_cursor` rather than silently returning page 1."
                    }
                  },
                  "required": [
                    "data",
                    "has_more"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "version": 0,
                      "version_id": "00000006-0000-4000-8000-000000000006",
                      "is_published": false,
                      "is_live": false,
                      "label": null,
                      "notes": null,
                      "base_version": null,
                      "document_revision": 2,
                      "blocked_reasons": [],
                      "inbound_phone": null,
                      "inbound_whatsapp": null,
                      "created_at": "2026-09-16T19:38:03.767024Z",
                      "published_at": null
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/versions/{version_id}": {
      "get": {
        "tags": [
          "agent-versions"
        ],
        "summary": "Get Version",
        "description": "One version's full configuration.\n\nSecrets you have stored in tool headers come back redacted, as on every read. Send a redacted value back unchanged and the stored secret is kept.",
        "operationId": "get_version_v1_agents__agent_id__versions__version_id__get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "version_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Version Id"
            },
            "description": "A version **number** (`0`, `1`, `3`) or a version uuid \u2014 both resolve. Prefer the number: it is the version's identity to you, it is what every version read returns, and it needs no lookup first."
          }
        ],
        "responses": {
          "200": {
            "description": "The agent as this version configures it.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicAgentDetail"
                },
                "example": {
                  "id": "00000005-0000-4000-8000-000000000005",
                  "name": "Support line",
                  "version": 0,
                  "version_id": "00000006-0000-4000-8000-000000000006",
                  "is_published": false,
                  "is_live": false,
                  "live_version": null,
                  "latest_version": 0,
                  "document_revision": 2,
                  "label": null,
                  "notes": null,
                  "blocked_reasons": [],
                  "created_at": "2026-09-16T19:38:03.767024Z",
                  "updated_at": "2026-09-16T19:38:03.919698Z",
                  "system_prompt": "## Agent Purpose\nYou confirm cash-on-delivery orders for Acme Store.\n\n## Response Style\nWarm, brief, one question at a time.\n\n## Call Flow\n1. Greet {{callee_name}}.\n2. Read back order {{order_id}}.\n3. Ask whether they accept delivery.\n4. Close politely.",
                  "greeting": {},
                  "language": {
                    "default": "hi-IN",
                    "additional": [
                      "en-IN"
                    ],
                    "switch_trigger": "requested_or_auto"
                  },
                  "transcriber": {
                    "provider": "sarvam",
                    "model": "saaras:v4",
                    "keywords": [
                      "Acme",
                      "COD"
                    ],
                    "fallback": {
                      "provider": "deepgram",
                      "model": "nova-3-general"
                    }
                  },
                  "model": {
                    "provider": "openai",
                    "model": "gpt-5.4-nano",
                    "temperature": 0.4,
                    "max_tokens": 128,
                    "fallback": {
                      "provider": "gemini",
                      "model": "gemini-3.5-flash-lite"
                    }
                  },
                  "voice": {
                    "provider": "vocily",
                    "model": "v2",
                    "voice_id": "hi-IN-aman",
                    "speed": 1.3,
                    "emotion": null,
                    "fallback": {
                      "provider": "sarvam",
                      "model": "bulbul:v3",
                      "voice_id": "shubh"
                    }
                  },
                  "conversation": {
                    "interruption_sensitivity": 0.5,
                    "response_eagerness": 0.75,
                    "noise_handling": {
                      "mode": "standard",
                      "level": 50
                    },
                    "silence_reminder": {
                      "enabled": true,
                      "seconds": 15
                    }
                  },
                  "call": {
                    "max_duration_minutes": 5,
                    "end_on_silence_seconds": 25,
                    "recording_enabled": true,
                    "custom_analysis_enabled": true,
                    "max_duration_message": {
                      "mode": "default",
                      "prompt": "The call has reached its maximum allowed duration and must end now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: the maximum call time has been reached, so the call is ending now. Keep it to one short sentence, with an optional brief thank-you. Do not ask a question. Do not offer more help, a callback, next steps, or reopen the conversation.",
                      "text": ""
                    },
                    "end_on_silence_message": {
                      "mode": "default",
                      "prompt": "The caller has been silent for too long and the call is ending now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: you could not hear anything on the line, so you are ending the call now. Keep it to one short sentence, with an optional brief thank-you. Do not ask a question. Do not offer more help, a callback, next steps, or reopen the conversation.",
                      "text": ""
                    }
                  },
                  "builtin_tools": {
                    "end_call": {
                      "enabled": true
                    },
                    "hold_call": {
                      "enabled": true,
                      "max_seconds": 90,
                      "follow_up_seconds": 45,
                      "acknowledgement_message": {
                        "mode": "default",
                        "prompt": "Write one short sentence to say to the caller as you start waiting, in the language you have been speaking \u2014 confirming you heard them and will wait. Do not ask a question and do not guess why they need the moment.",
                        "text": ""
                      },
                      "follow_up_message": {
                        "mode": "default",
                        "prompt": "You agreed to wait while the caller stepped away for a moment (they may be fetching a card, a document, or checking something). Generate one very short, gentle check-in in the same language and tone as the conversation above. Keep it to one short sentence, e.g. asking if they are back or reassuring them you are still on the line. Do not say goodbye. Do not say the call is ending. Do not repeat earlier content or ask new questions.",
                        "text": ""
                      },
                      "timeout_message": {
                        "mode": "default",
                        "prompt": "You agreed to wait while the caller stepped away, but they have not returned and the call is ending now. Generate a brief, natural closing in the same language and tone as the conversation above. The message must clearly preserve this intent: you waited but could not reach them, so you are ending the call; they are welcome to call back. Keep it to one short sentence. Do not ask a question.",
                        "text": ""
                      }
                    },
                    "transfer_call": {
                      "enabled": true,
                      "numbers": [
                        {
                          "number": "+919876543210",
                          "priority": 1,
                          "start_hour": 9,
                          "end_hour": 20,
                          "timezone": "Asia/Kolkata",
                          "max_concurrent_calls": 1
                        }
                      ],
                      "busy_message": {
                        "mode": "default",
                        "prompt": "You tried to transfer the caller to a human teammate, but nobody is available. Generate one short line in the same language and tone as the conversation above, saying the team is busy right now and asking them to try again a little later. Do not ask a question and do not promise a callback.",
                        "text": ""
                      },
                      "intro_message": {
                        "mode": "custom",
                        "prompt": "You are about to transfer the caller to a human teammate. Generate one short line in the same language and tone as the conversation above, telling them to hold while you connect them. Do not ask a question and do not promise a specific person, a wait time or a callback.",
                        "text": "Ek minute, main aapko connect karti hoon."
                      }
                    },
                    "send_whatsapp_template": {
                      "enabled": false,
                      "allowed_templates": [],
                      "phone_number_id": ""
                    }
                  },
                  "variables": [
                    {
                      "key": "callee_name",
                      "default_value": null,
                      "system_defined": true,
                      "deletable": false
                    },
                    {
                      "key": "callee_number",
                      "default_value": null,
                      "system_defined": true,
                      "deletable": false
                    }
                  ],
                  "knowledge_base_ids": [],
                  "analysis_group_ids": [
                    "00000007-0000-4000-8000-000000000007"
                  ],
                  "memory": {
                    "enabled": true,
                    "channels": [
                      "outbound",
                      "whatsapp"
                    ],
                    "allow_ai_labels": true,
                    "label_instructions": "Record anything about the caller worth knowing next time, even when it is not one of the fields above: who they are, other ways to reach them, how they prefer to be dealt with, their standing with the business, or anything situational. Only what will still be true later; nothing said in passing.",
                    "max_facts": 150,
                    "transcript_turns": 12,
                    "fields": [
                      {
                        "key": "delivery_pincode",
                        "label": "Delivery PIN code",
                        "type": "string",
                        "enum_values": null,
                        "description": "The PIN code the caller wants deliveries sent to.",
                        "category": "contact"
                      }
                    ]
                  },
                  "numbers": null,
                  "dashboard_url": "https://app.vocily.ai/agents/00000005-0000-4000-8000-000000000005",
                  "inbound": {
                    "business_hours_closed_message": {
                      "mode": "default",
                      "prompt": "This inbound call arrived outside business hours. Generate one short line telling the caller we are closed right now and inviting them to call back during business hours. Keep it to one sentence. Do not ask a question and do not invent the opening hours.",
                      "text": ""
                    },
                    "fallback_message": {
                      "mode": "default",
                      "prompt": "This inbound call cannot be handled right now. Generate one short, apologetic line asking the caller to try again later. Keep it to one sentence. Do not ask a question and do not explain the technical reason.",
                      "text": ""
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "delete": {
        "tags": [
          "agent-versions"
        ],
        "summary": "Delete Version",
        "description": "Delete any version except the live one, or one an unfinished batch pins.",
        "operationId": "delete_version_v1_agents__agent_id__versions__version_id__delete",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "version_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Version Id"
            },
            "description": "A version **number** (`0`, `1`, `3`) or a version uuid \u2014 both resolve. Prefer the number: it is the version's identity to you, it is what every version read returns, and it needs no lookup first."
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/activations": {
      "get": {
        "tags": [
          "agent-versions"
        ],
        "summary": "List Activations",
        "description": "The deploy history, newest first, **cursor-paginated**.\n\nTwo things are recorded: a version going live, and the agent being taken off air.\n\n`activated_by_email` is left out: it names your own staff, and the WHAT and WHEN are the\ndeploy history; the WHO is internal to your team.",
        "operationId": "list_activations_v1_agents__agent_id__activations_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page",
              "title": "Cursor"
            },
            "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum records to return in one page."
          }
        ],
        "responses": {
          "200": {
            "description": "Deploy history, newest first: when each version started answering and when it stopped.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PublicActivation"
                      },
                      "description": "The rows on this page."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page exists. `false` on the last."
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pass back as `?cursor=` for the next page; `null` on the last one. **Opaque** \u2014 do not parse or construct one. A cursor from a differently sorted list is refused with `invalid_cursor` rather than silently returning page 1."
                    }
                  },
                  "required": [
                    "data",
                    "has_more"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "version": 0,
                      "version_id": "00000006-0000-4000-8000-000000000006",
                      "action": "live",
                      "at": "2026-09-16T19:38:04.028171Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/drafts": {
      "post": {
        "tags": [
          "agent-versions"
        ],
        "summary": "Create Draft",
        "description": "Branch a new draft from any version. An agent may hold as many drafts as you like, and editing one never disturbs another.\n\nName the base by version number \u2014 `{\"from_version\": 4}`. Omit it to branch from the live version.",
        "operationId": "create_draft_v1_agents__agent_id__drafts_post",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicDraftRequest"
              },
              "example": {
                "from_version": 4,
                "label": "Shorter greeting"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new draft, branched from the version you named.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicVersionSummary"
                },
                "example": {
                  "version": 2,
                  "version_id": "00000009-0000-4000-8000-000000000009",
                  "is_published": false,
                  "is_live": false,
                  "label": "Second",
                  "notes": null,
                  "base_version": 0,
                  "document_revision": 1,
                  "blocked_reasons": [],
                  "inbound_phone": null,
                  "inbound_whatsapp": null,
                  "created_at": "2026-09-16T19:38:04.119386Z",
                  "published_at": null
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/versions/{version_id}/publish": {
      "post": {
        "tags": [
          "agent-versions"
        ],
        "summary": "Publish Version",
        "description": "Freeze a draft. **Does not go live** \u2014 unless you ask for both with `{\"make_live\": true}`.\n\nThat flag is never a shortcut past the gate: it re-checks `agents:publish` before moving\nanything. It exists because a script deploying twenty agents should not need forty calls.",
        "operationId": "publish_version_v1_agents__agent_id__versions__version_id__publish_post",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "version_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Version Id"
            },
            "description": "A version **number** (`0`, `1`, `3`) or a version uuid \u2014 both resolve. Prefer the number: it is the version's identity to you, it is what every version read returns, and it needs no lookup first."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublishRequest"
              },
              "example": {
                "label": "Shorter greeting",
                "make_live": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The frozen version. Publishing does NOT deploy unless you sent `make_live: true`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicVersionSummary"
                },
                "example": {
                  "version": 0,
                  "version_id": "00000006-0000-4000-8000-000000000006",
                  "is_published": true,
                  "is_live": false,
                  "label": "Autumn release",
                  "notes": null,
                  "base_version": null,
                  "document_revision": 2,
                  "blocked_reasons": [],
                  "inbound_phone": null,
                  "inbound_whatsapp": null,
                  "created_at": "2026-09-16T19:38:03.767024Z",
                  "published_at": "2026-09-16T19:38:03.999783Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/versions/{version_id}/make-live": {
      "post": {
        "tags": [
          "agent-versions"
        ],
        "summary": "Make Version Live",
        "description": "Point the agent at this version. The only action real callers feel.\n\nPointer only \u2014 no draft is touched, so rolling back never costs work in progress.",
        "operationId": "make_version_live_v1_agents__agent_id__versions__version_id__make_live_post",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "version_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Version Id"
            },
            "description": "A version **number** (`0`, `1`, `3`) or a version uuid \u2014 both resolve. Prefer the number: it is the version's identity to you, it is what every version read returns, and it needs no lookup first."
          }
        ],
        "responses": {
          "200": {
            "description": "The version now answering calls.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicVersionSummary"
                },
                "example": {
                  "version": 0,
                  "version_id": "00000006-0000-4000-8000-000000000006",
                  "is_published": true,
                  "is_live": true,
                  "label": "Renamed",
                  "notes": null,
                  "base_version": null,
                  "document_revision": 2,
                  "blocked_reasons": [],
                  "inbound_phone": null,
                  "inbound_whatsapp": null,
                  "created_at": "2026-09-16T19:38:03.767024Z",
                  "published_at": "2026-09-16T19:38:03.999783Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/live": {
      "delete": {
        "tags": [
          "agent-versions"
        ],
        "summary": "Take Agent Off Air",
        "description": "Stop this agent answering, and release the numbers it answered on.\n\nAfterwards inbound calls and WhatsApp no longer reach it, new outbound calls and batches\nare refused, and its numbers are free for another agent to claim. Returns the version it\nwas taken off, so you can name it.",
        "operationId": "take_agent_off_air_v1_agents__agent_id__live_delete",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          }
        ],
        "responses": {
          "200": {
            "description": "The version the agent was taken off. It still exists \u2014 nothing is deleted.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicVersionSummary"
                },
                "example": {
                  "version": 0,
                  "version_id": "00000006-0000-4000-8000-000000000006",
                  "is_published": true,
                  "is_live": false,
                  "label": "Renamed",
                  "notes": null,
                  "base_version": null,
                  "document_revision": 2,
                  "blocked_reasons": [],
                  "inbound_phone": null,
                  "inbound_whatsapp": null,
                  "created_at": "2026-09-16T19:38:03.767024Z",
                  "published_at": "2026-09-16T19:38:03.999783Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/compare": {
      "get": {
        "tags": [
          "agent-versions"
        ],
        "summary": "Compare Versions",
        "description": "Compare any two versions \u2014 any pair, not only a draft against the live version.\n\nCompares configuration only. Labels, timestamps and version numbers are left out of the diff: they say nothing about how the agent behaves.",
        "operationId": "compare_versions_v1_agents__agent_id__compare_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "left",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "version number, e.g. `3`",
              "title": "Left"
            },
            "description": "version number, e.g. `3`"
          },
          {
            "name": "right",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "version number, e.g. `4`",
              "title": "Right"
            },
            "description": "version number, e.g. `4`"
          }
        ],
        "responses": {
          "200": {
            "description": "What differs between the two versions, named in this API's own fields.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicVersionCompare"
                },
                "example": {
                  "left": {
                    "version": 0,
                    "version_id": "00000006-0000-4000-8000-000000000006",
                    "is_published": true,
                    "is_live": true,
                    "label": "Renamed",
                    "notes": null,
                    "base_version": null,
                    "document_revision": 2,
                    "blocked_reasons": [],
                    "inbound_phone": null,
                    "inbound_whatsapp": null,
                    "created_at": "2026-09-16T19:38:03.767024Z",
                    "published_at": "2026-09-16T19:38:03.999783Z"
                  },
                  "right": {
                    "version": 1,
                    "version_id": "0000000a-0000-4000-8000-00000000000a",
                    "is_published": false,
                    "is_live": false,
                    "label": null,
                    "notes": null,
                    "base_version": 0,
                    "document_revision": 2,
                    "blocked_reasons": [],
                    "inbound_phone": null,
                    "inbound_whatsapp": null,
                    "created_at": "2026-09-16T19:38:04.059129Z",
                    "published_at": null
                  },
                  "differences": [
                    {
                      "field": "call.max_duration_minutes",
                      "change": "changed",
                      "before": 5,
                      "after": 9
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/voices": {
      "get": {
        "tags": [
          "catalogues"
        ],
        "summary": "List Voices",
        "description": "Voices you can put in `voice.voice_id`.\n\n`languages` is the set a voice is certified for, and it is what decides whether an\nagent can be saved: a provider handed a language it cannot speak fails while the\npipeline is being built, so the call dies before the caller hears anything. Vocily\npublishes per-voice locales; the other providers certify per PROVIDER, so every voice\nof theirs carries the provider's own list (`GET /v1/tts-capabilities`).",
        "operationId": "list_voices_v1_voices_get",
        "parameters": [
          {
            "name": "provider",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only this provider's voices. Omit for every provider.",
              "title": "Provider"
            },
            "description": "Only this provider's voices. Omit for every provider."
          },
          {
            "name": "language",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Only voices certified for this language code, e.g. `hi-IN`.",
              "title": "Language"
            },
            "description": "Only voices certified for this language code, e.g. `hi-IN`."
          }
        ],
        "responses": {
          "200": {
            "description": "Voices you can put in `voice.voice_id`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "type": "string",
                        "enum": [
                          "vocily",
                          "sarvam",
                          "cartesia",
                          "elevenlabs",
                          "smallest"
                        ]
                      },
                      "voice_id": {
                        "type": "string",
                        "description": "What goes in `voice.voice_id`."
                      },
                      "name": {
                        "type": "string"
                      },
                      "gender": {
                        "type": "string"
                      },
                      "language": {
                        "type": "string",
                        "description": "The voice's own language, e.g. `hi-IN`."
                      },
                      "languages": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Every language this voice is certified for. An agent whose `language.default` is not in here is refused on save."
                      }
                    }
                  }
                },
                "example": [
                  {
                    "provider": "vocily",
                    "voice_id": "bn-IN-abhik",
                    "name": "Abhik",
                    "gender": "male",
                    "language": "bn-IN",
                    "languages": [
                      "bn-IN",
                      "hi-IN"
                    ]
                  },
                  {
                    "provider": "vocily",
                    "voice_id": "bn-IN-arnab",
                    "name": "Arnab",
                    "gender": "male",
                    "language": "bn-IN",
                    "languages": [
                      "bn-IN",
                      "hi-IN"
                    ]
                  },
                  {
                    "provider": "elevenlabs",
                    "voice_id": "EXAVITQu4vr4xnSDxMaL",
                    "name": "Sarah",
                    "gender": "female",
                    "language": "Multi",
                    "languages": [
                      "ar",
                      "as-IN",
                      "bn-IN",
                      "de-DE",
                      "en-GB",
                      "en-IN",
                      "en-US",
                      "es-ES",
                      "fr-FR",
                      "gu-IN",
                      "hi-IN",
                      "it-IT",
                      "ja-JP",
                      "kn-IN",
                      "ml-IN",
                      "mr-IN",
                      "nl-NL",
                      "or-IN",
                      "pa-IN",
                      "pt-PT",
                      "ru-RU",
                      "ta-IN",
                      "te-IN",
                      "ur-IN"
                    ]
                  }
                ]
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/transcribers": {
      "get": {
        "tags": [
          "catalogues"
        ],
        "summary": "List Transcribers",
        "description": "Speech models you can put in `transcriber.model`.\n\nWhich component performs end-of-turn detection \u2014 ours or the model's own \u2014 is not\npublished: it is an implementation detail that changes with the roster (field review E1).\n\n`conversation.response_eagerness` applies on every model here. How it LANDS differs: most\nmodels take it as how long to wait, and a model that runs its own end-of-turn detector takes\nit as a confidence threshold for that detector instead. Either way the setting matters, which\nis why it is offered everywhere \u2014 but `response_speed_seconds` describes only the first kind,\nbecause the second answers on its own confidence rather than on a clock of ours.\n\n`response_speed_seconds` is keyed by preset NAME while the field itself takes the preset\nNUMBER: `fast` is `1`, `responsive` `0.75`, `balanced` `0.5`, `patient` `0`. The pairing is\nthe same for every model, so it is stated once in the field's own description rather than\nrepeated on all six rows here \u2014 the same reason the TTS model name sits on\n`GET /v1/tts-capabilities` and not on every `GET /v1/voices` row (field review Q9.9, Q16).",
        "operationId": "list_transcribers_v1_transcribers_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Speech models you can put in `transcriber.model`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "provider": {
                        "type": "string",
                        "enum": [
                          "sarvam",
                          "deepgram",
                          "soniox"
                        ]
                      },
                      "model": {
                        "type": "string",
                        "description": "What goes in `transcriber.model`."
                      },
                      "label": {
                        "type": "string"
                      },
                      "languages": {
                        "type": "array",
                        "items": {
                          "type": "string"
                        },
                        "description": "Every language in an agent's set must be covered, or the agent is refused on save."
                      },
                      "response_speed_seconds": {
                        "type": "object",
                        "additionalProperties": {
                          "type": "number"
                        },
                        "nullable": true,
                        "description": "Typical caller-stops-to-text seconds per response_eagerness preset, for THIS model. **Null on a model that answers on confidence rather than on a clock** \u2014 the preset still applies there, but no number describes it, so none is given. Check for null before reading a preset off it."
                      }
                    }
                  }
                },
                "example": [
                  {
                    "provider": "soniox",
                    "model": "soniox",
                    "label": "Soniox",
                    "languages": [
                      "bn-IN",
                      "de-DE"
                    ],
                    "response_speed_seconds": {
                      "fast": 0.45,
                      "responsive": 0.75,
                      "balanced": 1.05,
                      "patient": 1.65
                    }
                  },
                  {
                    "provider": "deepgram",
                    "model": "nova-2",
                    "label": "Nova 2",
                    "languages": [
                      "de-DE",
                      "en-GB"
                    ],
                    "response_speed_seconds": {
                      "fast": 0.6,
                      "responsive": 0.65,
                      "balanced": 0.75,
                      "patient": 0.85
                    }
                  }
                ]
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/tts-capabilities": {
      "get": {
        "tags": [
          "catalogues"
        ],
        "summary": "Get Tts Capabilities",
        "description": "Which languages each voice PROVIDER can be handed at all.\n\nA different question from which voice you get, and no voice choice avoids it: a\nKannada agent on Cartesia is refused on save because every voice in that catalogue\nwould fail the same way.",
        "operationId": "get_tts_capabilities_v1_tts_capabilities_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "What each voice provider can be handed at all \u2014 independent of which voice you pick. Check it before saving an agent: a provider handed a language it cannot speak is refused, and every voice of theirs would fail the same way.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "providers": {
                      "type": "object",
                      "additionalProperties": {
                        "type": "object",
                        "properties": {
                          "model": {
                            "type": "string",
                            "nullable": true,
                            "description": "The one model this provider ships. It is filled in from `voice.provider`, so `voice.model` is read-only \u2014 this is what the value means."
                          },
                          "languages": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            },
                            "description": "Every language this provider can be handed. A `language.default` outside it is refused on save."
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "providers": {
                    "cartesia": {
                      "model": "sonic-3.5",
                      "languages": [
                        "bn-IN",
                        "de-DE",
                        "en-GB",
                        "en-IN"
                      ]
                    },
                    "elevenlabs": {
                      "model": "eleven_turbo_v2_5",
                      "languages": [
                        "as-IN",
                        "bn-IN",
                        "de-DE",
                        "en-GB"
                      ]
                    },
                    "sarvam": {
                      "model": "bulbul:v3",
                      "languages": [
                        "bn-IN",
                        "en-GB",
                        "en-IN",
                        "en-US"
                      ]
                    },
                    "smallest": {
                      "model": "lightning-v3.1",
                      "languages": [
                        "as-IN",
                        "bn-IN",
                        "de-DE",
                        "en-GB"
                      ]
                    },
                    "vocily": {
                      "model": "v2",
                      "languages": [
                        "bn-IN",
                        "en-GB",
                        "en-IN",
                        "en-US"
                      ]
                    }
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/languages": {
      "get": {
        "tags": [
          "catalogues"
        ],
        "summary": "List Languages",
        "description": "Languages an agent can be configured in.\n\nDerived from the speech models that ship, so a language offered here is one some\nmodel can actually recognise.",
        "operationId": "list_languages_v1_languages_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Languages an agent can be configured in.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "code": {
                        "type": "string",
                        "description": "What goes in `language.default` and `language.additional`, e.g. `hi-IN`."
                      },
                      "label": {
                        "type": "string",
                        "description": "The language's name, for a picker."
                      }
                    }
                  }
                },
                "example": [
                  {
                    "code": "as-IN",
                    "label": "Assamese"
                  },
                  {
                    "code": "bn-IN",
                    "label": "Bengali"
                  }
                ]
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/whatsapp/numbers": {
      "get": {
        "tags": [
          "catalogues"
        ],
        "summary": "List Whatsapp Numbers",
        "description": "Connected WhatsApp numbers, for `numbers.inbound_whatsapp`.\n\n`phone_number_id` is what `builtin_tools.send_whatsapp_template.phone_number_id` takes.\n`status` is the connection state on Vocily; `meta_status` is what WhatsApp Manager shows \u2014\nboth, because \"why can't this number send\" needs both.",
        "operationId": "list_whatsapp_numbers_v1_whatsapp_numbers_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The workspace's connected WhatsApp numbers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string"
                      },
                      "phone_number_id": {
                        "type": "string",
                        "description": "What `builtin_tools.send_whatsapp_template.phone_number_id` takes."
                      },
                      "number": {
                        "type": "string",
                        "description": "E.164. What goes in `numbers.inbound_whatsapp`."
                      },
                      "verified_name": {
                        "type": "string",
                        "nullable": true
                      },
                      "status": {
                        "type": "string",
                        "description": "Our connection state."
                      },
                      "meta_status": {
                        "type": "string",
                        "nullable": true,
                        "description": "What WhatsApp Manager shows. Published alongside `status` because a number can be live on one side and not the other."
                      },
                      "assigned_agent_id": {
                        "type": "string",
                        "nullable": true,
                        "description": "Which agent answers on it today, if any."
                      }
                    }
                  }
                },
                "example": [
                  {
                    "id": "00000001-0000-4000-8000-000000000001",
                    "phone_number_id": "1160636770473887",
                    "number": "+919278045657",
                    "verified_name": "Lily from Vocily",
                    "status": "active",
                    "meta_status": "CONNECTED",
                    "assigned_agent_id": "00000002-0000-4000-8000-000000000002"
                  }
                ]
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/numbers": {
      "get": {
        "tags": [
          "numbers"
        ],
        "summary": "List Numbers",
        "description": "List the numbers assigned to this workspace. Carrier status is computed from the\norg's connected accounts, so a number whose account has gone shows as inactive.",
        "operationId": "list_numbers_v1_numbers_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "The numbers assigned to this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/PublicNumberRead"
                  }
                },
                "example": [
                  {
                    "id": "00000003-0000-4000-8000-000000000003",
                    "number": "+919876500000",
                    "carrier_status": "active",
                    "source": "byoc",
                    "provider": "plivo",
                    "provider_sid": null,
                    "connection_id": "00000004-0000-4000-8000-000000000004",
                    "lifecycle_status": "active",
                    "country_iso": null,
                    "number_type": null,
                    "inbound_agent": {
                      "id": "00000002-0000-4000-8000-000000000002",
                      "name": "zdfbdhjfbdkfbdkjfbkdjfb"
                    },
                    "outbound_agents": [
                      {
                        "id": "00000002-0000-4000-8000-000000000002",
                        "name": "zdfbdhjfbdkfbdkjfbkdjfb"
                      }
                    ],
                    "rental": null,
                    "created_at": "2026-09-12T22:45:02.810506Z",
                    "updated_at": "2026-09-12T23:02:43.014234Z"
                  }
                ]
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/calls": {
      "post": {
        "tags": [
          "calls"
        ],
        "summary": "Place a call",
        "description": "Start an outbound call with one of your agents. Returns a `202` acknowledgement with the call's `id`; the call then dials and runs asynchronously \u2014 track it with [webhooks](/developers/webhooks/overview) or `GET /v1/calls/{id}`. An `Idempotency-Key` header is required.",
        "operationId": "create_outbound_call_v1_calls_post",
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": true,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Idempotency-Key"
            },
            "description": "Your own unique string for this attempt. Required for API-key callers: a repeat within 24h returns the ORIGINAL call instead of placing a second one, which is what stops a network timeout from dialling \u2014 and charging \u2014 twice."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CallCreate"
              },
              "example": {
                "agent_id": "9b1c3d5e-7a90-4c21-8b6d-2e4f6a8c0d11",
                "to_number": "+919876543210",
                "from_number": "+911171366867",
                "variables": {
                  "customer_name": "Rahul"
                },
                "metadata": {
                  "order_id": "88431"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CallRead"
                },
                "example": {
                  "id": "c7a1e2b3-4d5f-6789-a0b1-c2d3e4f5a6b7",
                  "status": "started",
                  "metadata": {
                    "order_id": "88431"
                  }
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "400": {
            "description": "The Idempotency-Key header is required for API-key requests.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "idempotency_key_required",
                    "message": "The Idempotency-Key header is required for API-key requests."
                  },
                  "code": "BAD_REQUEST"
                }
              }
            }
          },
          "402": {
            "description": "Wallet balance is below the reserve required for this call.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "insufficient_balance",
                    "message": "Wallet balance is below the reserve required for this call."
                  }
                }
              }
            }
          },
          "403": {
            "description": "`from_number` is the shared Vocily Test Number, which is usable only from the dashboard.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "test_number_not_allowed",
                    "message": "`from_number` is the shared Vocily Test Number, which is usable only from the dashboard."
                  },
                  "code": "FORBIDDEN"
                }
              }
            }
          },
          "404": {
            "description": "Agent not found in this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "agent_not_found",
                    "message": "Agent not found in this workspace."
                  },
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "409": {
            "description": "Refused for capacity, with `Retry-After`: `concurrency_exceeded` when every outbound line of the organization is busy; `workspace_concurrency_exceeded` when the organization has lines free but this workspace's allocated ceiling is full (`X-Vocily-Workspace-Concurrency-Limit` carries the ceiling).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "concurrency_exceeded",
                    "message": "Refused for capacity, with `Retry-After`: `concurrency_exceeded` when every outbound line of the organization is busy; `workspace_concurrency_exceeded` when the organization has lines free but this workspace's allocated ceiling is full (`X-Vocily-Workspace-Concurrency-Limit` carries the ceiling)."
                  },
                  "code": "CONFLICT"
                }
              }
            }
          },
          "501": {
            "description": "The telephony provider is not configured.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "provider_not_configured",
                    "message": "The telephony provider is not configured."
                  }
                }
              }
            }
          },
          "503": {
            "description": "Vocily's carrier account is momentarily at its channel cap. Not the organization's limit; retry after `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "carrier_capacity_exceeded",
                    "message": "Vocily's carrier account is momentarily at its channel cap. Not the organization's limit; retry after `Retry-After`."
                  },
                  "code": "SERVICE_UNAVAILABLE"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "get": {
        "tags": [
          "calls"
        ],
        "summary": "List calls",
        "description": "List your workspace's calls, newest first, using cursor pagination. `transcript` is omitted from list items unless you pass `include=transcript`.",
        "operationId": "list_calls_v1_calls_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by agent id",
              "title": "Agent Id"
            },
            "description": "Filter by agent id"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter: started | in_progress | completed | voicemail | no_answer | busy | declined | failed | transferring | transfer_answered | transfer_completed | transfer_failed",
              "title": "Status"
            },
            "description": "Filter: started | in_progress | completed | voicemail | no_answer | busy | declined | failed | transferring | transfer_answered | transfer_completed | transfer_failed"
          },
          {
            "name": "direction",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter: `inbound`, `outbound`, or `web` for calls that happened in a browser (widget calls and dashboard tests). Omit for all three.",
              "title": "Direction"
            },
            "description": "Filter: `inbound`, `outbound`, or `web` for calls that happened in a browser (widget calls and dashboard tests). Omit for all three."
          },
          {
            "name": "origin",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by who started it \u2014 comma-list of: widget | dashboard | api | batch | inbound | demo. Use it to exclude your own dashboard test calls, e.g. `?origin=api,inbound`. Rows with an unknown origin are excluded when this is set.",
              "title": "Origin"
            },
            "description": "Filter by who started it \u2014 comma-list of: widget | dashboard | api | batch | inbound | demo. Use it to exclude your own dashboard test calls, e.g. `?origin=api,inbound`. Rows with an unknown origin are excluded when this is set."
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time"
                },
                {
                  "type": "null"
                }
              ],
              "description": "started_at >= this datetime",
              "title": "Date From"
            },
            "description": "started_at >= this datetime"
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time"
                },
                {
                  "type": "null"
                }
              ],
              "description": "started_at <= this datetime",
              "title": "Date To"
            },
            "description": "started_at <= this datetime"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page",
              "title": "Cursor"
            },
            "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page"
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Comma-list of heavy fields to include. Currently: `transcript`",
              "title": "Include"
            },
            "description": "Comma-list of heavy fields to include. Currently: `transcript`"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum records to return in one page."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCallList"
                },
                "example": {
                  "data": [
                    {
                      "id": "c7a1e2b3-4d5f-6789-a0b1-c2d3e4f5a6b7",
                      "agent_id": "9b1c3d5e-7a90-4c21-8b6d-2e4f6a8c0d11",
                      "status": "completed",
                      "direction": "outbound",
                      "from_number": "+911171366867",
                      "to_number": "+919876543210",
                      "duration_seconds": 42,
                      "created_at": "2026-08-04T10:00:00.000Z",
                      "connected_at": "2026-08-04T10:00:05.000Z",
                      "ended_at": "2026-08-04T10:00:47.000Z",
                      "metadata": {
                        "order_id": "88431"
                      },
                      "variables": {
                        "customer_name": "Rahul"
                      },
                      "cost": {
                        "currency": "USD",
                        "total": 0.0554,
                        "rate_per_min": 0.0792
                      },
                      "custom_analysis": {
                        "Default Analysis": {
                          "Call Summary": "Customer confirmed the appointment for Friday at 3pm.",
                          "User Sentiment": "positive",
                          "Outcome": "Appointment confirmed for Friday 3pm",
                          "Language": "English"
                        },
                        "Lead QA": {
                          "Lead Score": 9,
                          "Wants Callback": true
                        }
                      },
                      "transfer": null,
                      "transcript": null,
                      "recording_url": "https://api.vocily.ai/v1/calls/c7a1e2b3-4d5f-6789-a0b1-c2d3e4f5a6b7/recording"
                    }
                  ],
                  "has_more": true,
                  "next_cursor": "eyJzIjoiMjAyNi0wOC0wNFQxMDowMDowMC4wMDBaIiwiaSI6ImM3YTFlMmIzIn0"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "400": {
            "description": "The pagination cursor is invalid or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "invalid_cursor",
                    "message": "The pagination cursor is invalid or expired."
                  },
                  "code": "BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/calls/{call_id}": {
      "get": {
        "tags": [
          "calls"
        ],
        "summary": "Get a call",
        "description": "Fetch one call's full record \u2014 transcript, cost, recording link, and analysis. Cost and analysis populate once the call ends and post-processing finishes.",
        "operationId": "get_call_v1_calls__call_id__get",
        "parameters": [
          {
            "name": "call_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Call Id"
            },
            "description": "The call's id, from `POST /v1/calls` or `GET /v1/calls`."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicCallRead"
                },
                "example": {
                  "id": "c7a1e2b3-4d5f-6789-a0b1-c2d3e4f5a6b7",
                  "agent_id": "9b1c3d5e-7a90-4c21-8b6d-2e4f6a8c0d11",
                  "status": "completed",
                  "direction": "outbound",
                  "from_number": "+911171366867",
                  "to_number": "+919876543210",
                  "duration_seconds": 42,
                  "created_at": "2026-08-04T10:00:00.000Z",
                  "connected_at": "2026-08-04T10:00:05.000Z",
                  "ended_at": "2026-08-04T10:00:47.000Z",
                  "metadata": {
                    "order_id": "88431"
                  },
                  "variables": {
                    "customer_name": "Rahul"
                  },
                  "cost": {
                    "currency": "USD",
                    "total": 0.0554,
                    "rate_per_min": 0.0792
                  },
                  "custom_analysis": {
                    "Default Analysis": {
                      "Call Summary": "Customer confirmed the appointment for Friday at 3pm.",
                      "User Sentiment": "positive",
                      "Outcome": "Appointment confirmed for Friday 3pm",
                      "Language": "English"
                    },
                    "Lead QA": {
                      "Lead Score": 9,
                      "Wants Callback": true
                    }
                  },
                  "transfer": null,
                  "transcript": {
                    "turns": [
                      {
                        "role": "assistant",
                        "text": "Hi Rahul, this is Vocily calling about your order."
                      },
                      {
                        "role": "user",
                        "text": "Yes, go ahead."
                      }
                    ]
                  },
                  "recording_url": "https://api.vocily.ai/v1/calls/c7a1e2b3-4d5f-6789-a0b1-c2d3e4f5a6b7/recording"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "404": {
            "description": "Call not found (a malformed id also returns this).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "call_not_found",
                    "message": "Call not found (a malformed id also returns this)."
                  },
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/calls/{call_id}/recording": {
      "get": {
        "tags": [
          "calls"
        ],
        "summary": "Get a recording",
        "description": "Redirects (`307`) to a short-lived, pre-signed URL to download the call's audio. Any client that follows redirects works. Returns `404` until the recording is finalized.",
        "operationId": "get_call_recording_v1_calls__call_id__recording_get",
        "parameters": [
          {
            "name": "call_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Call Id"
            },
            "description": "The call's id, from `POST /v1/calls` or `GET /v1/calls`."
          }
        ],
        "responses": {
          "307": {
            "description": "Redirect (`Location`) to a short-lived pre-signed recording URL."
          },
          "404": {
            "description": "The recording isn't finalized yet, or the call was not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "recording_not_available",
                    "message": "Recording not available for this call."
                  },
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/chats": {
      "get": {
        "tags": [
          "chats"
        ],
        "summary": "List Chats",
        "description": "List this workspace's text conversations, newest first, cursor-paginated.\n\nSame paging contract as `GET /v1/calls`, so one loop reads both. `transcript` is omitted unless you ask for it with `?include=transcript` \u2014 it is large, and get-by-id always includes it.",
        "operationId": "list_chats_v1_chats_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by agent id",
              "title": "Agent Id"
            },
            "description": "Filter by agent id"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by status",
              "title": "Status"
            },
            "description": "Filter by status"
          },
          {
            "name": "origin",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Filter by who started it \u2014 comma-list of: widget | dashboard. Use it to exclude your own dashboard chat tests, e.g. `?origin=widget`. Rows with an unknown origin are excluded when this is set.",
              "title": "Origin"
            },
            "description": "Filter by who started it \u2014 comma-list of: widget | dashboard. Use it to exclude your own dashboard chat tests, e.g. `?origin=widget`. Rows with an unknown origin are excluded when this is set."
          },
          {
            "name": "date_from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time"
                },
                {
                  "type": "null"
                }
              ],
              "description": "started_at >= this datetime",
              "title": "Date From"
            },
            "description": "started_at >= this datetime"
          },
          {
            "name": "date_to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string",
                  "format": "date-time"
                },
                {
                  "type": "null"
                }
              ],
              "description": "started_at <= this datetime",
              "title": "Date To"
            },
            "description": "started_at <= this datetime"
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Opaque cursor from a previous response's `next_cursor`",
              "title": "Cursor"
            },
            "description": "Opaque cursor from a previous response's `next_cursor`"
          },
          {
            "name": "include",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Comma-list of heavy fields to include. Currently: `transcript`",
              "title": "Include"
            },
            "description": "Comma-list of heavy fields to include. Currently: `transcript`"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum records to return in one page."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicChatList"
                },
                "example": {
                  "data": [
                    {
                      "id": "00000015-0000-4000-8000-000000000015",
                      "agent_id": "00000002-0000-4000-8000-000000000002",
                      "agent_name": "zdfbdhjfbdkfbdkjfbkdjfb",
                      "agent_version": 7,
                      "status": "completed",
                      "origin": "dashboard",
                      "turn_count": 2,
                      "created_at": "2026-09-14T13:29:19.058795Z",
                      "ended_at": "2026-09-14T13:29:33.914425Z",
                      "metadata": null,
                      "variables": null,
                      "cost": {
                        "currency": "USD",
                        "total": 0.002,
                        "rate_per_reply": 0.001
                      },
                      "custom_analysis": {
                        "Default Analysis": {
                          "Outcome": "Awaiting clarification on property type (house or flat) and further needs; no resolution yet",
                          "Language": "Hindi/Hinglish",
                          "Call Summary": "The caller shared a phone number and the agent asked for whether they are looking for a house or a flat, engaging in initial needs gathering. The call is in early questioning; no property details or decisions were made yet.",
                          "User Sentiment": "neutral"
                        }
                      },
                      "transcript": null,
                      "dashboard_url": "https://app.vocily.ai/calls?execution_id=00000015-0000-4000-8000-000000000015"
                    },
                    {
                      "id": "00000016-0000-4000-8000-000000000016",
                      "agent_id": "00000002-0000-4000-8000-000000000002",
                      "agent_name": "zdfbdhjfbdkfbdkjfbkdjfb",
                      "agent_version": 7,
                      "status": "completed",
                      "origin": "dashboard",
                      "turn_count": 2,
                      "created_at": "2026-09-14T13:28:57.514415Z",
                      "ended_at": "2026-09-14T13:29:07.043869Z",
                      "metadata": null,
                      "variables": null,
                      "cost": {
                        "currency": "USD",
                        "total": 0.002,
                        "rate_per_reply": 0.001
                      },
                      "custom_analysis": null,
                      "transcript": null,
                      "dashboard_url": "https://app.vocily.ai/calls?execution_id=00000016-0000-4000-8000-000000000016"
                    }
                  ],
                  "has_more": true,
                  "next_cursor": "eyJzIjoiMjAyNi0wOS0xNFQxMzoyODo1Ny41MTQ0MTUrMDA6MDAiLCJpIjoiYTA4ODgwYzktOTJhNC00MDA1LWI4OWMtZTcyYWYxOWQ5MTNhIn0"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "400": {
            "description": "The pagination cursor is invalid or expired.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "invalid_cursor",
                    "message": "The pagination cursor is invalid or expired."
                  },
                  "code": "BAD_REQUEST"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/chats/{chat_id}": {
      "get": {
        "tags": [
          "chats"
        ],
        "summary": "Get Chat",
        "description": "Fetch one chat by id, transcript always included.\n\nA call's id here is a 404: calls and chats are separate resources, and a call is read from\n`GET /v1/calls/{id}`.",
        "operationId": "get_chat_v1_chats__chat_id__get",
        "parameters": [
          {
            "name": "chat_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Chat Id"
            },
            "description": "The chat's id, from `GET /v1/chats`."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicChatRead"
                },
                "example": {
                  "id": "00000002-0000-4000-8000-000000000002",
                  "agent_id": "00000003-0000-4000-8000-000000000003",
                  "agent_name": "Acme Support",
                  "agent_version": 4,
                  "status": "completed",
                  "origin": "widget",
                  "turn_count": 6,
                  "created_at": "2026-09-17T09:20:11Z",
                  "ended_at": "2026-09-17T09:24:48Z",
                  "metadata": {
                    "order_id": "88431"
                  },
                  "variables": {
                    "plan": "pro"
                  },
                  "cost": {
                    "currency": "USD",
                    "total": 0.012,
                    "rate_per_reply": 0.002
                  },
                  "custom_analysis": {
                    "Default Analysis": {
                      "User Sentiment": "positive",
                      "Call Outcome": "resolved"
                    }
                  },
                  "transcript": {
                    "turns": [
                      {
                        "role": "user",
                        "content": "where is order 88431"
                      },
                      {
                        "role": "assistant",
                        "content": "It shipped this morning \u2014 arriving Thursday."
                      }
                    ]
                  },
                  "dashboard_url": "https://app.vocily.ai/chats?execution_id=00000002-0000-4000-8000-000000000002"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "404": {
            "description": "Chat not found (a malformed id also returns this).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": {
                    "code": "chat_not_found",
                    "message": "Chat not found (a malformed id also returns this)."
                  },
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/models": {
      "get": {
        "tags": [
          "models"
        ],
        "summary": "List Models",
        "description": "LLMs you can put in `model.model`.\n\n`rate_per_min` is what this model contributes to a voice minute \u2014 **not** the price of a\ncall, which also carries speech recognition, the voice and telephony. `chat_price_per_reply`\nis what one chat or WhatsApp reply costs. Both are in major units of `currency`, the\norganization's billing currency, and each is null when the model is unavailable on that channel.\n\n`is_default` marks the one an agent gets when you omit `model`.\n\n`supports_temperature` says whether a custom `model.temperature` is honoured. It is accepted\non every model, to match the dashboard, so read this before setting one: on a model that\nreports `false` the value is stored and the call runs at the model's own default.",
        "operationId": "list_models_v1_models_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "LLMs you can put in `model.model`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "models": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string",
                            "description": "What goes in `model.model`."
                          },
                          "label": {
                            "type": "string"
                          },
                          "provider": {
                            "type": "string",
                            "enum": [
                              "openai",
                              "gemini",
                              "sarvam"
                            ],
                            "description": "Who runs this model. `model.provider` on an agent is derived from the model id, so there is nothing to set."
                          },
                          "provider_label": {
                            "type": "string"
                          },
                          "is_default": {
                            "type": "boolean",
                            "description": "The model an agent gets when you omit `model`."
                          },
                          "supports_temperature": {
                            "type": "boolean",
                            "description": "Whether a custom `model.temperature` is honoured. `temperature` is accepted on every model, so read this first: where it is `false`, the value is stored and the call runs at the model's own default."
                          },
                          "currency": {
                            "type": "string",
                            "enum": [
                              "USD",
                              "INR"
                            ],
                            "description": "The organization's billing currency. Both prices in this row are major units of this currency."
                          },
                          "rate_per_min": {
                            "type": "number",
                            "nullable": true,
                            "description": "What this model contributes to a voice minute, in major units of `currency` \u2014 not the price of a call, which also carries speech recognition, the voice and telephony. Null if this model cannot be used for voice."
                          },
                          "chat_price_per_reply": {
                            "type": "number",
                            "nullable": true,
                            "description": "Price in major units of `currency` for one chat or WhatsApp reply. This is a separate price from `rate_per_min`, not the same figure in different units. Null if this model cannot be used for chat."
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "models": [
                    {
                      "id": "gpt-5-nano",
                      "label": "GPT-5 Nano",
                      "provider": "openai",
                      "provider_label": "OpenAI",
                      "is_default": false,
                      "supports_temperature": false,
                      "currency": "USD",
                      "rate_per_min": 0.001,
                      "chat_price_per_reply": 0.001
                    },
                    {
                      "id": "sarvam-105b-conversations",
                      "label": "Sarvam-105B",
                      "provider": "sarvam",
                      "provider_label": "Sarvam AI",
                      "is_default": false,
                      "supports_temperature": true,
                      "currency": "USD",
                      "rate_per_min": 0.002,
                      "chat_price_per_reply": 0.002
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/variable-suggestions": {
      "get": {
        "tags": [
          "api-tools"
        ],
        "summary": "List Agent Variable Suggestions",
        "description": "Every `{{token}}` this agent can reference, for one position.\n\nWhat is available differs by position: a prompt can arm a tool and read any tool's output,\na pre-call request can read the call's own details, and an on-call request can read what\npre-call produced. Asking for the wrong list is how a token silently renders as itself.",
        "operationId": "list_agent_variable_suggestions_v1_agents__agent_id__variable_suggestions_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "phase",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "description": "Which position the token will be used in. `prompt` \u2014 the system prompt or a greeting, which is the list a prompt editor wants. `pre_call` \u2014 inside the request body of a tool that runs before the call connects. `on_call` \u2014 inside the request body of a tool the agent calls mid-conversation. Tools themselves are built in the dashboard; these two lists say what their requests may reference.",
              "title": "Phase"
            },
            "description": "Which position the token will be used in. `prompt` \u2014 the system prompt or a greeting, which is the list a prompt editor wants. `pre_call` \u2014 inside the request body of a tool that runs before the call connects. `on_call` \u2014 inside the request body of a tool the agent calls mid-conversation. Tools themselves are built in the dashboard; these two lists say what their requests may reference."
          },
          {
            "name": "version_id",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Agent version; defaults to the newest one.",
              "title": "Version Id"
            },
            "description": "Agent version; defaults to the newest one."
          }
        ],
        "responses": {
          "200": {
            "description": "Every token that resolves in the place you asked about.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "value": {
                        "type": "string",
                        "description": "The token to paste, exactly as it must appear."
                      },
                      "category": {
                        "type": "string",
                        "description": "What kind of token it is, for grouping a picker: `custom`, `call`, `agent`, `pre`, `api`, or `activate` for an `<tool_name>` row."
                      }
                    }
                  }
                },
                "example": [
                  {
                    "value": "{{callee_name}}",
                    "category": "custom"
                  },
                  {
                    "value": "{{callee_number}}",
                    "category": "custom"
                  }
                ]
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/custom-analysis": {
      "get": {
        "tags": [
          "custom-analysis"
        ],
        "summary": "Get Custom Analysis Library",
        "description": "Every analysis group in this workspace, with the values inside it, **cursor-paginated**.\n\nIn creation order \u2014 oldest first \u2014 which is what `sort_order` leaving the public contract\nleft behind. The envelope is `data`, like every other list; it was `{\"groups\": [\u2026]}` for one\nrelease and `{\"categories\": [\u2026]}` before that.",
        "operationId": "get_custom_analysis_library_v1_custom_analysis_get",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page",
              "title": "Cursor"
            },
            "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum records to return in one page."
          }
        ],
        "responses": {
          "200": {
            "description": "The workspace's analysis library, in creation order. Groups are workspace-level \u2014 an agent stores only the selection, in `analysis_group_ids`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string",
                            "nullable": true
                          },
                          "model": {
                            "type": "string",
                            "nullable": true
                          },
                          "temperature": {
                            "type": "number",
                            "nullable": true
                          },
                          "max_tokens": {
                            "type": "integer",
                            "nullable": true
                          },
                          "conditions": {
                            "type": "object"
                          },
                          "is_default": {
                            "type": "boolean"
                          },
                          "items": {
                            "type": "array",
                            "items": {
                              "type": "object",
                              "properties": {
                                "id": {
                                  "type": "string"
                                },
                                "category_id": {
                                  "type": "string"
                                },
                                "name": {
                                  "type": "string"
                                },
                                "description": {
                                  "type": "string"
                                },
                                "result_format": {
                                  "type": "string",
                                  "enum": [
                                    "string",
                                    "number",
                                    "integer",
                                    "boolean",
                                    "array",
                                    "object"
                                  ]
                                },
                                "extraction_method": {
                                  "type": "string",
                                  "enum": [
                                    "ai",
                                    "regex"
                                  ]
                                },
                                "required": {
                                  "type": "boolean"
                                },
                                "constraints": {
                                  "type": "object"
                                },
                                "fields": {
                                  "type": "array",
                                  "items": {
                                    "type": "object"
                                  }
                                },
                                "enabled": {
                                  "type": "boolean"
                                },
                                "is_system": {
                                  "type": "boolean"
                                },
                                "created_at": {
                                  "type": "string",
                                  "format": "date-time"
                                },
                                "updated_at": {
                                  "type": "string",
                                  "format": "date-time"
                                }
                              }
                            }
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      },
                      "description": "The rows on this page."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page exists. `false` on the last."
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pass back as `?cursor=` for the next page; `null` on the last one. **Opaque** \u2014 do not parse or construct one. A cursor from a differently sorted list is refused with `invalid_cursor` rather than silently returning page 1."
                    }
                  },
                  "required": [
                    "data",
                    "has_more"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "name": "Default Analysis",
                      "description": "Vocily's built-in post-call analysis. Attached to every new agent; detach it from an agent that does not need it. You can reword any extraction description, switch a value off, or add your own values to this group.",
                      "model": null,
                      "temperature": null,
                      "max_tokens": null,
                      "conditions": {
                        "min_messages": 4
                      },
                      "id": "00000007-0000-4000-8000-000000000007",
                      "items": [
                        {
                          "name": "Call Summary",
                          "description": "Write a short recap of this conversation in English \u2014 one to three sentences \u2014 even when the conversation happened in Hindi, Hinglish, or any other language. Cover what the caller wanted, what the agent did about it, and how the call ended. Report only what was actually said; do not speculate about intent that was never expressed.",
                          "extraction_method": "ai",
                          "result_format": "string",
                          "required": false,
                          "constraints": {},
                          "fields": [],
                          "enabled": true,
                          "id": "0000000c-0000-4000-8000-00000000000c",
                          "category_id": "00000007-0000-4000-8000-000000000007",
                          "is_system": true,
                          "created_at": "2026-09-01T19:50:05.876753Z",
                          "updated_at": "2026-09-01T19:50:05.876753Z"
                        },
                        {
                          "name": "User Sentiment",
                          "description": "Score the caller's overall sentiment across the whole conversation \u2014 the caller's, never the agent's.\n- positive: the caller was satisfied, agreed, thanked the agent, showed interest, or got what they called for.\n- negative: the caller was frustrated, annoyed, complained, disputed something, repeatedly refused, or hung up unhappy.\n- neutral: the caller was matter-of-fact, or the exchange was purely informational, or positive and negative moments roughly balanced out.\nWhen the caller's tone shifted during the call, judge by where they ended up. When there is genuinely too little to go on, answer neutral.",
                          "extraction_method": "ai",
                          "result_format": "string",
                          "required": false,
                          "constraints": {
                            "enum": [
                              "positive",
                              "neutral"
                            ]
                          },
                          "fields": [],
                          "enabled": true,
                          "id": "0000000d-0000-4000-8000-00000000000d",
                          "category_id": "00000007-0000-4000-8000-000000000007",
                          "is_system": true,
                          "created_at": "2026-09-01T19:50:05.876753Z",
                          "updated_at": "2026-09-01T19:50:05.876753Z"
                        }
                      ],
                      "is_default": true,
                      "created_at": "2026-09-01T19:50:05.876753Z",
                      "updated_at": "2026-09-01T19:50:05.876753Z"
                    },
                    {
                      "name": "dafa",
                      "description": "asdasd",
                      "model": null,
                      "temperature": null,
                      "max_tokens": null,
                      "conditions": {},
                      "id": "0000000e-0000-4000-8000-00000000000e",
                      "items": [],
                      "is_default": false,
                      "created_at": "2026-09-05T20:41:06.966532Z",
                      "updated_at": "2026-09-05T20:41:06.966532Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/custom-analysis/items": {
      "post": {
        "tags": [
          "custom-analysis"
        ],
        "summary": "Create Custom Analysis Item",
        "description": "Add a value to a group. Its `description` is the instruction the model reads.",
        "operationId": "create_custom_analysis_item_v1_custom_analysis_items_post",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicAnalysisItemCreate"
              },
              "example": {
                "category_id": "1f7a2c3e-9b40-4d2a-8c11-5e6f7a8b9c0d",
                "name": "Lead Temperature",
                "description": "How ready the caller is to buy, from what they said.",
                "result_format": "string",
                "constraints": {
                  "enum": [
                    "hot",
                    "warm",
                    "cold"
                  ]
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created item.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "category_id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "result_format": {
                      "type": "string",
                      "enum": [
                        "string",
                        "number",
                        "integer",
                        "boolean",
                        "array",
                        "object"
                      ]
                    },
                    "extraction_method": {
                      "type": "string",
                      "enum": [
                        "ai",
                        "regex"
                      ]
                    },
                    "required": {
                      "type": "boolean"
                    },
                    "constraints": {
                      "type": "object"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "is_system": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "name": "Lead Temperature",
                  "description": "How ready the caller is to buy.",
                  "extraction_method": "ai",
                  "result_format": "string",
                  "required": false,
                  "constraints": {
                    "enum": [
                      "hot",
                      "warm"
                    ]
                  },
                  "fields": [],
                  "enabled": true,
                  "id": "00000010-0000-4000-8000-000000000010",
                  "category_id": "0000000f-0000-4000-8000-00000000000f",
                  "is_system": false,
                  "created_at": "2026-09-16T19:38:04.238748Z",
                  "updated_at": "2026-09-16T19:38:04.238748Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/custom-analysis/items/{item_id}": {
      "put": {
        "tags": [
          "custom-analysis"
        ],
        "summary": "Update Custom Analysis Item",
        "description": "Change a value. Send only the fields you are changing.",
        "operationId": "update_custom_analysis_item_v1_custom_analysis_items__item_id__put",
        "parameters": [
          {
            "name": "item_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Item Id"
            },
            "description": "The analysis item's id, from `GET /v1/custom-analysis`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicAnalysisItemUpdate"
              },
              "example": {
                "description": "How ready the caller is to buy. Ignore polite interest."
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated item.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "category_id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string"
                    },
                    "result_format": {
                      "type": "string",
                      "enum": [
                        "string",
                        "number",
                        "integer",
                        "boolean",
                        "array",
                        "object"
                      ]
                    },
                    "extraction_method": {
                      "type": "string",
                      "enum": [
                        "ai",
                        "regex"
                      ]
                    },
                    "required": {
                      "type": "boolean"
                    },
                    "constraints": {
                      "type": "object"
                    },
                    "fields": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "is_system": {
                      "type": "boolean"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "name": "Lead Temperature",
                  "description": "How ready the caller is to buy, judged from what they said \u2014 not from tone.",
                  "extraction_method": "ai",
                  "result_format": "string",
                  "required": false,
                  "constraints": {
                    "enum": [
                      "hot",
                      "warm"
                    ]
                  },
                  "fields": [],
                  "enabled": true,
                  "id": "00000010-0000-4000-8000-000000000010",
                  "category_id": "0000000f-0000-4000-8000-00000000000f",
                  "is_system": false,
                  "created_at": "2026-09-16T19:38:04.238748Z",
                  "updated_at": "2026-09-16T19:38:04.251020Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "delete": {
        "tags": [
          "custom-analysis"
        ],
        "summary": "Delete Custom Analysis Item",
        "description": "Delete a value. Vocily's built-in values cannot be deleted \u2014 switch them off instead.",
        "operationId": "delete_custom_analysis_item_v1_custom_analysis_items__item_id__delete",
        "parameters": [
          {
            "name": "item_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Item Id"
            },
            "description": "The analysis item's id, from `GET /v1/custom-analysis`."
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/memory/subjects": {
      "get": {
        "tags": [
          "agent-memory"
        ],
        "summary": "List Subjects",
        "description": "Callers this agent remembers, most recently seen first, **cursor-paginated**.\n\nFilter by the date they were last updated. `?offset=` is gone: memory is written by live\ncalls, so a caller's position moves while you page and an offset repeats or skips rows.",
        "operationId": "list_subjects_v1_agents__agent_id__memory_subjects_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "last_updated_on",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "ISO date - callers updated that day",
              "title": "Last Updated On"
            },
            "description": "ISO date - callers updated that day"
          },
          {
            "name": "last_updated_from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "ISO date - range start, inclusive",
              "title": "Last Updated From"
            },
            "description": "ISO date - range start, inclusive"
          },
          {
            "name": "last_updated_to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "ISO date - range end, inclusive",
              "title": "Last Updated To"
            },
            "description": "ISO date - range end, inclusive"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Match any part of the number",
              "title": "Search"
            },
            "description": "Match any part of the number"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 500,
              "default": 100,
              "title": "Limit"
            },
            "description": "Maximum records to return in one page."
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page",
              "title": "Cursor"
            },
            "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page"
          }
        ],
        "responses": {
          "200": {
            "description": "The callers this agent remembers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "msisdn_full": {
                            "type": "string"
                          },
                          "display_name": {
                            "type": "string",
                            "nullable": true
                          },
                          "fact_count": {
                            "type": "integer"
                          },
                          "interaction_count": {
                            "type": "integer"
                          },
                          "last_channel": {
                            "type": "string",
                            "nullable": true
                          },
                          "last_seen_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "first_seen_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      },
                      "description": "The rows on this page."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page exists. `false` on the last."
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pass back as `?cursor=` for the next page; `null` on the last one. **Opaque** \u2014 do not parse or construct one. A cursor from a differently sorted list is refused with `invalid_cursor` rather than silently returning page 1."
                    }
                  },
                  "required": [
                    "data",
                    "has_more"
                  ]
                },
                "example": {
                  "data": [],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/memory/export": {
      "get": {
        "tags": [
          "agent-memory"
        ],
        "summary": "Export Memory",
        "description": "Everything this agent remembers, as a CSV \u2014 one row per caller.\n\nHonours the same date/search filter as the list, so an export matches what you were\nlooking at. Not paginated: the point of an export is to get all of it.",
        "operationId": "export_memory_v1_agents__agent_id__memory_export_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "last_updated_on",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "ISO date - callers updated that day",
              "title": "Last Updated On"
            },
            "description": "ISO date - callers updated that day"
          },
          {
            "name": "last_updated_from",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "ISO date - range start, inclusive",
              "title": "Last Updated From"
            },
            "description": "ISO date - range start, inclusive"
          },
          {
            "name": "last_updated_to",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "ISO date - range end, inclusive",
              "title": "Last Updated To"
            },
            "description": "ISO date - range end, inclusive"
          },
          {
            "name": "search",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "title": "Search"
            },
            "description": "Free-text filter on the record's name."
          }
        ],
        "responses": {
          "200": {
            "description": "Everything this agent remembers, as CSV \u2014 ONE ROW PER FACT. Not paginated: the point of an export is to get all of it.",
            "content": {
              "text/csv": {
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/memory/subjects/{subject_id}": {
      "get": {
        "tags": [
          "agent-memory"
        ],
        "summary": "Get Subject",
        "description": "One caller's whole notebook \u2014 their facts, summary and recent turns.",
        "operationId": "get_subject_v1_agents__agent_id__memory_subjects__subject_id__get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "subject_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Subject Id"
            },
            "description": "The remembered person's id, from `GET \u2026/memory/subjects`."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemorySubjectDetail"
                },
                "example": {
                  "id": "00000004-0000-4000-8000-000000000004",
                  "msisdn_full": "+919876543210",
                  "display_name": "Rahul",
                  "fact_count": 3,
                  "interaction_count": 2,
                  "last_channel": "phone",
                  "last_seen_at": "2026-09-16T17:41:09Z",
                  "first_seen_at": "2026-08-30T11:02:55Z",
                  "summary": "Returning customer. Prefers WhatsApp. Last called about a delayed order.",
                  "transcript": [
                    {
                      "role": "user",
                      "content": "it still has not arrived"
                    },
                    {
                      "role": "assistant",
                      "content": "I have raised it with the courier."
                    }
                  ],
                  "facts": [
                    {
                      "id": "00000005-0000-4000-8000-000000000005",
                      "category": "identity",
                      "key": "callee_name",
                      "value": "Rahul",
                      "source": "extracted",
                      "source_channel": "phone",
                      "valid_from": "2026-08-30T11:04:12Z",
                      "expires_at": null
                    },
                    {
                      "id": "00000006-0000-4000-8000-000000000006",
                      "category": "preference",
                      "key": "preferred_channel",
                      "value": "whatsapp",
                      "source": "extracted",
                      "source_channel": "phone",
                      "valid_from": "2026-09-16T17:40:02Z",
                      "expires_at": null
                    }
                  ]
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/memory/facts/{fact_id}": {
      "delete": {
        "tags": [
          "agent-memory"
        ],
        "summary": "Delete One Fact",
        "description": "Erase a single fact. Takes effect immediately \u2014 no publish needed.",
        "operationId": "delete_one_fact_v1_agents__agent_id__memory_facts__fact_id__delete",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "fact_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Fact Id"
            },
            "description": "The fact's id, as a subject read lists it."
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/memory/flush": {
      "post": {
        "tags": [
          "agent-memory"
        ],
        "summary": "Flush",
        "description": "Delete whole notebooks matching the filter. Previews unless `dry_run` is false.",
        "operationId": "flush_v1_agents__agent_id__memory_flush_post",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicMemoryFlushRequest"
              },
              "example": {
                "last_updated_from": "2026-08-01",
                "last_updated_to": "2026-08-31",
                "dry_run": true
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MemoryFlushResult"
                },
                "example": {
                  "dry_run": true,
                  "subjects": 0,
                  "facts": 0,
                  "transcript_turns": 0
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/knowledge-bases": {
      "post": {
        "tags": [
          "knowledge-bases"
        ],
        "summary": "Create Kb",
        "description": "Create an empty knowledge base, then add documents to it.",
        "operationId": "create_kb_v1_knowledge_bases_post",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicKBCreate"
              },
              "example": {
                "name": "Support policies",
                "description": "Refunds, delivery windows and escalation rules."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created knowledge base.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicKnowledgeBaseRead"
                },
                "example": {
                  "id": "00000013-0000-4000-8000-000000000013",
                  "name": "Product FAQ",
                  "description": "Pricing pages and the returns policy, kept in sync with the website.",
                  "language": "english",
                  "kb_type": "non_deterministic",
                  "document_count": 0,
                  "created_at": "2026-09-16T19:38:04.356892+00:00",
                  "updated_at": "2026-09-16T19:38:04.356892+00:00"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "get": {
        "tags": [
          "knowledge-bases"
        ],
        "summary": "List Kbs",
        "description": "Every knowledge base in this workspace, newest first, **cursor-paginated**.\n\n`documents` is `null` here \u2014 read one by id for its documents.",
        "operationId": "list_kbs_v1_knowledge_bases_get",
        "parameters": [
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "schema": {
              "anyOf": [
                {
                  "type": "string"
                },
                {
                  "type": "null"
                }
              ],
              "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page",
              "title": "Cursor"
            },
            "description": "Opaque cursor from a previous response's `next_cursor`; omit for the first page"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "schema": {
              "type": "integer",
              "maximum": 100,
              "minimum": 1,
              "default": 20,
              "title": "Limit"
            },
            "description": "Maximum records to return in one page."
          }
        ],
        "responses": {
          "200": {
            "description": "This workspace's knowledge bases.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PublicKnowledgeBaseRead"
                      },
                      "description": "The rows on this page."
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "Whether another page exists. `false` on the last."
                    },
                    "next_cursor": {
                      "type": "string",
                      "nullable": true,
                      "description": "Pass back as `?cursor=` for the next page; `null` on the last one. **Opaque** \u2014 do not parse or construct one. A cursor from a differently sorted list is refused with `invalid_cursor` rather than silently returning page 1."
                    }
                  },
                  "required": [
                    "data",
                    "has_more"
                  ]
                },
                "example": {
                  "data": [
                    {
                      "id": "00000013-0000-4000-8000-000000000013",
                      "name": "Product FAQ",
                      "description": "Pricing pages and the returns policy, kept in sync with the website.",
                      "language": "english",
                      "kb_type": "non_deterministic",
                      "document_count": 0,
                      "created_at": "2026-09-16T19:38:04.356892+00:00",
                      "updated_at": "2026-09-16T19:38:04.356892+00:00"
                    },
                    {
                      "id": "00000014-0000-4000-8000-000000000014",
                      "name": "x",
                      "description": null,
                      "language": "english",
                      "kb_type": "non_deterministic",
                      "document_count": 0,
                      "created_at": "2026-09-15T20:53:07.793793+00:00",
                      "updated_at": "2026-09-15T20:53:07.793793+00:00"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/knowledge-bases/{kb_id}": {
      "get": {
        "tags": [
          "knowledge-bases"
        ],
        "summary": "Get Kb",
        "description": "One knowledge base, with its documents and their ingestion status.",
        "operationId": "get_kb_v1_knowledge_bases__kb_id__get",
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Kb Id"
            },
            "description": "The knowledge base's id, from `POST`/`GET /v1/knowledge-bases`."
          }
        ],
        "responses": {
          "200": {
            "description": "The knowledge base, including its documents.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicKnowledgeBaseRead"
                },
                "example": {
                  "id": "00000013-0000-4000-8000-000000000013",
                  "name": "Product FAQ",
                  "description": "Pricing pages and the returns policy, kept in sync with the website.",
                  "language": "english",
                  "kb_type": "non_deterministic",
                  "document_count": 0,
                  "created_at": "2026-09-16T19:38:04.356892+00:00",
                  "updated_at": "2026-09-16T19:38:04.356892+00:00",
                  "documents": []
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge base not found in this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Knowledge base not found in this workspace.",
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "patch": {
        "tags": [
          "knowledge-bases"
        ],
        "summary": "Update Kb",
        "description": "Rename a knowledge base or change how it answers.",
        "operationId": "update_kb_v1_knowledge_bases__kb_id__patch",
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Kb Id"
            },
            "description": "The knowledge base's id, from `POST`/`GET /v1/knowledge-bases`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicKBUpdate"
              },
              "example": {
                "name": "Support policies (2026)"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated knowledge base.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicKnowledgeBaseRead"
                },
                "example": {
                  "id": "00000013-0000-4000-8000-000000000013",
                  "name": "Product FAQ (2026)",
                  "description": "Pricing pages and the returns policy, kept in sync with the website.",
                  "language": "english",
                  "kb_type": "non_deterministic",
                  "document_count": 0,
                  "created_at": "2026-09-16T19:38:04.356892+00:00",
                  "updated_at": "2026-09-16T19:38:04.384922+00:00"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge base not found in this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Knowledge base not found in this workspace.",
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "delete": {
        "tags": [
          "knowledge-bases"
        ],
        "summary": "Delete Kb",
        "description": "Delete a knowledge base and everything in it.",
        "operationId": "delete_kb_v1_knowledge_bases__kb_id__delete",
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Kb Id"
            },
            "description": "The knowledge base's id, from `POST`/`GET /v1/knowledge-bases`."
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge base not found in this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Knowledge base not found in this workspace.",
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/knowledge-bases/{kb_id}/documents": {
      "post": {
        "tags": [
          "knowledge-bases"
        ],
        "summary": "Add Document",
        "description": "Add content to a knowledge base.\n\nReturns `202` immediately \u2014 **ingestion is asynchronous**. Poll `GET /v1/knowledge-bases/{id}`\nuntil the document's `status` reports success; it is not searchable before then.",
        "operationId": "add_document_v1_knowledge_bases__kb_id__documents_post",
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Kb Id"
            },
            "description": "The knowledge base's id, from `POST`/`GET /v1/knowledge-bases`."
          }
        ],
        "requestBody": {
          "content": {
            "multipart/form-data": {
              "schema": {
                "$ref": "#/components/schemas/Body_add_document_v1_knowledge_bases__kb_id__documents_post"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Accepted \u2014 the document is queued for processing. Poll the knowledge base until its `status` reads `processed`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicKnowledgeBaseDocumentRead"
                },
                "example": {
                  "id": "00000001-0000-4000-8000-000000000001",
                  "file_name": "refund-policy-2026.pdf",
                  "source_url": null,
                  "mime_type": "application/pdf",
                  "status": "processing",
                  "error_message": null,
                  "created_at": "2026-09-17T09:14:02Z",
                  "updated_at": "2026-09-17T09:14:02Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "400": {
            "description": "Provide either a file or a `source_url` \u2014 not both, and not neither.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Provide either a file or a `source_url` \u2014 not both, and not neither.",
                  "code": "BAD_REQUEST"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge base not found in this workspace.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Knowledge base not found in this workspace.",
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/knowledge-bases/{kb_id}/documents/{doc_id}": {
      "delete": {
        "tags": [
          "knowledge-bases"
        ],
        "summary": "Delete Document",
        "description": "Remove one document from a knowledge base.",
        "operationId": "delete_document_v1_knowledge_bases__kb_id__documents__doc_id__delete",
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Kb Id"
            },
            "description": "The knowledge base's id, from `POST`/`GET /v1/knowledge-bases`."
          },
          {
            "name": "doc_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Doc Id"
            },
            "description": "The document's id, as the knowledge base read lists it."
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge base or document not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Knowledge base or document not found.",
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/knowledge-bases/{kb_id}/documents/{doc_id}/reindex": {
      "post": {
        "tags": [
          "knowledge-bases"
        ],
        "summary": "Reindex Document",
        "description": "Run a stored document through ingestion again \u2014 after a failure, or to pick up a\nchanged page at `source_url`.",
        "operationId": "reindex_document_v1_knowledge_bases__kb_id__documents__doc_id__reindex_post",
        "parameters": [
          {
            "name": "kb_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Kb Id"
            },
            "description": "The knowledge base's id, from `POST`/`GET /v1/knowledge-bases`."
          },
          {
            "name": "doc_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Doc Id"
            },
            "description": "The document's id, as the knowledge base read lists it."
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted \u2014 the document is queued for reprocessing.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PublicKnowledgeBaseDocumentRead"
                },
                "example": {
                  "id": "00000001-0000-4000-8000-000000000001",
                  "file_name": "refund-policy-2026.pdf",
                  "source_url": null,
                  "mime_type": "application/pdf",
                  "status": "processing",
                  "error_message": null,
                  "created_at": "2026-09-17T09:14:02Z",
                  "updated_at": "2026-09-17T11:02:40Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "404": {
            "description": "Knowledge base or document not found.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Knowledge base or document not found.",
                  "code": "NOT_FOUND"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/memory/calls/{call_id}": {
      "get": {
        "tags": [
          "agent-memory"
        ],
        "summary": "Memory For Call",
        "description": "What one call put into memory and took out of it.",
        "operationId": "memory_for_call_v1_agents__agent_id__memory_calls__call_id__get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          },
          {
            "name": "call_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Call Id"
            },
            "description": "The call whose contribution to memory you want."
          }
        ],
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/MemoryChangeRead"
                  },
                  "title": "Response Memory For Call V1 Agents  Agent Id  Memory Calls  Call Id  Get"
                },
                "example": [
                  {
                    "id": "00000007-0000-4000-8000-000000000007",
                    "source_kind": "call",
                    "context_injected": {
                      "summary": "Returning customer. Prefers WhatsApp.",
                      "facts": {
                        "callee_name": "Rahul"
                      }
                    },
                    "changes_applied": [
                      {
                        "key": "preferred_channel",
                        "from": null,
                        "to": "whatsapp",
                        "action": "added"
                      }
                    ],
                    "created_at": "2026-09-16T17:41:20Z"
                  }
                ]
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/widget": {
      "get": {
        "tags": [
          "widgets"
        ],
        "summary": "Get Agent Widget",
        "description": "The agent's widget.\n\nAn agent holds exactly one, prepared on first read \u2014 so this never 404s and never comes back\nempty. It carries `public_key_prefix`, not the key: the secret is shown once, at rotation.",
        "operationId": "get_agent_widget_v1_agents__agent_id__widget_get",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          }
        ],
        "responses": {
          "200": {
            "description": "The agent's widget. One is prepared on first read, so this never 404s.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "agent_id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "allowed_origins": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "enabled_modes": {
                      "type": "object",
                      "properties": {
                        "chat": {
                          "type": "boolean"
                        },
                        "talk": {
                          "type": "boolean"
                        }
                      }
                    },
                    "theme": {
                      "type": "object"
                    },
                    "default_variables": {
                      "type": "object"
                    },
                    "public_key_prefix": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "name": "Website widget",
                  "allowed_origins": [],
                  "enabled_modes": {
                    "chat": true,
                    "talk": false
                  },
                  "theme": {
                    "title": "Acme Support",
                    "subtitle": "Ask anything or start a web call",
                    "welcome_message": "Hi! How can I help you today?",
                    "logo_url": null,
                    "accent_color": "#7C83FF",
                    "launcher_text_color": "#FFFFFF",
                    "user_message_color": "#7C83FF",
                    "user_message_text_color": "#FFFFFF",
                    "assistant_message_color": "#17171D",
                    "assistant_message_text_color": "#E5E7EB",
                    "position": "bottom-right",
                    "launcher_label": "Chat",
                    "button_shape": "rounded",
                    "panel_radius": 24,
                    "message_radius": 16,
                    "launcher_radius": 999,
                    "icon_radius": 999,
                    "dock_icon_size": 26,
                    "launcher_padding_x": 18,
                    "launcher_padding_y": 13,
                    "widget_width": 380,
                    "widget_height": 620,
                    "show_inbound_number": true
                  },
                  "default_variables": {},
                  "id": "00000011-0000-4000-8000-000000000011",
                  "agent_id": "00000005-0000-4000-8000-000000000005",
                  "public_key_prefix": "pk_widget_live_EXA",
                  "status": "active",
                  "created_at": "2026-09-16T19:38:04.301686Z",
                  "updated_at": "2026-09-16T19:38:04.301686Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "patch": {
        "tags": [
          "widgets"
        ],
        "summary": "Update Agent Widget",
        "description": "Change the widget. Send only the fields you are changing.",
        "operationId": "update_agent_widget_v1_agents__agent_id__widget_patch",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicWidgetUpdate"
              },
              "example": {
                "allowed_origins": [
                  "https://acme.example"
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated widget.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "agent_id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "allowed_origins": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "enabled_modes": {
                      "type": "object",
                      "properties": {
                        "chat": {
                          "type": "boolean"
                        },
                        "talk": {
                          "type": "boolean"
                        }
                      }
                    },
                    "theme": {
                      "type": "object"
                    },
                    "default_variables": {
                      "type": "object"
                    },
                    "public_key_prefix": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "name": "Website widget",
                  "allowed_origins": [
                    "https://acme.example"
                  ],
                  "enabled_modes": {
                    "chat": true,
                    "talk": true
                  },
                  "theme": {
                    "title": "Acme Support",
                    "subtitle": "Ask anything or start a web call",
                    "welcome_message": "Hi! How can I help you today?",
                    "logo_url": null,
                    "accent_color": "#7C83FF",
                    "launcher_text_color": "#FFFFFF",
                    "user_message_color": "#7C83FF",
                    "user_message_text_color": "#FFFFFF",
                    "assistant_message_color": "#17171D",
                    "assistant_message_text_color": "#E5E7EB",
                    "position": "bottom-right",
                    "launcher_label": "Chat",
                    "button_shape": "rounded",
                    "panel_radius": 24,
                    "message_radius": 16,
                    "launcher_radius": 999,
                    "icon_radius": 999,
                    "dock_icon_size": 26,
                    "launcher_padding_x": 18,
                    "launcher_padding_y": 13,
                    "widget_width": 380,
                    "widget_height": 620,
                    "show_inbound_number": true
                  },
                  "default_variables": {},
                  "id": "00000011-0000-4000-8000-000000000011",
                  "agent_id": "00000005-0000-4000-8000-000000000005",
                  "public_key_prefix": "pk_widget_live_EXA",
                  "status": "active",
                  "created_at": "2026-09-16T19:38:04.301686Z",
                  "updated_at": "2026-09-16T19:38:04.312452Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/agents/{agent_id}/widget/rotate-key": {
      "post": {
        "tags": [
          "widgets"
        ],
        "summary": "Rotate Agent Widget Key",
        "description": "Mint a new public key. The old one stops working immediately, so update the snippet on\nyour site before rotating.",
        "operationId": "rotate_agent_widget_key_v1_agents__agent_id__widget_rotate_key_post",
        "parameters": [
          {
            "name": "agent_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Agent Id"
            },
            "description": "The agent's id, as `GET /v1/agents` returns it."
          }
        ],
        "responses": {
          "200": {
            "description": "The new public key, shown once. The old one stops working immediately.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "public_key": {
                      "type": "string"
                    },
                    "public_key_prefix": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "id": "00000011-0000-4000-8000-000000000011",
                  "public_key_prefix": "pk_widget_live_EXA"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/custom-analysis/groups": {
      "post": {
        "tags": [
          "custom-analysis"
        ],
        "summary": "Create Custom Analysis Category",
        "description": "Create a group. Its name becomes part of the key its values arrive under.",
        "operationId": "create_custom_analysis_category_v1_custom_analysis_groups_post",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicAnalysisGroupCreate"
              },
              "example": {
                "name": "Lead QA",
                "description": "Qualification signals from sales calls.",
                "conditions": {
                  "min_messages": 4
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The created group.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string",
                      "nullable": true
                    },
                    "model": {
                      "type": "string",
                      "nullable": true
                    },
                    "temperature": {
                      "type": "number",
                      "nullable": true
                    },
                    "max_tokens": {
                      "type": "integer",
                      "nullable": true
                    },
                    "conditions": {
                      "type": "object"
                    },
                    "is_default": {
                      "type": "boolean"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "category_id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "result_format": {
                            "type": "string",
                            "enum": [
                              "string",
                              "number",
                              "integer",
                              "boolean",
                              "array",
                              "object"
                            ]
                          },
                          "extraction_method": {
                            "type": "string",
                            "enum": [
                              "ai",
                              "regex"
                            ]
                          },
                          "required": {
                            "type": "boolean"
                          },
                          "constraints": {
                            "type": "object"
                          },
                          "fields": {
                            "type": "array",
                            "items": {
                              "type": "object"
                            }
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "is_system": {
                            "type": "boolean"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "name": "Lead quality",
                  "description": "What we ask the model to pull out of every call.",
                  "model": null,
                  "temperature": null,
                  "max_tokens": null,
                  "conditions": {},
                  "id": "0000000f-0000-4000-8000-00000000000f",
                  "items": [],
                  "is_default": false,
                  "created_at": "2026-09-16T19:38:04.226829Z",
                  "updated_at": "2026-09-16T19:38:04.226829Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/custom-analysis/groups/{group_id}": {
      "put": {
        "tags": [
          "custom-analysis"
        ],
        "summary": "Update Custom Analysis Category",
        "description": "Change a group. Renaming changes the key future calls arrive under; past calls keep the\nold name.",
        "operationId": "update_custom_analysis_category_v1_custom_analysis_groups__group_id__put",
        "parameters": [
          {
            "name": "group_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Group Id"
            },
            "description": "The analysis group's id, from `GET /v1/custom-analysis`."
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicAnalysisGroupUpdate"
              },
              "example": {
                "name": "Lead QA (v2)"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated group.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "description": {
                      "type": "string",
                      "nullable": true
                    },
                    "model": {
                      "type": "string",
                      "nullable": true
                    },
                    "temperature": {
                      "type": "number",
                      "nullable": true
                    },
                    "max_tokens": {
                      "type": "integer",
                      "nullable": true
                    },
                    "conditions": {
                      "type": "object"
                    },
                    "is_default": {
                      "type": "boolean"
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "string"
                          },
                          "category_id": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "description": {
                            "type": "string"
                          },
                          "result_format": {
                            "type": "string",
                            "enum": [
                              "string",
                              "number",
                              "integer",
                              "boolean",
                              "array",
                              "object"
                            ]
                          },
                          "extraction_method": {
                            "type": "string",
                            "enum": [
                              "ai",
                              "regex"
                            ]
                          },
                          "required": {
                            "type": "boolean"
                          },
                          "constraints": {
                            "type": "object"
                          },
                          "fields": {
                            "type": "array",
                            "items": {
                              "type": "object"
                            }
                          },
                          "enabled": {
                            "type": "boolean"
                          },
                          "is_system": {
                            "type": "boolean"
                          },
                          "created_at": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "updated_at": {
                            "type": "string",
                            "format": "date-time"
                          }
                        }
                      }
                    },
                    "created_at": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "updated_at": {
                      "type": "string",
                      "format": "date-time"
                    }
                  }
                },
                "example": {
                  "name": "Lead quality (v2)",
                  "description": "What we ask the model to pull out of every call.",
                  "model": null,
                  "temperature": null,
                  "max_tokens": null,
                  "conditions": {},
                  "id": "0000000f-0000-4000-8000-00000000000f",
                  "items": [
                    {
                      "name": "Lead Temperature",
                      "description": "How ready the caller is to buy, judged from what they said \u2014 not from tone.",
                      "extraction_method": "ai",
                      "result_format": "string",
                      "required": false,
                      "constraints": {
                        "enum": [
                          "hot",
                          "warm"
                        ]
                      },
                      "fields": [],
                      "enabled": true,
                      "id": "00000010-0000-4000-8000-000000000010",
                      "category_id": "0000000f-0000-4000-8000-00000000000f",
                      "is_system": false,
                      "created_at": "2026-09-16T19:38:04.238748Z",
                      "updated_at": "2026-09-16T19:38:04.251020Z"
                    }
                  ],
                  "is_default": false,
                  "created_at": "2026-09-16T19:38:04.226829Z",
                  "updated_at": "2026-09-16T19:38:04.260569Z"
                }
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      },
      "delete": {
        "tags": [
          "custom-analysis"
        ],
        "summary": "Delete Custom Analysis Category",
        "description": "Delete a group and its values. Past results keep the names they were stored under.",
        "operationId": "delete_custom_analysis_category_v1_custom_analysis_groups__group_id__delete",
        "parameters": [
          {
            "name": "group_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "title": "Group Id"
            },
            "description": "The analysis group's id, from `GET /v1/custom-analysis`."
          }
        ],
        "responses": {
          "204": {
            "description": "Successful Response"
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/whatsapp/templates": {
      "get": {
        "tags": [
          "catalogues"
        ],
        "summary": "List Whatsapp Templates",
        "description": "Approved template names, for `builtin_tools.send_whatsapp_template.allowed_templates`.\n\nWithout this, that list had to be typed from memory: a name with a typo is stored happily and\nthe agent then simply cannot send, with nothing to compare against.\n\nOnly `APPROVED` templates are returned. A `DRAFT` has never been sent to WhatsApp for review,\nand `PENDING`, `REJECTED` and `PAUSED` all mean the same thing to an agent \u2014 it cannot send\nwith them \u2014 so offering them would invite exactly the silent failure this closes. Templates\nare created and submitted in the dashboard.",
        "operationId": "list_whatsapp_templates_v1_whatsapp_templates_get",
        "parameters": [],
        "responses": {
          "200": {
            "description": "Approved templates you can name in `allowed_templates`.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "name": {
                        "type": "string",
                        "description": "What goes in `builtin_tools.send_whatsapp_template.allowed_templates`."
                      },
                      "language": {
                        "type": "string",
                        "description": "The language this template was approved in, e.g. `en` or `hi`. The same name can be approved in several, which is why a row is a name and a language together."
                      },
                      "category": {
                        "type": "string",
                        "nullable": true,
                        "description": "`MARKETING`, `UTILITY` or `AUTHENTICATION` \u2014 what WhatsApp classified it as, which decides when it may be sent. Null until they have classified it."
                      }
                    }
                  }
                },
                "example": [
                  {
                    "name": "order_shipped",
                    "language": "en",
                    "category": "UTILITY"
                  },
                  {
                    "name": "order_shipped",
                    "language": "hi",
                    "category": "UTILITY"
                  },
                  {
                    "name": "autumn_offer",
                    "language": "en",
                    "category": "MARKETING"
                  }
                ]
              }
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    },
    "/v1/speech": {
      "post": {
        "tags": [
          "speech"
        ],
        "summary": "Synthesize speech",
        "description": "Turn text into audio with any voice from [`GET /v1/voices`](/developers/catalogues/voices), and get the audio back in the response body. Up to 1,000 characters per request.\n\nIt is the same engine your agent speaks with, so it is the way to hear a voice before you put it on one.\n\nNothing is stored. There is no id and no URL to fetch the audio again, so save the bytes if you need them. Each provider ships one model and it is chosen for you.",
        "operationId": "create_speech_v1_speech_post",
        "parameters": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PublicSpeechRequest"
              },
              "example": {
                "text": "Hi, this is Riya calling from Acme about your appointment tomorrow.",
                "provider": "cartesia",
                "voice_id": "f6141af3-5f94-418c-80ed-a45d450e7e2e",
                "language": "en"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The spoken audio \u2014 the response body is the audio file itself.",
            "content": {
              "audio/mpeg": {}
            }
          },
          "422": {
            "description": "Validation Error",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HTTPValidationError"
                }
              }
            }
          },
          "400": {
            "description": "`provider` is not a voice provider; the voice or language was refused by it; or a control was sent to a provider that does not honour it (`speed` is not supported by `elevenlabs`, `emotion` only by `cartesia`). The message names the providers that do.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "`provider` is not a voice provider; the voice or language was refused by it; or a control was sent to a provider that does not honour it (`speed` is not supported by `elevenlabs`, `emotion` only by `cartesia`). The message names the providers that do.",
                  "code": "BAD_REQUEST"
                }
              }
            }
          },
          "502": {
            "description": "The voice provider refused the request or returned no audio.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "The voice provider refused the request or returned no audio."
                }
              }
            }
          },
          "504": {
            "description": "The voice provider did not respond in time.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "The voice provider did not respond in time."
                }
              }
            }
          },
          "401": {
            "description": "Missing or invalid API key.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "detail": "Invalid API key",
                  "code": "UNAUTHORIZED"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded \u2014 honor `Retry-After`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                },
                "example": {
                  "code": "rate_limited"
                }
              }
            }
          }
        },
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "x-mint": {
          "metadata": {
            "playground": "disabled"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Body_add_document_v1_knowledge_bases__kb_id__documents_post": {
        "properties": {
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Url",
            "description": "Fetch the document from this URL instead of uploading bytes. Send this OR `file`, never both and never neither."
          },
          "file": {
            "anyOf": [
              {
                "type": "string",
                "contentMediaType": "application/octet-stream"
              },
              {
                "type": "null"
              }
            ],
            "title": "File",
            "description": "The document itself. Send this OR `source_url`. Read back as `file_name` \u2014 the response names what we stored, not the bytes."
          }
        },
        "type": "object",
        "title": "Body_add_document_v1_knowledge_bases__kb_id__documents_post"
      },
      "BuiltinTools": {
        "additionalProperties": false,
        "properties": {
          "end_call": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/EndCallTool"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Let the agent hang up by itself."
          },
          "hold_call": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/HoldCallTool"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Let it put the caller on hold."
          },
          "transfer_call": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TransferCallTool"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Let it transfer to a human."
          },
          "send_whatsapp_template": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WhatsAppTemplateTool"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Let it send a WhatsApp template mid-call."
          }
        },
        "title": "BuiltinTools",
        "type": "object"
      },
      "CallCreate": {
        "properties": {
          "agent_id": {
            "type": "string",
            "title": "Agent Id",
            "description": "Agent to use for the call"
          },
          "version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Version",
            "description": "Which version of that agent to run, by number \u2014 e.g. `4`, the same number every other version route takes. Omit it and the agent's live version answers."
          },
          "agent_version_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent Version Id",
            "description": "The same choice as `version`, by uuid. Prefer `version`: a number is what you already hold after publishing. Omit both and the agent's live version answers."
          },
          "to_number": {
            "type": "string",
            "title": "To Number",
            "description": "Destination number (E.164)"
          },
          "from_number": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "From Number",
            "description": "Our number (must be in workspace); optional if only one number"
          },
          "variables": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Variables",
            "description": "Prompt variables e.g. {customer_name: 'Rahul'}"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata",
            "description": "Opaque customer JSON, stored + echoed on reads/webhooks"
          }
        },
        "type": "object",
        "required": [
          "agent_id",
          "to_number"
        ],
        "title": "CallCreate",
        "description": "Outbound call request."
      },
      "CallRead": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "The call's id. Use it on `GET /v1/calls/{id}` and to join webhook events to this call."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Where the request got to. The call is placed asynchronously \u2014 `started` means accepted, not answered.",
            "default": "started"
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata",
            "description": "Exactly what you sent as `metadata`, echoed back."
          }
        },
        "type": "object",
        "required": [
          "id"
        ],
        "title": "CallRead",
        "description": "A placed call, acknowledged. The call dials shortly after this returns."
      },
      "CallSettings": {
        "additionalProperties": false,
        "properties": {
          "max_duration_minutes": {
            "anyOf": [
              {
                "maximum": 30,
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Hard cap on call length. The call ends when it is reached.",
            "title": "Max Duration Minutes"
          },
          "end_on_silence_seconds": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "How long the caller may be silent before the call is ended. 5-120 seconds; the silence reminder must land before it.",
            "title": "End On Silence Seconds"
          },
          "recording_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the call is recorded. Recordings are read back through `GET /v1/calls/{id}/recording`, never a raw storage link.",
            "title": "Recording Enabled"
          },
          "custom_analysis_enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the analysis groups in `analysis_group_ids` run after the call. Turning it off stops future runs for this agent and **leaves the groups attached**, so switching it back on needs no re-selection.",
            "title": "Custom Analysis Enabled"
          },
          "end_on_silence_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What it says before ending a call the caller went silent on."
          },
          "max_duration_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What it says as `max_duration_minutes` is reached."
          }
        },
        "title": "CallSettings",
        "type": "object"
      },
      "Conversation": {
        "additionalProperties": false,
        "properties": {
          "interruption_sensitivity": {
            "anyOf": [
              {
                "maximum": 1,
                "minimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "How readily the agent stops talking when the caller speaks. 0 = never yields, 1 = yields at any sound.",
            "title": "Interruption Sensitivity"
          },
          "response_eagerness": {
            "anyOf": [
              {
                "enum": [
                  1,
                  0.75,
                  0.5,
                  0
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "How long the transcriber is given to decide the caller has finished. One of four presets, sent as the number it is stored as: `1` Fast, `0.75` Responsive, `0.5` Balanced (the default), `0` Patient. Any other value is rejected. `GET /v1/transcribers` reports, per speech model, how many seconds each preset typically costs.",
            "title": "Response Eagerness"
          },
          "noise_handling": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/NoiseHandling"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "How aggressively background noise is filtered out."
          },
          "silence_reminder": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SilenceReminder"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "A nudge when the caller goes quiet, before the call is given up on."
          }
        },
        "title": "Conversation",
        "type": "object"
      },
      "CustomAnalysisConditions": {
        "properties": {
          "min_messages": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Messages",
            "description": "Skip the group unless the conversation ran at least this many messages."
          },
          "min_duration_seconds": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Duration Seconds",
            "description": "Skip it unless the call lasted at least this long."
          },
          "ended_reason": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CustomAnalysisEndedReasonCondition"
              },
              {
                "type": "null"
              }
            ],
            "description": "Run it only for calls that ended a particular way."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "CustomAnalysisConditions",
        "description": "Run a category only on the calls it applies to. Leave it empty and the category runs on every call.\n\nThe fields are fixed rather than free-form, so a misspelled condition is a `422` instead of one that silently never matches."
      },
      "CustomAnalysisConstraints": {
        "properties": {
          "enum": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enum",
            "description": "The allowed values. Use this rather than describing a fixed set in prose."
          },
          "min_length": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Min Length",
            "description": "Shortest acceptable string."
          },
          "max_length": {
            "anyOf": [
              {
                "type": "integer",
                "minimum": 1.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Length",
            "description": "Longest acceptable string."
          },
          "format": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Format",
            "description": "A named string format, e.g. `email` or `date`."
          },
          "pattern": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Pattern",
            "description": "A regular expression the value must match. **Required when `extraction_method` is `regex`** \u2014 it is what does the extracting."
          },
          "minimum": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Minimum",
            "description": "Smallest acceptable number, inclusive."
          },
          "maximum": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Maximum",
            "description": "Largest acceptable number, inclusive."
          },
          "exclusive_minimum": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exclusive Minimum",
            "description": "The value must be strictly greater than this."
          },
          "exclusive_maximum": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Exclusive Maximum",
            "description": "The value must be strictly less than this."
          },
          "multiple_of": {
            "anyOf": [
              {
                "type": "number",
                "exclusiveMinimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Multiple Of",
            "description": "The value must be a multiple of this."
          },
          "item_shape": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Item Shape",
            "description": "The shape of each element, for an array value."
          },
          "item_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Item Type",
            "description": "The JSON type of each element, for an array value."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "CustomAnalysisConstraints",
        "description": "Every constraint any format can carry. Which ones are legal depends on the format."
      },
      "CustomAnalysisEndedReasonCondition": {
        "properties": {
          "operator": {
            "type": "string",
            "title": "Operator",
            "description": "`one_of` to run the group only for these outcomes, `not_one_of` to run it for everything except them."
          },
          "values": {
            "items": {
              "type": "string"
            },
            "type": "array",
            "title": "Values",
            "description": "How the call ended \u2014 one or more of `completed`, `voicemail`, `no_answer`, `busy`, `declined`, `failed`, `transfer_completed`, `transfer_failed`. These are the outcomes a *finished* call can hold, which is why the mid-call states are not offered: a condition on one would never match. Anything else is refused."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "operator"
        ],
        "title": "CustomAnalysisEndedReasonCondition"
      },
      "CustomAnalysisFieldSpec": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "description": "The inner field's name."
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "title": "Description",
            "description": "The instruction the model reads for this inner field."
          },
          "type": {
            "type": "string",
            "maxLength": 16,
            "title": "Type",
            "description": "The inner field's JSON type."
          },
          "required": {
            "type": "boolean",
            "title": "Required",
            "description": "Whether it must be produced.",
            "default": false
          },
          "constraints": {
            "$ref": "#/components/schemas/CustomAnalysisConstraints",
            "description": "Limits on the inner field's value."
          }
        },
        "type": "object",
        "required": [
          "name",
          "description",
          "type"
        ],
        "title": "CustomAnalysisFieldSpec",
        "description": "One property of an `object` item, or of each record in an `array` of fields."
      },
      "EndCallTool": {
        "additionalProperties": false,
        "properties": {
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the agent may hang up by itself. Still has to be armed with `<end_call>` in the prompt.",
            "title": "Enabled"
          },
          "message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The goodbye it says before hanging up."
          }
        },
        "title": "EndCallTool",
        "type": "object"
      },
      "Greeting": {
        "additionalProperties": false,
        "description": "The first thing the agent says. May use `{{variables}}`.",
        "properties": {
          "message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The first thing the agent says. Leave empty and the agent waits for the caller to speak first. Spoken aloud, so it is capped at 2000 characters.",
            "title": "Message"
          }
        },
        "title": "Greeting",
        "type": "object"
      },
      "HTTPValidationError": {
        "type": "object",
        "title": "HTTPValidationError",
        "description": "A request the API could not read: a field of the wrong type, out of range, missing, or one we do not accept. Same envelope as every other error.",
        "properties": {
          "detail": {
            "type": "object",
            "description": "What was wrong, as `code`, a one-line `message`, and every offending field in `errors`.",
            "required": [
              "code",
              "message",
              "errors"
            ],
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "validation_error"
                ]
              },
              "message": {
                "type": "string",
                "description": "The first problem in one line, with a count of the rest \u2014 e.g. `model.temperature: Input should be less than or equal to 2 (and 1 more)`."
              },
              "errors": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ValidationError"
                },
                "description": "One entry per offending field. **Every problem is reported at once**, not just the first, so a malformed body needs one round trip to fix rather than one per field."
              }
            }
          },
          "code": {
            "type": "string",
            "enum": [
              "VALIDATION_ERROR"
            ],
            "description": "Derived from the HTTP status, as on every error."
          }
        }
      },
      "HoldCallTool": {
        "additionalProperties": false,
        "properties": {
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the agent may put the caller on hold. Armed with `<hold_call>` in the prompt.",
            "title": "Enabled"
          },
          "max_seconds": {
            "anyOf": [
              {
                "maximum": 600,
                "minimum": 10,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Longest a single hold may last before the agent must come back. The call ends politely if the caller is not back by then.",
            "title": "Max Seconds"
          },
          "follow_up_seconds": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "When the agent checks back in while holding. Must be less than `max_seconds` \u2014 a check-in after the hold has ended is silence \u2014 and the pair is refused if it is not, whichever half you send.",
            "title": "Follow Up Seconds"
          },
          "acknowledgement_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What it says the moment the caller asks for a moment, before it goes quiet."
          },
          "follow_up_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The check-in spoken at `follow_up_seconds`."
          },
          "timeout_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What it says when `max_seconds` runs out and the hold ends."
          }
        },
        "title": "HoldCallTool",
        "type": "object"
      },
      "LanguageConfig": {
        "additionalProperties": false,
        "description": "The language the call starts in, plus the set it may switch into.",
        "properties": {
          "default": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The language the call opens in, e.g. `hi-IN`. The voice must be certified for it or the agent is refused on save.",
            "title": "Default"
          },
          "additional": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Other languages it may switch to mid-call. A language cannot be both the default and an additional one.",
            "title": "Additional"
          },
          "switch_trigger": {
            "anyOf": [
              {
                "enum": [
                  "requested_or_auto",
                  "requested_only"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "`requested_or_auto` also switches when it hears a different language; `requested_only` switches only when asked.",
            "title": "Switch Trigger"
          }
        },
        "title": "LanguageConfig",
        "type": "object"
      },
      "Memory": {
        "additionalProperties": false,
        "description": "What the agent remembers about the people it talks to.\n\nThese SETTINGS are versioned like the prompt. The remembered people are keyed to the\nagent and survive every publish and rollback \u2014 read and erase them through\n`/v1/agents/{id}/memory/*`.",
        "properties": {
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether this agent remembers callers between calls at all.",
            "title": "Enabled"
          },
          "channels": {
            "anyOf": [
              {
                "items": {
                  "enum": [
                    "inbound",
                    "outbound",
                    "whatsapp"
                  ],
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which kinds of conversation contribute to memory.",
            "title": "Channels"
          },
          "allow_ai_labels": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the model may invent its own labels for what it remembers, beyond the fields you defined.",
            "title": "Allow Ai Labels"
          },
          "label_instructions": {
            "anyOf": [
              {
                "maxLength": 500,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Guidance the model reads when inventing labels, if `allow_ai_labels` is on.",
            "title": "Label Instructions"
          },
          "max_facts": {
            "anyOf": [
              {
                "maximum": 1000,
                "minimum": 10,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Most facts kept per person. The oldest are dropped past this.",
            "title": "Max Facts"
          },
          "transcript_turns": {
            "anyOf": [
              {
                "maximum": 30,
                "minimum": 4,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "How many recent turns are considered when deciding what to remember.",
            "title": "Transcript Turns"
          },
          "fields": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/MemoryField"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The specific things to remember, each with its own type and category. Sending this list replaces the whole set, and a `key` declared twice in it is refused. These are the STRUCTURE; the facts themselves are written by the model after a call and read through the memory endpoints.",
            "title": "Fields"
          }
        },
        "title": "Memory",
        "type": "object"
      },
      "MemoryChangeRead": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "This change's id."
          },
          "source_kind": {
            "type": "string",
            "title": "Source Kind",
            "description": "What produced the change. `voice` \u2014 a phone call. `whatsapp` \u2014 a WhatsApp thread. `fold` \u2014 a periodic pass that consolidates what is already known. `fallback` \u2014 a catch-up pass for a conversation whose own run did not complete."
          },
          "context_injected": {
            "additionalProperties": true,
            "type": "object",
            "title": "Context Injected",
            "description": "What memory was put in front of the agent for this call."
          },
          "changes_applied": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "title": "Changes Applied",
            "description": "What the call added or altered, fact by fact."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When it was applied (UTC, ISO 8601)."
          }
        },
        "type": "object",
        "required": [
          "id",
          "source_kind",
          "context_injected",
          "changes_applied",
          "created_at"
        ],
        "title": "MemoryChangeRead",
        "description": "What one call put into memory and took out of it."
      },
      "MemoryFactRead": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "This fact's id. Pass it to `DELETE \u2026/memory/facts/{fact_id}` to erase just this one."
          },
          "category": {
            "type": "string",
            "title": "Category",
            "description": "Which group it belongs to \u2014 identity, contact, preference, account, context."
          },
          "key": {
            "type": "string",
            "title": "Key",
            "description": "Which field it fills, matching a `key` in the agent's `memory.fields`."
          },
          "value": {
            "type": "string",
            "title": "Value",
            "description": "What is remembered."
          },
          "source": {
            "type": "string",
            "title": "Source",
            "description": "How it was learned. `caller_asserted` \u2014 the caller said it, which is all the extractor ever hears. `tool_verified` \u2014 confirmed by a tool against your own system. `operator_set` \u2014 set in the dashboard. Only `tool_verified` and `operator_set` are established fact."
          },
          "source_channel": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Source Channel",
            "description": "Which channel the conversation was on."
          },
          "valid_from": {
            "type": "string",
            "format": "date-time",
            "title": "Valid From",
            "description": "When it was learned (UTC, ISO 8601)."
          },
          "expires_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Expires At",
            "description": "When it stops being used. `null` means it does not expire."
          }
        },
        "type": "object",
        "required": [
          "id",
          "category",
          "key",
          "value",
          "source",
          "source_channel",
          "valid_from",
          "expires_at"
        ],
        "title": "MemoryFactRead",
        "description": "One thing the agent holds about a caller."
      },
      "MemoryField": {
        "additionalProperties": false,
        "description": "One structured thing to remember about a caller. `description` is the extractor's\ninstruction and goes into the prompt verbatim \u2014 it is not a tooltip.",
        "properties": {
          "key": {
            "description": "Machine name for this fact, used when reading memory back.",
            "maxLength": 64,
            "pattern": "^[a-z][a-z0-9_]*$",
            "title": "Key",
            "type": "string"
          },
          "label": {
            "description": "A human-readable name for this field.",
            "maxLength": 120,
            "title": "Label",
            "type": "string"
          },
          "type": {
            "default": "string",
            "description": "The JSON type this fact is stored as.",
            "enum": [
              "string",
              "number",
              "integer",
              "boolean",
              "array"
            ],
            "title": "Type",
            "type": "string"
          },
          "enum_values": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The allowed values, when the fact is one of a fixed set. `string` fields only \u2014 the extractor ignores a list on any other type, so one sent there is refused.",
            "title": "Enum Values"
          },
          "description": {
            "description": "The instruction the model reads when deciding what to record here. A direction, not a label.",
            "title": "Description",
            "type": "string"
          },
          "category": {
            "default": "context",
            "description": "How this field is grouped when the agent's memory is shown.",
            "enum": [
              "identity",
              "contact",
              "preference",
              "account",
              "context"
            ],
            "title": "Category",
            "type": "string"
          }
        },
        "required": [
          "key",
          "label",
          "description"
        ],
        "title": "MemoryField",
        "type": "object"
      },
      "MemoryFlushResult": {
        "properties": {
          "dry_run": {
            "type": "boolean",
            "title": "Dry Run",
            "description": "Whether this was a rehearsal. `true` means nothing was deleted."
          },
          "subjects": {
            "type": "integer",
            "title": "Subjects",
            "description": "How many people were affected."
          },
          "facts": {
            "type": "integer",
            "title": "Facts",
            "description": "How many facts were erased."
          },
          "transcript_turns": {
            "type": "integer",
            "title": "Transcript Turns",
            "description": "How many stored turns were erased."
          }
        },
        "type": "object",
        "required": [
          "dry_run",
          "subjects",
          "facts",
          "transcript_turns"
        ],
        "title": "MemoryFlushResult",
        "description": "What a flush did, or would do."
      },
      "MemorySubjectDetail": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "This person's id, for reading and erasing their memory."
          },
          "msisdn_full": {
            "type": "string",
            "title": "Msisdn Full",
            "description": "Their number, E.164."
          },
          "display_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Display Name",
            "description": "What the agent knows them as, if anything."
          },
          "fact_count": {
            "type": "integer",
            "title": "Fact Count",
            "description": "How many facts are held about them."
          },
          "interaction_count": {
            "type": "integer",
            "title": "Interaction Count",
            "description": "How many conversations they have had with this agent."
          },
          "last_channel": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Channel",
            "description": "How they last got in touch \u2014 `voice` (a phone call) or `whatsapp`. Widget conversations are not recorded in memory, so they never appear here. A **record** of what happened, which is a different question from the agent's `memory.channels` setting, which decides what is *allowed* to feed memory."
          },
          "last_seen_at": {
            "type": "string",
            "format": "date-time",
            "title": "Last Seen At",
            "description": "When they last spoke to it (UTC, ISO 8601)."
          },
          "first_seen_at": {
            "type": "string",
            "format": "date-time",
            "title": "First Seen At",
            "description": "When they first did (UTC, ISO 8601)."
          },
          "summary": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Summary",
            "description": "The agent's running summary of who they are."
          },
          "transcript": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "type": "array",
            "title": "Transcript",
            "description": "Recent turns kept as context for the next conversation."
          },
          "facts": {
            "items": {
              "$ref": "#/components/schemas/MemoryFactRead"
            },
            "type": "array",
            "title": "Facts",
            "description": "Everything the agent remembers about them, fact by fact."
          }
        },
        "type": "object",
        "required": [
          "id",
          "msisdn_full",
          "display_name",
          "fact_count",
          "interaction_count",
          "last_channel",
          "last_seen_at",
          "first_seen_at",
          "summary",
          "transcript",
          "facts"
        ],
        "title": "MemorySubjectDetail",
        "description": "One caller's whole notebook."
      },
      "Model": {
        "additionalProperties": false,
        "description": "The LLM. `GET /v1/models` is the catalogue.",
        "properties": {
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Read-only. Derived from `model` \u2014 the catalogue decides routing, so a value sent here is replaced by the one the catalogue names.",
            "title": "Provider"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Model id, from `GET /v1/models`. Every model that catalogue lists can be used.",
            "title": "Model"
          },
          "temperature": {
            "anyOf": [
              {
                "maximum": 2,
                "minimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Randomness. Lower is more repeatable; higher is more varied.",
            "title": "Temperature"
          },
          "max_tokens": {
            "anyOf": [
              {
                "maximum": 256,
                "minimum": 10,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Cap on the length of a single reply.",
            "title": "Max Tokens"
          },
          "fallback": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/ModelFallback"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Backup model, used for the rest of the call if this one's provider stops responding. Send `{\"model\": \"gemini-3.5-flash-lite\"}` \u2014 the provider is filled in. Must be from a different provider \u2014 one on the main engine's own provider is refused. See [Backups](/developers/agents/backups)."
          }
        },
        "title": "Model",
        "type": "object"
      },
      "NoiseHandling": {
        "additionalProperties": false,
        "description": "`level` is derived from `mode` when omitted (0 / 50 / 75 / 90).",
        "properties": {
          "mode": {
            "anyOf": [
              {
                "enum": [
                  "off",
                  "standard",
                  "high",
                  "background_voice"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "How aggressively to filter background noise. `background_voice` is for a caller with other people talking nearby.",
            "title": "Mode"
          },
          "level": {
            "anyOf": [
              {
                "maximum": 100,
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Filter strength 0-100. Derived from `mode` when omitted: off 0, standard 50, high 75, background_voice 90.",
            "title": "Level"
          }
        },
        "title": "NoiseHandling",
        "type": "object"
      },
      "Numbers": {
        "additionalProperties": false,
        "description": "Where the agent answers, and what it dials out from.\n\n`inbound_phone` and `inbound_whatsapp` are RECORDED on the version and applied when it\nis made live \u2014 a number written here routes nothing until then, which is what lets a\nrollback restore routing along with behaviour.",
        "properties": {
          "inbound_phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The phone number this agent answers on. Must be a number `GET /v1/numbers` lists for your workspace.",
            "title": "Inbound Phone"
          },
          "inbound_whatsapp": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The WhatsApp number it answers on, from `GET /v1/whatsapp/numbers`. Any spelling of it is accepted and read back in E.164, e.g. `+15513745854`. Recorded on this version; it starts answering when the version is made live.",
            "title": "Inbound Whatsapp"
          },
          "default_outbound": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The number outbound calls are placed from when `POST /v1/calls` omits `from_number`.",
            "title": "Default Outbound"
          }
        },
        "title": "Numbers",
        "type": "object"
      },
      "PublicAgentDetail": {
        "additionalProperties": false,
        "description": "One agent at one version \u2014 the response of every agent read, create and update.\n\nA request body is this same object minus the read-only fields, so what you send is what you read back.",
        "properties": {
          "id": {
            "description": "The agent's id. Stable across every version.",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "description": "What the agent is called. Yours to choose; never spoken to a caller.",
            "title": "Name",
            "type": "string"
          },
          "version": {
            "description": "Which version this body describes. 0-based, and the identity you use in `/versions/{n}` and `?version=`.",
            "title": "Version",
            "type": "integer"
          },
          "version_id": {
            "description": "This version's uuid. Pass it as `agent_version_id` on `POST /v1/calls` to pin a call to this exact version \u2014 that field takes a uuid, not a number.",
            "title": "Version Id",
            "type": "string"
          },
          "is_published": {
            "description": "True once frozen. A published version's configuration can never be edited again; branch a draft instead.",
            "title": "Is Published",
            "type": "boolean"
          },
          "is_live": {
            "description": "True if this is the version answering calls right now.",
            "title": "Is Live",
            "type": "boolean"
          },
          "live_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which version is live, if any. `null` means the agent is off air and answers nothing.",
            "title": "Live Version"
          },
          "latest_version": {
            "description": "The highest version number this agent has.",
            "title": "Latest Version",
            "type": "integer"
          },
          "document_revision": {
            "description": "This version's edit counter. Echo it back as `If-Match` on your next write and the write becomes a compare-and-set, so you cannot silently overwrite an edit made between your read and your write.",
            "title": "Document Revision",
            "type": "integer"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Short name for this version, e.g. `Shorter greeting`. Editable even after publishing \u2014 it is metadata, not configuration.",
            "title": "Label"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Longer free text about this version.",
            "title": "Notes"
          },
          "blocked_reasons": {
            "description": "Why this version cannot be made live, if it cannot \u2014 e.g. it pins a model that has since been retired. Empty means it can go live.",
            "items": {
              "type": "string"
            },
            "title": "Blocked Reasons",
            "type": "array"
          },
          "created_at": {
            "description": "When this version was created (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "updated_at": {
            "description": "When this version was last edited (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          },
          "system_prompt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The agent's instructions. Naming a tool as `<tool_name>` here is what ARMS it: a tool the prompt never names is never called, and naming one the version does not have is refused on save.",
            "title": "System Prompt"
          },
          "greeting": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Greeting"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What the agent says first."
          },
          "language": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LanguageConfig"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The language it opens in, which others it may switch to, and what triggers a switch."
          },
          "transcriber": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Transcriber"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Speech recognition. `GET /v1/transcribers` lists valid `model` values."
          },
          "model": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Model"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The LLM. `GET /v1/models` lists valid `model` and `provider` values."
          },
          "voice": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Voice"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Text to speech. `GET /v1/voices` lists valid `voice_id` values, and a voice that cannot speak `language.default` is refused on save."
          },
          "conversation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Conversation"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Turn-taking, interruption and noise handling \u2014 how it behaves in the back-and-forth."
          },
          "call": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CallSettings"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Limits on the call itself: maximum duration, silence timeout, and what ends it."
          },
          "inbound": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Inbound"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Lines for inbound calls that cannot be handled normally."
          },
          "builtin_tools": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BuiltinTools"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The tools Vocily ships: end the call, hold, transfer, send a WhatsApp template. Each still has to be armed from the prompt."
          },
          "variables": {
            "description": "The `{{placeholders}}` the prompt and tools can use. Reference them namespaced as `{{custom.your_key}}`, never bare.",
            "items": {
              "$ref": "#/components/schemas/RuntimeVariable"
            },
            "title": "Variables",
            "type": "array"
          },
          "knowledge_base_ids": {
            "description": "Which knowledge bases this agent can search, from `GET /v1/knowledge-bases`. **This list IS the attachment** \u2014 there is no separate attach endpoint, and sending it replaces the whole set. An id this workspace does not hold is refused, not ignored.",
            "items": {
              "type": "string"
            },
            "title": "Knowledge Base Ids",
            "type": "array"
          },
          "analysis_group_ids": {
            "description": "Which custom-analysis groups run after each call, from `GET /v1/custom-analysis`. Same rule as `knowledge_base_ids`: the list is the attachment, and an id this workspace does not hold is refused, not ignored.",
            "items": {
              "type": "string"
            },
            "title": "Analysis Group Ids",
            "type": "array"
          },
          "memory": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Memory"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the agent remembers callers between calls, and what it is allowed to remember."
          },
          "numbers": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Numbers"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which phone and WhatsApp numbers this agent answers on. `GET /v1/numbers` and `GET /v1/whatsapp/numbers` list what you may use."
          },
          "dashboard_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Deep link to this agent in the Vocily dashboard, for your own UI to link out to.",
            "title": "Dashboard Url"
          }
        },
        "required": [
          "id",
          "name",
          "version",
          "version_id",
          "is_published",
          "is_live",
          "latest_version",
          "document_revision",
          "created_at",
          "updated_at"
        ],
        "title": "PublicAgentDetail",
        "type": "object"
      },
      "PublicCallList": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PublicCallRead"
            },
            "type": "array",
            "title": "Data",
            "description": "The page of calls."
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "Whether another page exists."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor",
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        },
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "PublicCallList",
        "description": "A page of calls. Pass `next_cursor` back as `?cursor=` to fetch the next one; `has_more` is\n`false` on the last page. Cursors rather than an offset, so a call placed while you are paging\ncannot shift rows onto a page you have already read."
      },
      "PublicCallRead": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "The call's id. Use it on `GET /v1/calls/{id}` and to join webhook events to this call."
          },
          "agent_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent Id",
            "description": "Which agent handled it."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Where the call got to. Mid-call: `started` (placed, ringing), `in_progress`, `transferring`, `transfer_answered`. Finished: `completed`, `voicemail`, `no_answer`, `busy`, `declined`, `failed`, `transfer_completed`, `transfer_failed`. **Open set** \u2014 treat it as a string rather than switching exhaustively."
          },
          "direction": {
            "type": "string",
            "title": "Direction",
            "description": "Which way the call went: `inbound`, `outbound`, or `web` for a call that happened in a browser rather than on a phone. For WHO started it, read `origin`."
          },
          "agent_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent Version",
            "description": "Which version of the agent answered. The difference between \"the agent said something wrong\" and \"V4 said something wrong\" after a deploy. `null` when that version has since been deleted."
          },
          "batch_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Batch Id",
            "description": "Which campaign placed it, when `origin` is `batch`; `null` otherwise. The join key for a campaign's calls."
          },
          "origin": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Origin",
            "description": "WHO started it: `widget`, `dashboard`, `api`, `batch`, `inbound`, `demo`. Answers \"is this real traffic or one of my own test clicks?\". **Nullable, and `null` means unknown \u2014 never treat it as a channel**: the column postdates some rows, and a call whose origin was never captured is unattributable forever."
          },
          "from_number": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "From Number",
            "description": "The number dialled from, E.164. `null` for a web call."
          },
          "to_number": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "To Number",
            "description": "The number dialled, E.164. `null` for a web call."
          },
          "duration_seconds": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Duration Seconds",
            "description": "How long the call lasted. `null` until it ends."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the call was placed or received (UTC, ISO 8601)."
          },
          "connected_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Connected At",
            "description": "When it was answered. `null` if it never was."
          },
          "ended_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ended At",
            "description": "When it ended. `null` while it is still running."
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata",
            "description": "Exactly what you sent as `metadata` on `POST /v1/calls`, unchanged. Your id-to-our-id join key."
          },
          "variables": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Variables",
            "description": "The call's own variables \u2014 what you sent as `variables`, or what was resolved for an inbound call. Only the values you can set \u2014 the `custom` namespace."
          },
          "cost": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PublicCost"
              },
              {
                "type": "null"
              }
            ],
            "description": "What the call cost. `null` until it is finalised after the call."
          },
          "custom_analysis": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Analysis",
            "description": "Everything your analysis groups extracted, keyed by group then item: `custom_analysis[\"Lead QA\"][\"Lead Temperature\"]`. Vocily's own summary, sentiment and outcome arrive here too, under `\"Default Analysis\"` \u2014 there is no separate `analysis` object."
          },
          "transcript": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Transcript",
            "description": "The conversation. **Omitted (`null`) on the LIST unless you pass `?include=transcript`**, because it is heavy; always present on get-by-id."
          },
          "transfer": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Transfer",
            "description": "Human-transfer detail \u2014 `state` (`transferring`, `answered`, `failed`), `target`, `reason`. `null` unless a transfer happened."
          },
          "recording_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Recording Url",
            "description": "A stable Vocily URL, never a raw storage link. `null` until the recording is ready. Fetching it (authenticated) redirects to a short-lived download."
          },
          "dashboard_url": {
            "type": "string",
            "title": "Dashboard Url",
            "description": "Deep link to this call in the Vocily dashboard \u2014 paste it into a bug report."
          }
        },
        "type": "object",
        "required": [
          "id",
          "agent_id",
          "status",
          "direction",
          "batch_id",
          "origin",
          "from_number",
          "to_number",
          "duration_seconds",
          "created_at",
          "connected_at",
          "ended_at",
          "metadata",
          "variables",
          "cost",
          "custom_analysis",
          "transcript",
          "transfer",
          "recording_url",
          "dashboard_url"
        ],
        "title": "PublicCallRead",
        "description": "One call: what it was, how it went, and what it cost."
      },
      "PublicChatCost": {
        "properties": {
          "currency": {
            "type": "string",
            "title": "Currency",
            "description": "ISO currency code.",
            "default": "USD"
          },
          "total": {
            "type": "number",
            "title": "Total",
            "description": "What the chat cost, in major units of `currency`."
          },
          "rate_per_reply": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rate Per Reply",
            "description": "The per-reply rate it was billed at, in major units of `currency` per assistant reply at the time of the chat. Text is priced per reply, not per minute."
          }
        },
        "type": "object",
        "required": [
          "total"
        ],
        "title": "PublicChatCost",
        "description": "What a chat cost. Priced per assistant REPLY, which is why this carries no `rate_per_min` \u2014 that is the voice unit and would be wrong here."
      },
      "PublicChatList": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/PublicChatRead"
            },
            "type": "array",
            "title": "Data",
            "description": "The page of chats."
          },
          "has_more": {
            "type": "boolean",
            "title": "Has More",
            "description": "Whether another page exists."
          },
          "next_cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Next Cursor",
            "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
          }
        },
        "type": "object",
        "required": [
          "data",
          "has_more",
          "next_cursor"
        ],
        "title": "PublicChatList",
        "description": "Envelope for `GET /v1/chats`. Same cursor contract as `GET /v1/calls`, so one paging loop reads both."
      },
      "PublicChatRead": {
        "properties": {
          "id": {
            "type": "string",
            "title": "Id",
            "description": "The chat's id."
          },
          "agent_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent Id",
            "description": "Which agent handled it."
          },
          "agent_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent Name",
            "description": "The agent's name as it was at the time \u2014 snapshotted, so a later rename does not rewrite history."
          },
          "agent_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "Agent Version",
            "description": "Which version of the agent answered."
          },
          "status": {
            "type": "string",
            "title": "Status",
            "description": "Where the chat got to \u2014 `started`, `in_progress`, or `completed`. A chat has no failure state: it cannot ring, be declined or reach voicemail. `completed` means **no longer active**, which includes a visitor simply closing the tab."
          },
          "origin": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Origin",
            "description": "`widget` for a real end user on your site, `dashboard` for our own chat test button. `null` means unknown on older rows."
          },
          "turn_count": {
            "type": "integer",
            "title": "Turn Count",
            "description": "Assistant replies in the session. **This is the billing unit for text** \u2014 voice bills on `duration_seconds`, which is always `null` here \u2014 so it is published rather than left for you to count out of the transcript and get a different answer than the invoice."
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "title": "Created At",
            "description": "When the chat started (UTC, ISO 8601)."
          },
          "ended_at": {
            "anyOf": [
              {
                "type": "string",
                "format": "date-time"
              },
              {
                "type": "null"
              }
            ],
            "title": "Ended At",
            "description": "When it ended. `null` while still open."
          },
          "metadata": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Metadata",
            "description": "Your own passthrough, unchanged."
          },
          "variables": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Variables",
            "description": "The chat's own variables. Only your `custom` bag."
          },
          "cost": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PublicChatCost"
              },
              {
                "type": "null"
              }
            ],
            "description": "What the chat cost. Priced per assistant reply, not per minute."
          },
          "custom_analysis": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Custom Analysis",
            "description": "Everything your analysis groups extracted, keyed by group then item."
          },
          "transcript": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Transcript",
            "description": "The conversation. Omitted (`null`) on the LIST unless you pass `?include=transcript`."
          },
          "dashboard_url": {
            "type": "string",
            "title": "Dashboard Url",
            "description": "Deep link to this chat in the Vocily dashboard."
          }
        },
        "type": "object",
        "required": [
          "id",
          "agent_id",
          "agent_name",
          "agent_version",
          "status",
          "origin",
          "turn_count",
          "created_at",
          "ended_at",
          "metadata",
          "variables",
          "cost",
          "custom_analysis",
          "transcript",
          "dashboard_url"
        ],
        "title": "PublicChatRead",
        "description": "One text conversation \u2014 a widget chat or a WhatsApp thread.\n\nSeparate from a call because a chat has no numbers, no duration, no recording and no transfer, and is priced per assistant reply rather than per minute.\n\nRead-only. A chat begins when someone opens your widget or messages your WhatsApp number, so there is no endpoint that starts one."
      },
      "PublicCost": {
        "properties": {
          "currency": {
            "type": "string",
            "title": "Currency",
            "description": "ISO currency code.",
            "default": "USD"
          },
          "total": {
            "type": "number",
            "title": "Total",
            "description": "What the call cost, in major units of `currency`, e.g. 0.0554."
          },
          "rate_per_min": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "title": "Rate Per Min",
            "description": "The per-minute rate it was billed at, in major units of `currency` per minute at the time of the call."
          }
        },
        "type": "object",
        "required": [
          "total"
        ],
        "title": "PublicCost",
        "description": "A call's cost, explicitly currency-labeled: every org is billed in its own currency (USD or\nINR), so a bare number is ambiguous \u2014 this names it. `total` is in major units of `currency`."
      },
      "RuntimeVariable": {
        "additionalProperties": false,
        "description": "A `{{placeholder}}` the prompt and tools can use.\n\nKeys found in the prompt are added automatically on save. `callee_name` and\n`callee_number` are on every agent; `callee_number` cannot be removed, `callee_name` can (a\ncampaign with no names drops it so the batch builder stops asking for one).",
        "properties": {
          "key": {
            "description": "The placeholder name. Reference it in a prompt or tool as `{{custom.key}}`, never bare.",
            "maxLength": 128,
            "pattern": "^[A-Za-z_][A-Za-z0-9_]*$",
            "title": "Key",
            "type": "string"
          },
          "default_value": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What it resolves to when a call does not supply one.",
            "title": "Default Value"
          },
          "system_defined": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "**Read-only.** True for the variables every agent has. The platform sets it, on a new variable as on an existing one; a value that disagrees with what you read is refused. Echoing back the value unchanged is fine.",
            "title": "System Defined"
          },
          "deletable": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "**Read-only.** False for `callee_number`, which is on every agent and cannot be removed \u2014 sending a list without it does not delete it. `callee_name` is system-defined but deletable. The platform sets it; a value that disagrees with what you read is refused.",
            "title": "Deletable"
          }
        },
        "required": [
          "key"
        ],
        "title": "RuntimeVariable",
        "type": "object"
      },
      "SilenceReminder": {
        "additionalProperties": false,
        "description": "`seconds` must be less than `call.end_on_silence_seconds` \u2014 a reminder that fires\nafter the call has already ended is not a reminder.",
        "properties": {
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the agent nudges a silent caller.",
            "title": "Enabled"
          },
          "message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What it says when it nudges. `default` generates the line per call; `custom` says `text` verbatim."
          },
          "seconds": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "How long the caller may be silent before the agent nudges them. 3-119 seconds, and it must be less than `call.end_on_silence_seconds` \u2014 a reminder after the call has ended is nothing.",
            "title": "Seconds"
          }
        },
        "title": "SilenceReminder",
        "type": "object"
      },
      "SystemMessage": {
        "additionalProperties": false,
        "description": "One platform-spoken line.\n\n`default` generates it per call from `prompt`, in the language being spoken; `custom`\nsays `text` verbatim. A `default` entry needs a non-blank `prompt` \u2014 a message with\nnothing steering it means the agent goes quiet for no reason anyone stated.",
        "properties": {
          "mode": {
            "anyOf": [
              {
                "enum": [
                  "default",
                  "custom"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "`default` generates the line per call from `prompt`, in the language being spoken; `custom` says `text` verbatim.",
            "title": "Mode"
          },
          "prompt": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The instruction used to generate the line, for `default` mode. Required and non-blank when `mode` is `default`.",
            "title": "Prompt"
          },
          "text": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The exact words, for `custom` mode.",
            "title": "Text"
          }
        },
        "title": "SystemMessage",
        "type": "object"
      },
      "Transcriber": {
        "additionalProperties": false,
        "description": "Speech recognition. `GET /v1/transcribers` lists what `model` accepts.",
        "properties": {
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Read-only. Derived from `model` \u2014 each speech model belongs to exactly one provider, so a value sent here is replaced by the one the catalogue names.",
            "title": "Provider"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Model id, from `GET /v1/transcribers`. It must cover every language in the agent's set or the agent is refused on save.",
            "title": "Model"
          },
          "keywords": {
            "description": "Words to bias recognition towards \u2014 brand names, product names, anything it mishears. How strongly they apply depends on the speech model: some take them as a recognition boost, and one is told to expect them, which is weaker. Send the same list either way.",
            "items": {
              "type": "string"
            },
            "title": "Keywords",
            "type": "array"
          },
          "fallback": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/TranscriberFallback"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Backup speech model, used for the rest of the call if this one's provider stops responding. Send `{\"model\": \"nova-3-general\"}` \u2014 the provider is filled in. Must be from a different provider \u2014 one on the main engine's own provider is refused. See [Backups](/developers/agents/backups)."
          }
        },
        "title": "Transcriber",
        "type": "object"
      },
      "TransferCallTool": {
        "additionalProperties": false,
        "properties": {
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the agent may transfer the call. Armed with `<transfer_call>` in the prompt.",
            "title": "Enabled"
          },
          "numbers": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/TransferNumber"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Where it may transfer to, in priority order. Sending this list replaces the whole set.",
            "title": "Numbers"
          },
          "intro_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What it says to the caller as it hands the call over."
          },
          "busy_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What it says when no destination is free."
          }
        },
        "title": "TransferCallTool",
        "type": "object"
      },
      "TransferNumber": {
        "additionalProperties": false,
        "description": "A human to hand the call to. `start_hour`/`end_hour` null = always available.",
        "properties": {
          "number": {
            "description": "Destination in E.164, e.g. `+919876543210`.",
            "title": "Number",
            "type": "string"
          },
          "priority": {
            "default": 0,
            "description": "Order to try. Lower is tried first.",
            "title": "Priority",
            "type": "integer"
          },
          "start_hour": {
            "anyOf": [
              {
                "maximum": 23,
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Earliest hour of the day this destination accepts transfers, 0-23 in its own `timezone`.",
            "title": "Start Hour"
          },
          "end_hour": {
            "anyOf": [
              {
                "maximum": 23,
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Latest hour, 0-23 in its own `timezone`.",
            "title": "End Hour"
          },
          "timezone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "IANA zone the hours are read in, e.g. `Asia/Kolkata`. A name that is not one is refused: at call time an unknown zone would make this destination look always-available, silently ignoring the hours above.",
            "title": "Timezone"
          },
          "max_concurrent_calls": {
            "anyOf": [
              {
                "maximum": 50,
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "How many transferred calls this destination can take at once, 1-50. Leave it at 1 for a personal phone; raise it for a call-centre line or hunt group that several people answer. A destination already carrying this many transfers (ringing or connected) is skipped for the next one in priority order. Omitted means 1. Sending `numbers` replaces the whole list, so a row sent without this field goes back to 1.",
            "title": "Max Concurrent Calls"
          }
        },
        "required": [
          "number"
        ],
        "title": "TransferNumber",
        "type": "object"
      },
      "ValidationError": {
        "type": "object",
        "title": "ValidationError",
        "required": [
          "field",
          "message",
          "type"
        ],
        "properties": {
          "field": {
            "type": "string",
            "description": "The offending field as a path from the root of your request \u2014 `voice.speed`, `variables[0].key`, or `query.limit` for a query parameter. **This is the field to read.**"
          },
          "message": {
            "type": "string",
            "description": "What is wrong with it, in plain language."
          },
          "type": {
            "type": "string",
            "description": "A stable machine code for the kind of failure, e.g. `extra_forbidden` for a field we do not accept, `missing` for a required one, or `less_than_equal` for a number out of range. Switch on this rather than on `message`, which may be reworded."
          }
        }
      },
      "Voice": {
        "additionalProperties": false,
        "description": "Text to speech. `GET /v1/voices?provider=` lists voices; `GET /v1/tts-capabilities`\nsays which languages each provider can be handed at all.",
        "properties": {
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "TTS provider, from `GET /v1/voices`.",
            "title": "Provider"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Read-only. Each voice provider ships exactly one model and it is filled in from `provider`; `GET /v1/tts-capabilities` names which.",
            "title": "Model"
          },
          "voice_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which voice, from `GET /v1/voices`. It must be certified for `language.default` or the agent is refused on save \u2014 a provider handed a language it cannot speak fails while the call is being set up, before the caller hears anything.",
            "title": "Voice Id"
          },
          "speed": {
            "anyOf": [
              {
                "maximum": 2.0,
                "minimum": 0.5,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Speaking rate. 1.0 is the voice's natural pace.",
            "title": "Speed"
          },
          "emotion": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Emotional colour: `neutral` `curious` `excited` `enthusiastic` `happy` `content` `calm` `confident` `sad` `apologetic` `frustrated`. **Cartesia only** \u2014 sent for any other provider it is refused, because nothing else would speak it.",
            "title": "Emotion"
          },
          "fallback": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/VoiceFallback"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Backup voice, used for the rest of the call if this one's provider stops responding. Send `{\"provider\": \"sarvam\", \"voice_id\": \"shubh\"}` \u2014 both are required; the model is filled in. Must be from a different provider \u2014 one on the main engine's own provider is refused. See [Backups](/developers/agents/backups)."
          }
        },
        "title": "Voice",
        "type": "object"
      },
      "VoiceFallback": {
        "additionalProperties": false,
        "description": "A backup voice on a DIFFERENT provider, used for the rest of the call if the main\nvoice's provider stops responding. Name both the provider and one of its voices.",
        "properties": {
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Required. The provider to fall back to, from `GET /v1/tts-capabilities`. A voice id alone does not say whose voice it is.",
            "title": "Provider"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The provider's model. Filled in when the provider has only one.",
            "title": "Model"
          },
          "voice_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Required. The voice to use there, from `GET /v1/voices?provider=`.",
            "title": "Voice Id"
          }
        },
        "title": "VoiceFallback",
        "type": "object"
      },
      "WhatsAppTemplateTool": {
        "additionalProperties": false,
        "description": "Off by default, and opt-in: every send spends a template and reaches a real person.\n\n`allowed_templates` is a security boundary \u2014 the agent can only send a template named here. Add the templates themselves in your Vocily workspace first.",
        "properties": {
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the agent may send a WhatsApp template. Armed with `<send_whatsapp_template>` in the prompt.",
            "title": "Enabled"
          },
          "allowed_templates": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "**A security boundary, not a convenience**: the model can only send a template named here.",
            "title": "Allowed Templates"
          },
          "phone_number_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which WhatsApp sender it goes out from \u2014 a `phone_number_id` from `GET /v1/whatsapp/numbers`. One this workspace has not connected is refused.",
            "title": "Phone Number Id"
          }
        },
        "title": "WhatsAppTemplateTool",
        "type": "object"
      },
      "WidgetModes": {
        "properties": {
          "chat": {
            "type": "boolean",
            "title": "Chat",
            "description": "Whether visitors can type to the agent.",
            "default": true
          },
          "talk": {
            "type": "boolean",
            "title": "Talk",
            "description": "Whether visitors can speak to it. A talk session is a real voice call and bills like one.",
            "default": false
          }
        },
        "type": "object",
        "title": "WidgetModes"
      },
      "WidgetTheme": {
        "properties": {
          "title": {
            "type": "string",
            "title": "Title",
            "description": "Heading shown at the top of the widget panel.",
            "default": "Vocily Assistant"
          },
          "subtitle": {
            "type": "string",
            "title": "Subtitle",
            "description": "Line under the heading.",
            "default": "Ask anything or start a web call"
          },
          "welcome_message": {
            "type": "string",
            "title": "Welcome Message",
            "description": "First thing shown in the panel, before the conversation starts.",
            "default": "Hi! How can I help you today?"
          },
          "logo_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Logo Url",
            "description": "Your logo, shown in the panel header."
          },
          "accent_color": {
            "type": "string",
            "title": "Accent Color",
            "description": "Main brand colour, as a hex string like `#7C83FF`.",
            "default": "#7C83FF"
          },
          "launcher_text_color": {
            "type": "string",
            "title": "Launcher Text Color",
            "description": "Text colour on the launcher button, hex.",
            "default": "#FFFFFF"
          },
          "user_message_color": {
            "type": "string",
            "title": "User Message Color",
            "description": "Bubble colour for the visitor's messages, hex.",
            "default": "#7C83FF"
          },
          "user_message_text_color": {
            "type": "string",
            "title": "User Message Text Color",
            "description": "Text colour inside the visitor's bubbles, hex.",
            "default": "#FFFFFF"
          },
          "assistant_message_color": {
            "type": "string",
            "title": "Assistant Message Color",
            "description": "Bubble colour for the agent's messages, hex.",
            "default": "#17171D"
          },
          "assistant_message_text_color": {
            "type": "string",
            "title": "Assistant Message Text Color",
            "description": "Text colour inside the agent's bubbles, hex.",
            "default": "#E5E7EB"
          },
          "position": {
            "type": "string",
            "title": "Position",
            "description": "Which corner the widget sits in \u2014 `bottom-right`, `bottom-left`, `top-right` or `top-left`. Anything else is refused.",
            "default": "bottom-right"
          },
          "launcher_label": {
            "type": "string",
            "title": "Launcher Label",
            "description": "Text on the launcher button.",
            "default": "Chat"
          },
          "button_shape": {
            "type": "string",
            "title": "Button Shape",
            "description": "Shape of the launcher button. `rounded` and `square` are what the dashboard offers. **Open set** \u2014 an unrecognised value is stored and the launcher falls back to its default shape.",
            "default": "rounded"
          },
          "panel_radius": {
            "type": "integer",
            "maximum": 48.0,
            "minimum": 0.0,
            "title": "Panel Radius",
            "description": "Corner radius of the panel, in pixels.",
            "default": 24
          },
          "message_radius": {
            "type": "integer",
            "maximum": 32.0,
            "minimum": 0.0,
            "title": "Message Radius",
            "description": "Corner radius of message bubbles, in pixels.",
            "default": 16
          },
          "launcher_radius": {
            "type": "integer",
            "maximum": 999.0,
            "minimum": 0.0,
            "title": "Launcher Radius",
            "description": "Corner radius of the launcher button, in pixels.",
            "default": 999
          },
          "icon_radius": {
            "type": "integer",
            "maximum": 999.0,
            "minimum": 0.0,
            "title": "Icon Radius",
            "description": "Corner radius of the icon, in pixels.",
            "default": 999
          },
          "dock_icon_size": {
            "type": "integer",
            "maximum": 96.0,
            "minimum": 16.0,
            "title": "Dock Icon Size",
            "description": "Size of the docked icon, in pixels.",
            "default": 26
          },
          "launcher_padding_x": {
            "type": "integer",
            "maximum": 96.0,
            "minimum": 0.0,
            "title": "Launcher Padding X",
            "description": "Horizontal padding inside the launcher button, in pixels.",
            "default": 18
          },
          "launcher_padding_y": {
            "type": "integer",
            "maximum": 80.0,
            "minimum": 0.0,
            "title": "Launcher Padding Y",
            "description": "Vertical padding inside the launcher button, in pixels.",
            "default": 13
          },
          "widget_width": {
            "type": "integer",
            "maximum": 520.0,
            "minimum": 300.0,
            "title": "Widget Width",
            "description": "Panel width, in pixels.",
            "default": 380
          },
          "widget_height": {
            "type": "integer",
            "maximum": 820.0,
            "minimum": 420.0,
            "title": "Widget Height",
            "description": "Panel height, in pixels.",
            "default": 620
          },
          "show_inbound_number": {
            "type": "boolean",
            "title": "Show Inbound Number",
            "description": "Whether to show the agent's inbound number in the panel, so a visitor can call instead.",
            "default": true
          }
        },
        "type": "object",
        "title": "WidgetTheme"
      },
      "ApiError": {
        "type": "object",
        "description": "Error envelope. `code` is derived from the HTTP status, so branch on it for the CLASS of failure; the specific reason is `detail.code`. Every public refusal carries both.",
        "properties": {
          "detail": {
            "type": "object",
            "description": "The reason. `code` is the domain reason (e.g. `call_not_found`) and `message` is a sentence safe to log. On a `422` it also carries `errors[]`, one entry per rejected field \u2014 see `HTTPValidationError`.",
            "properties": {
              "code": {
                "type": "string",
                "example": "call_not_found"
              },
              "message": {
                "type": "string",
                "example": "Call not found"
              }
            },
            "required": [
              "code",
              "message"
            ]
          },
          "code": {
            "type": "string",
            "description": "Derived from the HTTP status, not the domain reason.",
            "example": "NOT_FOUND"
          }
        }
      },
      "PublicKnowledgeBaseDocumentRead": {
        "description": "One piece of content in a knowledge base, as the public API promises it.\n\n`status` is the ingestion state \u2014 adding a document returns 202 and processing happens in the\nbackground, so a client polls the KB until this reads `processed`.",
        "properties": {
          "id": {
            "description": "The document's id.",
            "title": "Id",
            "type": "string"
          },
          "file_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The name we stored it under.",
            "title": "File Name"
          },
          "source_url": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Where it was fetched from, for a URL-sourced document.",
            "title": "Source Url"
          },
          "mime_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "What kind of file it is.",
            "title": "Mime Type"
          },
          "status": {
            "description": "Where ingestion got to \u2014 `pending`, `processing`, `processed`, or `failed`. **Ingestion is asynchronous**: the upload returns `202` and the document is not searchable until this reads `processed`. On `failed`, `error_message` says why.",
            "title": "Status",
            "type": "string"
          },
          "error_message": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Why ingestion failed, if it did.",
            "title": "Error Message"
          },
          "created_at": {
            "description": "When it was uploaded (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "updated_at": {
            "description": "When its status last changed (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "file_name",
          "source_url",
          "mime_type",
          "status",
          "error_message",
          "created_at",
          "updated_at"
        ],
        "title": "PublicKnowledgeBaseDocumentRead",
        "type": "object"
      },
      "PublicKnowledgeBaseRead": {
        "description": "One knowledge base.\n\n`language` and `kb_type` are both growing enums \u2014 match on the values you know and fall through on the rest, rather than switching exhaustively.\n\n`documents` is returned by get-by-id and is `null` in the list, the same convention as `transcript` on a call.",
        "properties": {
          "id": {
            "description": "The knowledge base's id. List it in an agent's `knowledge_base_ids` to attach it.",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "description": "What it is called.",
            "title": "Name",
            "type": "string"
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Your own note about what is in it.",
            "title": "Description"
          },
          "language": {
            "description": "The language its content is in.",
            "title": "Language",
            "type": "string"
          },
          "kb_type": {
            "description": "How answers are produced: `non_deterministic` composes an answer from matching passages, `deterministic` answers only on a near-exact match and returns the stored text verbatim \u2014 which suits pricing, policy and legal copy that must not be paraphrased.",
            "title": "Kb Type",
            "type": "string"
          },
          "document_count": {
            "description": "How many documents it holds.",
            "title": "Document Count",
            "type": "integer"
          },
          "documents": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/PublicKnowledgeBaseDocumentRead"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The documents themselves, with their ingestion status.",
            "title": "Documents"
          },
          "created_at": {
            "description": "When it was created (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "updated_at": {
            "description": "When it last changed (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "language",
          "kb_type",
          "document_count",
          "created_at",
          "updated_at"
        ],
        "title": "PublicKnowledgeBaseRead",
        "type": "object"
      },
      "PublicNumberAgent": {
        "description": "An agent bound to a number. `id` + `name` only \u2014 the same minimal agent shape\n`GET /v1/agents` publishes, for the same reason: an agent's config is not a public contract.",
        "properties": {
          "id": {
            "description": "The agent's id.",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The agent's name.",
            "title": "Name"
          }
        },
        "required": [
          "id"
        ],
        "title": "PublicNumberAgent",
        "type": "object"
      },
      "PublicNumberRental": {
        "description": "Rental terms. Present only for a number you rent from Vocily (`source: \"vocily\"`), and `null` for a number on your own carrier account, where your carrier bills you directly.\n\n`monthly_price` is in major units of `currency` and is fixed at purchase: it is what YOU pay, so a change to our list price never reprices a rental you already hold.",
        "properties": {
          "currency": {
            "default": "USD",
            "description": "ISO currency code.",
            "title": "Currency",
            "type": "string"
          },
          "monthly_price": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What this number costs per month.",
            "title": "Monthly Price"
          },
          "renewal_date": {
            "anyOf": [
              {
                "format": "date",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "When it next renews.",
            "title": "Renewal Date"
          },
          "rented_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "When you started renting it.",
            "title": "Rented At"
          },
          "released_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "When you gave it up. `null` while you still hold it.",
            "title": "Released At"
          }
        },
        "title": "PublicNumberRental",
        "type": "object"
      },
      "PublicNumberRead": {
        "description": "One phone number.\n\nTwo fields say where it comes from: `source` is who you get it from \u2014 `vocily` for a number you rent from us, `byoc` for one on your own carrier account \u2014 and `provider` is the carrier that actually carries it.",
        "properties": {
          "id": {
            "description": "Our stable id for this number. Prefer it over `number` as a key: an E.164 is re-rentable and a released number keeps its row.",
            "title": "Id",
            "type": "string"
          },
          "number": {
            "description": "The number itself, E.164.",
            "title": "Number",
            "type": "string"
          },
          "carrier_status": {
            "description": "`active` or `inactive` \u2014 whether the number is still present in its own carrier account. An `inactive` number will fail if you dial from it. A different question from `lifecycle_status`: a number you still rent reads `active` here only while the carrier lists it, and a carrier outage never changes its rental state.",
            "title": "Carrier Status",
            "type": "string"
          },
          "source": {
            "description": "`vocily` if you rent it from us, `byoc` if you brought your own carrier account.",
            "title": "Source",
            "type": "string"
          },
          "provider": {
            "description": "The carrier your number runs on. `vocily` for a number you rent from us. Your own carrier is named (`plivo`, `vobiz`) when `source` is `byoc`. **Unstable enum: it grows as we support more carriers, so never switch exhaustively on it.**",
            "title": "Provider",
            "type": "string"
          },
          "provider_sid": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "The carrier's own identifier. `null` for a number you rent from us, where the id lives in our account.",
            "title": "Provider Sid"
          },
          "connection_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "Which of your own carrier accounts this number is attached to, when `source` is `byoc` \u2014 it tells two of your accounts apart, which `provider` alone cannot. **Opaque**: no endpoint resolves it to a name, so group by it rather than looking it up. `null` for a number you rent from us.",
            "title": "Connection Id"
          },
          "lifecycle_status": {
            "description": "Where the number is in its rental life with us \u2014 `pending`, `active`, `failed`, `releasing`, `released`. A `released` number keeps its row as a billing record. **Open set.** A different question from `status`, which is carrier presence.",
            "title": "Lifecycle Status",
            "type": "string"
          },
          "country_iso": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "ISO country code the number belongs to.",
            "title": "Country Iso"
          },
          "number_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "description": "How the carrier classified it at purchase \u2014 `local`, `mobile`, `tollfree`. **Unstable enum**: never switch exhaustively on it.",
            "title": "Number Type"
          },
          "inbound_agent": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PublicNumberAgent"
              },
              {
                "type": "null"
              }
            ],
            "description": "The agent answering INBOUND on this number, if any."
          },
          "outbound_agents": {
            "description": "Agents that dial OUT from this number, read from each agent's LIVE version \u2014 an unpublished draft never appears here.",
            "items": {
              "$ref": "#/components/schemas/PublicNumberAgent"
            },
            "title": "Outbound Agents",
            "type": "array"
          },
          "rental": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/PublicNumberRental"
              },
              {
                "type": "null"
              }
            ],
            "description": "Billing detail for a number you rent from us. `null` for BYOC, which you pay your own carrier for."
          },
          "created_at": {
            "description": "When the number was added to your workspace (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "updated_at": {
            "description": "When its record last changed (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "number",
          "carrier_status",
          "source",
          "provider",
          "provider_sid",
          "connection_id",
          "lifecycle_status",
          "country_iso",
          "number_type",
          "inbound_agent",
          "outbound_agents",
          "rental",
          "created_at",
          "updated_at"
        ],
        "title": "PublicNumberRead",
        "type": "object"
      },
      "PublicAgentSummary": {
        "additionalProperties": false,
        "description": "One row of `GET /v1/agents`. No configuration \u2014 the list stays cheap.",
        "properties": {
          "id": {
            "description": "The agent's id. Pass it as `agent_id` on `POST /v1/calls`.",
            "title": "Id",
            "type": "string"
          },
          "name": {
            "description": "What the agent is called.",
            "title": "Name",
            "type": "string"
          },
          "is_live": {
            "description": "Whether any version of it is currently answering.",
            "title": "Is Live",
            "type": "boolean"
          },
          "live_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which version number is live. `null` means the agent is off air.",
            "title": "Live Version"
          },
          "latest_version": {
            "description": "The highest version number this agent has.",
            "title": "Latest Version",
            "type": "integer"
          },
          "inbound_phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The number it answers on, if any.",
            "title": "Inbound Phone"
          },
          "created_at": {
            "description": "When the agent was created (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "updated_at": {
            "description": "When it was last changed (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Updated At",
            "type": "string"
          }
        },
        "required": [
          "id",
          "name",
          "is_live",
          "latest_version",
          "created_at",
          "updated_at"
        ],
        "title": "PublicAgentSummary",
        "type": "object"
      },
      "PublicVersionSummary": {
        "additionalProperties": false,
        "description": "One version in an agent's history.\n\nVersions are identified by NUMBER: it is what every version read returns and what `?version=` and `/versions/{n}` take.",
        "properties": {
          "version": {
            "description": "This version's number \u2014 what you pass in `/versions/{n}`.",
            "title": "Version",
            "type": "integer"
          },
          "version_id": {
            "description": "This version's uuid. Published because `POST /v1/calls` pins a call with `agent_version_id`, which takes a uuid rather than a number.",
            "title": "Version Id",
            "type": "string"
          },
          "is_published": {
            "description": "True once frozen. Configuration can never be edited again; `label` and `notes` still can.",
            "title": "Is Published",
            "type": "boolean"
          },
          "is_live": {
            "description": "True if this is the version answering calls right now.",
            "title": "Is Live",
            "type": "boolean"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Short name for this version.",
            "title": "Label"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Longer free text about this version.",
            "title": "Notes"
          },
          "base_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which version this one was branched from, by NUMBER \u2014 `null` for the agent's first.",
            "title": "Base Version"
          },
          "document_revision": {
            "description": "This version's edit counter. Send it as `If-Match` to make a write conditional.",
            "title": "Document Revision",
            "type": "integer"
          },
          "blocked_reasons": {
            "description": "Why this version cannot be made live, if it cannot \u2014 e.g. it pins a retired model. Check it before offering a deploy button, so the button never fails on click.",
            "items": {
              "type": "string"
            },
            "title": "Blocked Reasons",
            "type": "array"
          },
          "inbound_phone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The phone number this version will answer on once it is made live. Inert until then.",
            "title": "Inbound Phone"
          },
          "inbound_whatsapp": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The WhatsApp number this version will answer on once it is made live. Inert until then.",
            "title": "Inbound Whatsapp"
          },
          "created_at": {
            "description": "When this version was created (UTC, ISO 8601).",
            "format": "date-time",
            "title": "Created At",
            "type": "string"
          },
          "published_at": {
            "anyOf": [
              {
                "format": "date-time",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "When it was frozen. `null` while it is still a draft.",
            "title": "Published At"
          }
        },
        "required": [
          "version",
          "version_id",
          "is_published",
          "is_live",
          "document_revision",
          "created_at"
        ],
        "title": "PublicVersionSummary",
        "type": "object"
      },
      "PublicActivation": {
        "additionalProperties": false,
        "description": "One entry in the deploy history: when a version started answering, or stopped.\n\n`version_id` is null when that version was later deleted \u2014 the number and the moment\nstill tell the story, which is the point of keeping the row.",
        "properties": {
          "version": {
            "description": "Which version number was involved.",
            "title": "Version",
            "type": "integer"
          },
          "version_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "That version's uuid. `null` when the version has since been deleted \u2014 `version` and the timestamp still tell you what happened.",
            "title": "Version Id"
          },
          "action": {
            "description": "What happened. `live` \u2014 this version started answering calls. `off_air` \u2014 the agent stopped answering; `version` is what it was taken off.",
            "enum": [
              "live",
              "off_air"
            ],
            "title": "Action",
            "type": "string"
          },
          "at": {
            "description": "When it happened (UTC, ISO 8601).",
            "format": "date-time",
            "title": "At",
            "type": "string"
          }
        },
        "required": [
          "version",
          "action",
          "at"
        ],
        "title": "PublicActivation",
        "type": "object"
      },
      "VersionDiff": {
        "additionalProperties": false,
        "description": "One difference between two versions, in the PUBLIC field vocabulary.\n\n`field` is the path as this API names it (`voice.voice_id`), not the stored path\n(`core.voice_config.tts.voice`) \u2014 a diff a customer cannot map back onto the fields\nthey set is a diff they cannot act on.",
        "properties": {
          "field": {
            "description": "The field that differs, as a PUBLIC path \u2014 the same path you would send on a PATCH.",
            "title": "Field",
            "type": "string"
          },
          "change": {
            "description": "Whether it was added, removed, or changed between the two versions.",
            "enum": [
              "added",
              "removed",
              "changed"
            ],
            "title": "Change",
            "type": "string"
          },
          "before": {
            "default": null,
            "description": "Its value on the left version.",
            "title": "Before"
          },
          "after": {
            "default": null,
            "description": "Its value on the right version.",
            "title": "After"
          }
        },
        "required": [
          "field",
          "change"
        ],
        "title": "VersionDiff",
        "type": "object"
      },
      "PublicVersionCompare": {
        "additionalProperties": false,
        "properties": {
          "left": {
            "$ref": "#/components/schemas/PublicVersionSummary",
            "description": "The first version of the pair."
          },
          "right": {
            "$ref": "#/components/schemas/PublicVersionSummary",
            "description": "The second version of the pair."
          },
          "differences": {
            "description": "Every configuration field that differs, in PUBLIC field paths \u2014 the same paths you send on a PATCH. Metadata (labels, timestamps, version numbers) is excluded: it always differs and says nothing about behaviour.",
            "items": {
              "$ref": "#/components/schemas/VersionDiff"
            },
            "title": "Differences",
            "type": "array"
          }
        },
        "required": [
          "left",
          "right"
        ],
        "title": "PublicVersionCompare",
        "type": "object"
      },
      "PublicAgentCreate": {
        "additionalProperties": false,
        "description": "Create an agent, fully configured, in one request.\n\n`name` is the only required field \u2014 everything else takes the platform default, so the\nsmallest useful body is a name, a prompt and a greeting. The agent is created as an\n**unpublished draft (V0)**: it answers nothing until you publish a version and make it\nlive, which stays two explicit calls.",
        "properties": {
          "name": {
            "description": "What the agent is called. The one required field. Never spoken to a caller.",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "system_prompt": {
            "anyOf": [
              {
                "maxLength": 65536,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The agent's instructions. Naming a tool as `<tool_name>` here is what ARMS it: a tool the prompt never names is never called, and naming one the version does not have is refused on save.",
            "title": "System Prompt"
          },
          "greeting": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Greeting"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What the agent says first."
          },
          "language": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LanguageConfig"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The language it opens in, which others it may switch to, and what triggers a switch."
          },
          "transcriber": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Transcriber"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Speech recognition. `GET /v1/transcribers` lists valid `model` values."
          },
          "model": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Model"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The LLM. `GET /v1/models` lists valid `model` and `provider` values."
          },
          "voice": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Voice"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Text to speech. `GET /v1/voices` lists valid `voice_id` values, and a voice that cannot speak `language.default` is refused on save."
          },
          "conversation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Conversation"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Turn-taking, interruption and noise handling \u2014 how it behaves in the back-and-forth."
          },
          "call": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CallSettings"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Limits on the call itself: maximum duration, silence timeout, and what ends it."
          },
          "inbound": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Inbound"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Lines for inbound calls that cannot be handled normally."
          },
          "builtin_tools": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BuiltinTools"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The tools Vocily ships: end the call, hold, transfer, send a WhatsApp template. Each still has to be armed from the prompt."
          },
          "variables": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/RuntimeVariable"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The `{{placeholders}}` the prompt and tools can use. Reference them namespaced as `{{custom.your_key}}`, never bare. Sending this list replaces the whole set.",
            "title": "Variables"
          },
          "knowledge_base_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which knowledge bases this agent can search, from `GET /v1/knowledge-bases`. **This list IS the attachment** \u2014 there is no separate attach endpoint, and sending it replaces the whole set. An id this workspace does not hold is refused, not ignored.",
            "title": "Knowledge Base Ids"
          },
          "analysis_group_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which custom-analysis groups run after each call, from `GET /v1/custom-analysis`. The list is the attachment, and an id this workspace does not hold is refused, not ignored.",
            "title": "Analysis Group Ids"
          },
          "memory": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Memory"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the agent remembers callers between calls, and what it is allowed to remember."
          },
          "numbers": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Numbers"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which phone and WhatsApp numbers this agent answers on. `GET /v1/numbers` and `GET /v1/whatsapp/numbers` list what you may use."
          }
        },
        "required": [
          "name"
        ],
        "title": "PublicAgentCreate",
        "type": "object"
      },
      "PublicAgentUpdate": {
        "additionalProperties": false,
        "description": "Change any setting. Merge-patch: objects merge, lists replace whole, `null` clears.\n\nApplies to the agent's newest draft. If the newest version is published, a draft is branched from the live version first \u2014 a published version's configuration cannot change.",
        "properties": {
          "name": {
            "anyOf": [
              {
                "maxLength": 255,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What the agent is called. Yours to choose; never spoken to a caller.",
            "title": "Name"
          },
          "system_prompt": {
            "anyOf": [
              {
                "maxLength": 65536,
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The agent's instructions. Naming a tool as `<tool_name>` here is what ARMS it: a tool the prompt never names is never called, and naming one the version does not have is refused on save.",
            "title": "System Prompt"
          },
          "greeting": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Greeting"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What the agent says first."
          },
          "language": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/LanguageConfig"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The language it opens in, which others it may switch to, and what triggers a switch."
          },
          "transcriber": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Transcriber"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Speech recognition. `GET /v1/transcribers` lists valid `model` values."
          },
          "model": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Model"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The LLM. `GET /v1/models` lists valid `model` and `provider` values."
          },
          "voice": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Voice"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Text to speech. `GET /v1/voices` lists valid `voice_id` values, and a voice that cannot speak `language.default` is refused on save."
          },
          "conversation": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Conversation"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Turn-taking, interruption and noise handling \u2014 how it behaves in the back-and-forth."
          },
          "call": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CallSettings"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Limits on the call itself: maximum duration, silence timeout, and what ends it."
          },
          "inbound": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Inbound"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Lines for inbound calls that cannot be handled normally."
          },
          "builtin_tools": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/BuiltinTools"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The tools Vocily ships: end the call, hold, transfer, send a WhatsApp template. Each still has to be armed from the prompt."
          },
          "variables": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/RuntimeVariable"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The `{{placeholders}}` the prompt and tools can use. Reference them namespaced as `{{custom.your_key}}`, never bare. Sending this list replaces the whole set.",
            "title": "Variables"
          },
          "knowledge_base_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which knowledge bases this agent can search, from `GET /v1/knowledge-bases`. **This list IS the attachment** \u2014 there is no separate attach endpoint, and sending it replaces the whole set. An id this workspace does not hold is refused, not ignored.",
            "title": "Knowledge Base Ids"
          },
          "analysis_group_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which custom-analysis groups run after each call, from `GET /v1/custom-analysis`. The list is the attachment, and an id this workspace does not hold is refused, not ignored.",
            "title": "Analysis Group Ids"
          },
          "memory": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Memory"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Whether the agent remembers callers between calls, and what it is allowed to remember."
          },
          "numbers": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/Numbers"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Which phone and WhatsApp numbers this agent answers on. `GET /v1/numbers` and `GET /v1/whatsapp/numbers` list what you may use."
          },
          "label": {
            "anyOf": [
              {
                "maxLength": 80,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Short name for the version this change lands on. Editable on a published version too.",
            "title": "Label"
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Longer free text for the version this change lands on. Editable on a published version too.",
            "title": "Notes"
          }
        },
        "title": "PublicAgentUpdate",
        "type": "object"
      },
      "Inbound": {
        "additionalProperties": false,
        "description": "Lines for calls that arrive and cannot be handled normally.\n\n`business_hours_closed` is recorded but never spoken today: the platform has no business\nhours to compare a call against, so nothing can decide a call arrived outside them.",
        "properties": {
          "business_hours_closed_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Reserved. Stored, and not spoken today \u2014 the platform has no business-hours schedule to judge a call against."
          },
          "fallback_message": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/SystemMessage"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "What an inbound caller hears when the call cannot be handled."
          }
        },
        "title": "Inbound",
        "type": "object"
      },
      "ModelFallback": {
        "additionalProperties": false,
        "description": "A backup model on a DIFFERENT provider, used for the rest of the call if the main\nmodel's provider stops responding.\n\nName the model; the provider comes with it. A backup on the main model's own provider is\nrefused: what fails is almost never one model \u2014 the vendor is unreachable, the key is\nrejected, the region is down \u2014 and every model behind that provider fails with it.",
        "properties": {
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Read-only. Derived from `model` \u2014 the catalogue decides routing, so a value sent here is ignored.",
            "title": "Provider"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Model id, from `GET /v1/models`. It must be on a different provider than the main model \u2014 one on the same provider is refused, because an outage takes every model behind that provider down together.",
            "title": "Model"
          }
        },
        "title": "ModelFallback",
        "type": "object"
      },
      "PublicAnalysisGroupCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "description": "What to call this group. **It becomes part of the key values arrive under** \u2014 `custom_analysis[\"Lead QA\"][\u2026]` \u2014 so renaming it later changes your payload shape."
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Your own note about what the group is for."
          },
          "model": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 128
              },
              {
                "type": "null"
              }
            ],
            "title": "Model",
            "description": "Which LLM runs the extraction. Defaults to the agent's own."
          },
          "temperature": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 2.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Temperature",
            "description": "Randomness for the extraction. Lower is more repeatable, which is usually what you want here."
          },
          "max_tokens": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 10000.0,
                "minimum": 50.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Tokens",
            "description": "Cap on the extraction response."
          },
          "conditions": {
            "$ref": "#/components/schemas/CustomAnalysisConditions",
            "description": "When this group runs at all. A group that does not run costs nothing."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "name"
        ],
        "title": "PublicAnalysisGroupCreate"
      },
      "PublicAnalysisGroupUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "description": "What to call this group. Renaming changes the key values arrive under on every future call, while past calls keep the old name."
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Your own note about what the group is for."
          },
          "model": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 128,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Model",
            "description": "Which LLM runs the extraction."
          },
          "temperature": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 2.0,
                "minimum": 0.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Temperature",
            "description": "Randomness for the extraction."
          },
          "max_tokens": {
            "anyOf": [
              {
                "type": "integer",
                "maximum": 10000.0,
                "minimum": 50.0
              },
              {
                "type": "null"
              }
            ],
            "title": "Max Tokens",
            "description": "Cap on the extraction response."
          },
          "conditions": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CustomAnalysisConditions"
              },
              {
                "type": "null"
              }
            ],
            "description": "When this group runs at all."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PublicAnalysisGroupUpdate"
      },
      "PublicAnalysisItemCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "description": "What to call this value. **Part of the key it arrives under** \u2014 `custom_analysis[\"Lead QA\"][\"Lead Temperature\"]`."
          },
          "description": {
            "type": "string",
            "minLength": 1,
            "title": "Description",
            "description": "**The instruction the model reads, not a label.** Write it as a direction \u2014 what to look for \u2014 rather than a title."
          },
          "extraction_method": {
            "type": "string",
            "maxLength": 8,
            "title": "Extraction Method",
            "description": "`regex` pulls the value out by pattern using `constraints.pattern` and costs nothing; anything else asks the model. A group made only of regex items makes no model call at all.",
            "default": "ai"
          },
          "result_format": {
            "type": "string",
            "maxLength": 16,
            "title": "Result Format",
            "description": "The shape of the value: `string`, `number`, `integer`, `boolean`, `array` or `object`."
          },
          "required": {
            "type": "boolean",
            "title": "Required",
            "description": "Whether the model must produce a value rather than leaving it out.",
            "default": false
          },
          "constraints": {
            "$ref": "#/components/schemas/CustomAnalysisConstraints",
            "description": "Limits on the value \u2014 a fixed set with `enum`, a range, a regex, a length."
          },
          "fields": {
            "items": {
              "$ref": "#/components/schemas/CustomAnalysisFieldSpec"
            },
            "type": "array",
            "title": "Fields",
            "description": "The inner fields, when `result_format` is `object` or `array`."
          },
          "enabled": {
            "type": "boolean",
            "title": "Enabled",
            "description": "Turn it off without deleting it.",
            "default": true
          },
          "category_id": {
            "type": "string",
            "title": "Category Id",
            "description": "Which group this value belongs to, from `GET /v1/custom-analysis`."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "name",
          "description",
          "result_format",
          "category_id"
        ],
        "title": "PublicAnalysisItemCreate"
      },
      "PublicAnalysisItemUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "description": "What to call this value. Renaming changes the key it arrives under on every future call."
          },
          "description": {
            "anyOf": [
              {
                "type": "string",
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "**The instruction the model reads.** Tightening it is how you fix a bad extraction."
          },
          "extraction_method": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 8
              },
              {
                "type": "null"
              }
            ],
            "title": "Extraction Method",
            "description": "`regex` pulls the value out by pattern and costs nothing; anything else asks the model."
          },
          "result_format": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 16
              },
              {
                "type": "null"
              }
            ],
            "title": "Result Format",
            "description": "The shape of the value. Changing it changes the shape on every future call; past calls keep what they were analysed with."
          },
          "required": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Required",
            "description": "Whether the model must produce a value."
          },
          "constraints": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/CustomAnalysisConstraints"
              },
              {
                "type": "null"
              }
            ],
            "description": "Limits on the value. Narrowing an `enum` can leave older rows holding values no longer in the list."
          },
          "fields": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/components/schemas/CustomAnalysisFieldSpec"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Fields",
            "description": "The inner fields, for an `object` or `array` value."
          },
          "enabled": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "title": "Enabled",
            "description": "Turn it off without deleting it."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PublicAnalysisItemUpdate"
      },
      "PublicDraftRequest": {
        "properties": {
          "from_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "title": "From Version",
            "description": "The version to branch from, by number \u2014 e.g. `4`. Omit to branch from the live version, or from the newest one if nothing is live yet."
          },
          "base_version_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Base Version Id",
            "description": "The same choice by uuid. `from_version` is the friendlier one: a number is what a version is called everywhere else."
          },
          "label": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80
              },
              {
                "type": "null"
              }
            ],
            "title": "Label",
            "description": "A short name for the draft. `V<n>` is already its identity, so this is description rather than a name."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PublicDraftRequest",
        "description": "`POST /v1/agents/{id}/drafts`.\n\nEither spelling of \"which version do I branch from\" is accepted: `from_version`, the number\nyou already hold, or `base_version_id`, its uuid. An unknown field is refused here rather\nthan deeper in, so a typo reads like every other refused body on this surface."
      },
      "PublicKBCreate": {
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255,
            "minLength": 1,
            "title": "Name",
            "description": "What to call this knowledge base."
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Your own note about what is in it."
          },
          "language": {
            "type": "string",
            "pattern": "^(english|multilingual)$",
            "title": "Language",
            "description": "`english` or `multilingual`, matching the content you will upload.",
            "default": "english"
          },
          "kb_type": {
            "type": "string",
            "pattern": "^(deterministic|non_deterministic)$",
            "title": "Kb Type",
            "description": "`non_deterministic` composes an answer from matching passages; `deterministic` answers only on a near-exact match and returns the stored text verbatim \u2014 which suits pricing, policy and legal copy that must not be paraphrased.",
            "default": "non_deterministic"
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "name"
        ],
        "title": "PublicKBCreate"
      },
      "PublicKBUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "description": "What to call this knowledge base."
          },
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Description",
            "description": "Your own note about what is in it."
          },
          "language": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(english|multilingual)$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "`english` or `multilingual`, matching the content you will upload."
          },
          "kb_type": {
            "anyOf": [
              {
                "type": "string",
                "pattern": "^(deterministic|non_deterministic)$"
              },
              {
                "type": "null"
              }
            ],
            "title": "Kb Type",
            "description": "`non_deterministic` composes an answer from matching passages; `deterministic` answers only on a near-exact match and returns the stored text verbatim \u2014 which suits pricing, policy and legal copy that must not be paraphrased."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PublicKBUpdate"
      },
      "PublicMemoryFlushRequest": {
        "properties": {
          "last_updated_on": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Updated On",
            "description": "Erase memory last touched on this date. A selector, not a stored field."
          },
          "last_updated_from": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Updated From",
            "description": "Erase memory last touched on or after this date."
          },
          "last_updated_to": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Last Updated To",
            "description": "Erase memory last touched on or before this date."
          },
          "subjects": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Subjects",
            "description": "Erase only these people, by subject id. Omit to cover everyone the filters match."
          },
          "dry_run": {
            "type": "boolean",
            "title": "Dry Run",
            "description": "**Send `true` first.** It reports exactly what WOULD be erased and deletes nothing \u2014 the only way to check a filter before an irreversible delete.",
            "default": true
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PublicMemoryFlushRequest"
      },
      "PublicWidgetUpdate": {
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 255,
                "minLength": 1
              },
              {
                "type": "null"
              }
            ],
            "title": "Name",
            "description": "What to call this widget."
          },
          "allowed_origins": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "title": "Allowed Origins",
            "description": "**The security boundary**: which origins may use this widget's public key. Sending the list replaces the whole set."
          },
          "enabled_modes": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WidgetModes"
              },
              {
                "type": "null"
              }
            ],
            "description": "Whether visitors can type, talk, or both."
          },
          "theme": {
            "anyOf": [
              {
                "$ref": "#/components/schemas/WidgetTheme"
              },
              {
                "type": "null"
              }
            ],
            "description": "Appearance and placement."
          },
          "default_variables": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "title": "Default Variables",
            "description": "Values supplied for the agent's `{{variables}}` on every conversation this widget starts."
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Status",
            "description": "Whether the widget is live or paused."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PublicWidgetUpdate"
      },
      "PublishRequest": {
        "properties": {
          "label": {
            "anyOf": [
              {
                "type": "string",
                "maxLength": 80
              },
              {
                "type": "null"
              }
            ],
            "title": "Label",
            "description": "Short name to freeze onto this version."
          },
          "notes": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Notes",
            "description": "Longer free text to freeze onto it."
          },
          "make_live": {
            "type": "boolean",
            "title": "Make Live",
            "description": "Publish AND put it on air in one call. Read the result back as `is_live`.",
            "default": false
          }
        },
        "additionalProperties": false,
        "type": "object",
        "title": "PublishRequest",
        "description": "Freeze a draft. `make_live` deploys it in the same call.\n\n`V<n>` is already the version's identity, so `label` is description rather than\nidentification and forcing one only buys junk names."
      },
      "TranscriberFallback": {
        "additionalProperties": false,
        "description": "A backup speech model on a DIFFERENT provider, used for the rest of the call if the\nmain one stops responding.\n\nName the model; the provider comes with it. A backup on the main model's own provider is\nrefused: what fails is almost never one model \u2014 the vendor is unreachable, the key is\nrejected, the region is down \u2014 and every model behind that provider fails with it.",
        "properties": {
          "provider": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Read-only. Derived from `model` \u2014 each speech model belongs to one provider, so a value sent here is ignored.",
            "title": "Provider"
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Model id, from `GET /v1/transcribers`. A model not listed there is refused.",
            "title": "Model"
          }
        },
        "title": "TranscriberFallback",
        "type": "object"
      },
      "PublicSpeechRequest": {
        "properties": {
          "text": {
            "type": "string",
            "maxLength": 1000,
            "minLength": 1,
            "title": "Text",
            "description": "What to say. Up to 1000 characters."
          },
          "provider": {
            "type": "string",
            "title": "Provider",
            "description": "Voice provider, from `GET /v1/voices`."
          },
          "voice_id": {
            "type": "string",
            "title": "Voice Id",
            "description": "Which voice, from `GET /v1/voices?provider=`. Must belong to `provider` \u2014 a voice id means nothing without the engine it came from."
          },
          "model": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Model",
            "description": "Read-only in practice. Each provider ships exactly one model and it is filled in from `provider`; `GET /v1/tts-capabilities` names which."
          },
          "language": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Language",
            "description": "The language to speak `text` in, e.g. `hi-IN`. Defaults to the provider's own default. A voice not certified for it is refused rather than substituted \u2014 `languages` on each `GET /v1/voices` row is that list."
          },
          "speed": {
            "anyOf": [
              {
                "type": "number",
                "maximum": 4.0,
                "minimum": 0.25
              },
              {
                "type": "null"
              }
            ],
            "title": "Speed",
            "description": "Speaking rate. 1.0 is the voice's natural pace, and each provider clamps it to its own range. **Not supported by `elevenlabs`** \u2014 sent for that provider it is refused rather than ignored."
          },
          "emotion": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "title": "Emotion",
            "description": "Emotional colour: `neutral` `curious` `excited` `enthusiastic` `happy` `content` `calm` `confident` `sad` `apologetic` `frustrated`. **Cartesia only** \u2014 sent for any other provider it is refused, because nothing else would speak it."
          }
        },
        "additionalProperties": false,
        "type": "object",
        "required": [
          "text",
          "provider",
          "voice_id"
        ],
        "title": "PublicSpeechRequest",
        "description": "The body of `POST /v1/speech`."
      }
    },
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Your API key as a Bearer token, e.g. `Authorization: Bearer vk_\u2026`."
      }
    }
  },
  "servers": [
    {
      "url": "https://api.vocily.ai",
      "description": "Production"
    }
  ]
}
