{
  "openapi": "3.1.0",
  "info": {
    "title": "Voximate API",
    "version": "v1",
    "summary": "Build on Voximate voice agents: agents, calls, phone numbers, webhooks and usage.",
    "description": "The Voximate API lets your own software create and manage AI voice agents, start outbound calls, read call results and transcripts, and receive signed webhooks when calls start and end. Every request is authenticated with an API key created in the Voximate dashboard.",
    "contact": {
      "name": "Voximate",
      "url": "https://voximate.no",
      "email": "kontakt@voximate.no"
    }
  },
  "servers": [
    {
      "url": "https://api.voximate.no/public/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "ApiKey": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "The API key in use and what it may do."
    },
    {
      "name": "Agents",
      "description": "AI voice agents: their instructions, greeting, voice and language."
    },
    {
      "name": "Calls",
      "description": "Start outbound calls and read finished ones, with transcript and analysis."
    },
    {
      "name": "Phone numbers",
      "description": "The numbers in your workspace and which agent answers each one."
    },
    {
      "name": "Webhooks",
      "description": "Endpoints that receive signed events from Voximate."
    },
    {
      "name": "Usage",
      "description": "Call counts and minutes for a period."
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "operationId": "getMe",
        "tags": [
          "Account"
        ],
        "summary": "Retrieve the current API key",
        "description": "Returns the key that made the request: its id, workspace and scopes. Needs no scope, so it is the quickest way to check that a key works.",
        "responses": {
          "200": {
            "description": "The API key.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiKeyInfo"
                },
                "example": {
                  "object": "api_key",
                  "id": "0b6f3c2e-1a4d-4e5f-9a8b-7c6d5e4f3a2b",
                  "workspace_id": "4f1a2b3c-5d6e-4f70-8a9b-0c1d2e3f4a5b",
                  "scopes": [
                    "agents:read",
                    "calls:read",
                    "calls:write"
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/agents": {
      "get": {
        "operationId": "listAgents",
        "tags": [
          "Agents"
        ],
        "summary": "List agents",
        "description": "Returns the agents in your workspace, newest first.",
        "x-scopes": [
          "agents:read"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of agents.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Agent"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page follows this one."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
                    }
                  }
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "agent",
                      "id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                      "name": "Reception - Nordvik Dental",
                      "description": "Answers the main line and books check-ups.",
                      "status": "published",
                      "language": "nb-NO",
                      "system_prompt": "You are Sara, the receptionist at Nordvik Dental. Keep answers short.",
                      "first_message": "Hei, du har kommet til Nordvik Tannklinikk. Hva kan jeg hjelpe deg med?",
                      "outbound_first_message": "Hei, dette er Nordvik Tannklinikk.",
                      "voice": {
                        "provider": "elevenlabs",
                        "voice_id": "aya-norwegian"
                      },
                      "llm": {
                        "provider": "openai",
                        "model": "gpt-4o"
                      },
                      "created_at": "2026-10-01T09:12:44.000Z",
                      "updated_at": "2026-10-12T18:03:10.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "operationId": "createAgent",
        "tags": [
          "Agents"
        ],
        "summary": "Create an agent",
        "description": "Creates an agent as a draft. A draft answers in the dashboard test panel but takes no phone calls until it is published.",
        "x-scopes": [
          "agents:write"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentCreate"
              },
              "example": {
                "name": "After-hours line",
                "language": "nb-NO",
                "system_prompt": "You take messages after opening hours. Ask for name, number and reason.",
                "first_message": "Hei! Vi har stengt nå, men jeg kan ta imot en beskjed."
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                },
                "example": {
                  "object": "agent",
                  "id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "name": "After-hours line",
                  "description": "Answers the main line and books check-ups.",
                  "status": "draft",
                  "language": "nb-NO",
                  "system_prompt": "You are Sara, the receptionist at Nordvik Dental. Keep answers short.",
                  "first_message": "Hei, du har kommet til Nordvik Tannklinikk. Hva kan jeg hjelpe deg med?",
                  "outbound_first_message": "Hei, dette er Nordvik Tannklinikk.",
                  "voice": {
                    "provider": "elevenlabs",
                    "voice_id": "aya-norwegian"
                  },
                  "llm": {
                    "provider": "openai",
                    "model": "gpt-4o"
                  },
                  "created_at": "2026-10-01T09:12:44.000Z",
                  "updated_at": "2026-10-12T18:03:10.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/agents/{agent_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "get": {
        "operationId": "getAgent",
        "tags": [
          "Agents"
        ],
        "summary": "Retrieve an agent",
        "x-scopes": [
          "agents:read"
        ],
        "responses": {
          "200": {
            "description": "The agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                },
                "example": {
                  "object": "agent",
                  "id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "name": "Reception - Nordvik Dental",
                  "description": "Answers the main line and books check-ups.",
                  "status": "published",
                  "language": "nb-NO",
                  "system_prompt": "You are Sara, the receptionist at Nordvik Dental. Keep answers short.",
                  "first_message": "Hei, du har kommet til Nordvik Tannklinikk. Hva kan jeg hjelpe deg med?",
                  "outbound_first_message": "Hei, dette er Nordvik Tannklinikk.",
                  "voice": {
                    "provider": "elevenlabs",
                    "voice_id": "aya-norwegian"
                  },
                  "llm": {
                    "provider": "openai",
                    "model": "gpt-4o"
                  },
                  "created_at": "2026-10-01T09:12:44.000Z",
                  "updated_at": "2026-10-12T18:03:10.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "operationId": "updateAgent",
        "tags": [
          "Agents"
        ],
        "summary": "Update an agent",
        "description": "Changes only the fields you send. A published agent stays published, and the change applies from its next call.",
        "x-scopes": [
          "agents:write"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AgentUpdate"
              },
              "example": {
                "first_message": "Hei, du har kommet til Nordvik Tannklinikk. Hvordan kan jeg hjelpe?"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                },
                "example": {
                  "object": "agent",
                  "id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "name": "Reception - Nordvik Dental",
                  "description": "Answers the main line and books check-ups.",
                  "status": "published",
                  "language": "nb-NO",
                  "system_prompt": "You are Sara, the receptionist at Nordvik Dental. Keep answers short.",
                  "first_message": "Hei, du har kommet til Nordvik Tannklinikk. Hva kan jeg hjelpe deg med?",
                  "outbound_first_message": "Hei, dette er Nordvik Tannklinikk.",
                  "voice": {
                    "provider": "elevenlabs",
                    "voice_id": "aya-norwegian"
                  },
                  "llm": {
                    "provider": "openai",
                    "model": "gpt-4o"
                  },
                  "created_at": "2026-10-01T09:12:44.000Z",
                  "updated_at": "2026-10-12T18:03:10.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      },
      "delete": {
        "operationId": "deleteAgent",
        "tags": [
          "Agents"
        ],
        "summary": "Delete an agent",
        "description": "Deletes the agent. Phone numbers it answered are left without an agent. Past calls and their transcripts are kept.",
        "x-scopes": [
          "agents:write"
        ],
        "responses": {
          "200": {
            "description": "The agent was deleted.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "agent",
                  "id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "deleted": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/agents/{agent_id}/publish": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "post": {
        "operationId": "publishAgent",
        "tags": [
          "Agents"
        ],
        "summary": "Publish an agent",
        "description": "Makes the agent live: phone numbers assigned to it start reaching it, and it can place outbound calls.",
        "x-scopes": [
          "agents:write"
        ],
        "responses": {
          "200": {
            "description": "The published agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                },
                "example": {
                  "object": "agent",
                  "id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "name": "Reception - Nordvik Dental",
                  "description": "Answers the main line and books check-ups.",
                  "status": "published",
                  "language": "nb-NO",
                  "system_prompt": "You are Sara, the receptionist at Nordvik Dental. Keep answers short.",
                  "first_message": "Hei, du har kommet til Nordvik Tannklinikk. Hva kan jeg hjelpe deg med?",
                  "outbound_first_message": "Hei, dette er Nordvik Tannklinikk.",
                  "voice": {
                    "provider": "elevenlabs",
                    "voice_id": "aya-norwegian"
                  },
                  "llm": {
                    "provider": "openai",
                    "model": "gpt-4o"
                  },
                  "created_at": "2026-10-01T09:12:44.000Z",
                  "updated_at": "2026-10-12T18:03:10.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/agents/{agent_id}/unpublish": {
      "parameters": [
        {
          "$ref": "#/components/parameters/AgentId"
        }
      ],
      "post": {
        "operationId": "unpublishAgent",
        "tags": [
          "Agents"
        ],
        "summary": "Unpublish an agent",
        "description": "Takes the agent off the phone. Its settings are kept and it can be published again.",
        "x-scopes": [
          "agents:write"
        ],
        "responses": {
          "200": {
            "description": "The unpublished agent.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Agent"
                },
                "example": {
                  "object": "agent",
                  "id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "name": "Reception - Nordvik Dental",
                  "description": "Answers the main line and books check-ups.",
                  "status": "unpublished",
                  "language": "nb-NO",
                  "system_prompt": "You are Sara, the receptionist at Nordvik Dental. Keep answers short.",
                  "first_message": "Hei, du har kommet til Nordvik Tannklinikk. Hva kan jeg hjelpe deg med?",
                  "outbound_first_message": "Hei, dette er Nordvik Tannklinikk.",
                  "voice": {
                    "provider": "elevenlabs",
                    "voice_id": "aya-norwegian"
                  },
                  "llm": {
                    "provider": "openai",
                    "model": "gpt-4o"
                  },
                  "created_at": "2026-10-01T09:12:44.000Z",
                  "updated_at": "2026-10-12T18:03:10.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/calls": {
      "get": {
        "operationId": "listCalls",
        "tags": [
          "Calls"
        ],
        "summary": "List calls",
        "description": "Returns calls newest first. Filter by agent, direction and time.",
        "x-scopes": [
          "calls:read"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "agent_id",
            "in": "query",
            "description": "Only calls handled by this agent.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "direction",
            "in": "query",
            "description": "Only inbound or only outbound calls.",
            "schema": {
              "type": "string",
              "enum": [
                "inbound",
                "outbound"
              ]
            }
          },
          {
            "name": "created_after",
            "in": "query",
            "description": "Only calls that started at or after this time (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "created_before",
            "in": "query",
            "description": "Only calls that started before this time (ISO 8601).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of calls.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Call"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page follows this one."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
                    }
                  }
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "call",
                      "id": "3c27f11c-8a1e-4d55-9b0e-1f4c2a7d9e10",
                      "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                      "direction": "outbound",
                      "channel": "phone",
                      "status": "completed",
                      "from": "+4721000000",
                      "to": "+4712345678",
                      "started_at": "2026-10-12T10:04:12.000Z",
                      "ended_at": "2026-10-12T10:07:33.000Z",
                      "duration_seconds": 201,
                      "end_reason": "caller_hangup",
                      "metadata": {
                        "crm_contact_id": "48213"
                      },
                      "has_recording": null,
                      "analysis": null
                    }
                  ],
                  "has_more": true,
                  "next_cursor": "eyJvIjoyMH0"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "operationId": "createCall",
        "tags": [
          "Calls"
        ],
        "summary": "Start an outbound call",
        "description": "Asks a published agent to call a phone number. Every check runs first (the agent is published, the number is yours, the number is not an emergency number, your plan has minutes); then the dial starts and this returns `202` with the call in status `queued`, without waiting for the phone to be answered.\n\nHow the call goes arrives as webhooks: `call.started` when it is answered, then `call.completed` with the analysis, or `call.failed` with `reason` `no_answer`, `busy` or `not_connected`. `GET /calls/{call_id}` shows the same.\n\nThe agent knows it placed the call: it says who it is and why it is calling, instead of answering as if it had been rung. It opens with `first_message` when you send one, else the agent's `outbound_first_message`, else its `first_message`.\n\nSend an `Idempotency-Key` so a retried request can never ring the same person twice. If this answers `503 call_outcome_unknown`, the call may already be ringing: look for it with `GET /calls` before trying again with a new key.",
        "x-scopes": [
          "calls:write"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CallCreate"
              },
              "example": {
                "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                "to": "+4712345678",
                "first_message": "Hei, dette er Nordvik Tannklinikk. Jeg ringer om timen din i morgen.",
                "metadata": {
                  "crm_contact_id": "48213"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "The call passed every check and the dial has started.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Call"
                },
                "example": {
                  "object": "call",
                  "id": "3c27f11c-8a1e-4d55-9b0e-1f4c2a7d9e10",
                  "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "direction": "outbound",
                  "channel": "phone",
                  "status": "queued",
                  "from": "+4721000000",
                  "to": "+4712345678",
                  "started_at": "2026-10-12T10:04:12.000Z",
                  "ended_at": null,
                  "duration_seconds": null,
                  "end_reason": null,
                  "metadata": {
                    "crm_contact_id": "48213"
                  },
                  "has_recording": false,
                  "analysis": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/calls/{call_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallId"
        }
      ],
      "get": {
        "operationId": "getCall",
        "tags": [
          "Calls"
        ],
        "summary": "Retrieve a call",
        "description": "Returns the call with its analysis (summary, outcome, sentiment) once the analysis is ready.",
        "x-scopes": [
          "calls:read"
        ],
        "responses": {
          "200": {
            "description": "The call.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Call"
                },
                "example": {
                  "object": "call",
                  "id": "3c27f11c-8a1e-4d55-9b0e-1f4c2a7d9e10",
                  "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "direction": "outbound",
                  "channel": "phone",
                  "status": "completed",
                  "from": "+4721000000",
                  "to": "+4712345678",
                  "started_at": "2026-10-12T10:04:12.000Z",
                  "ended_at": "2026-10-12T10:07:33.000Z",
                  "duration_seconds": 201,
                  "end_reason": "caller_hangup",
                  "metadata": {
                    "crm_contact_id": "48213"
                  },
                  "has_recording": true,
                  "analysis": {
                    "summary": "The caller booked a check-up on Tuesday 14 October at 12:00.",
                    "outcome": "resolved",
                    "sentiment": "positive",
                    "action_items": [
                      "Send booking confirmation by SMS"
                    ],
                    "created_at": "2026-10-12T10:07:51.000Z"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/calls/{call_id}/transcript": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallId"
        }
      ],
      "get": {
        "operationId": "getCallTranscript",
        "tags": [
          "Calls"
        ],
        "summary": "Retrieve a call transcript",
        "description": "Every line spoken on the call, in order.",
        "x-scopes": [
          "calls:read"
        ],
        "responses": {
          "200": {
            "description": "The transcript.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "call_id",
                    "data"
                  ],
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "transcript"
                    },
                    "call_id": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TranscriptEntry"
                      }
                    }
                  }
                },
                "example": {
                  "object": "transcript",
                  "call_id": "3c27f11c-8a1e-4d55-9b0e-1f4c2a7d9e10",
                  "data": [
                    {
                      "index": 0,
                      "role": "agent",
                      "text": "Hei, du har kommet til Nordvik Tannklinikk. Hva kan jeg hjelpe deg med?"
                    },
                    {
                      "index": 1,
                      "role": "caller",
                      "text": "Jeg vil gjerne bestille en time til kontroll."
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/phone-numbers": {
      "get": {
        "operationId": "listPhoneNumbers",
        "tags": [
          "Phone numbers"
        ],
        "summary": "List phone numbers",
        "x-scopes": [
          "numbers:read"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of phone numbers.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PhoneNumber"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page follows this one."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
                    }
                  }
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "phone_number",
                      "id": "b8f2a1c4-3d5e-4f60-8a71-92b3c4d5e6f7",
                      "number": "+4721000000",
                      "label": "Main line",
                      "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                      "status": "active",
                      "capabilities": [
                        "voice"
                      ],
                      "created_at": "2026-09-02T08:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    },
    "/phone-numbers/{phone_number_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/PhoneNumberId"
        }
      ],
      "get": {
        "operationId": "getPhoneNumber",
        "tags": [
          "Phone numbers"
        ],
        "summary": "Retrieve a phone number",
        "x-scopes": [
          "numbers:read"
        ],
        "responses": {
          "200": {
            "description": "The phone number.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneNumber"
                },
                "example": {
                  "object": "phone_number",
                  "id": "b8f2a1c4-3d5e-4f60-8a71-92b3c4d5e6f7",
                  "number": "+4721000000",
                  "label": "Main line",
                  "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "status": "active",
                  "capabilities": [
                    "voice"
                  ],
                  "created_at": "2026-09-02T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "operationId": "updatePhoneNumber",
        "tags": [
          "Phone numbers"
        ],
        "summary": "Assign an agent to a phone number",
        "description": "Sets which agent answers calls to this number. Send `null` to leave the number without an agent.",
        "x-scopes": [
          "numbers:write"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhoneNumberUpdate"
              },
              "example": {
                "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated number.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneNumber"
                },
                "example": {
                  "object": "phone_number",
                  "id": "b8f2a1c4-3d5e-4f60-8a71-92b3c4d5e6f7",
                  "number": "+4721000000",
                  "label": "Main line",
                  "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                  "status": "active",
                  "capabilities": [
                    "voice"
                  ],
                  "created_at": "2026-09-02T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/webhooks": {
      "get": {
        "operationId": "listWebhooks",
        "tags": [
          "Webhooks"
        ],
        "summary": "List webhook endpoints",
        "x-scopes": [
          "webhooks:read"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of endpoints.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookEndpoint"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page follows this one."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
                    }
                  }
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "webhook_endpoint",
                      "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
                      "url": "https://example.com/voximate/webhooks",
                      "events": [
                        "call.completed",
                        "call.failed"
                      ],
                      "status": "active",
                      "description": "CRM sync",
                      "created_at": "2026-10-13T08:00:00.000Z",
                      "updated_at": "2026-10-13T08:00:00.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      },
      "post": {
        "operationId": "createWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Create a webhook endpoint",
        "description": "Registers a URL that receives the events you choose. The response carries the signing `secret` **once** — store it, you need it to verify each delivery. The URL must be public `https`.",
        "x-scopes": [
          "webhooks:write"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              },
              "example": {
                "url": "https://example.com/voximate/webhooks",
                "events": [
                  "call.completed",
                  "call.failed"
                ],
                "description": "CRM sync"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The new endpoint, with its signing secret.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
                  "url": "https://example.com/voximate/webhooks",
                  "events": [
                    "call.completed",
                    "call.failed"
                  ],
                  "status": "active",
                  "description": "CRM sync",
                  "created_at": "2026-10-13T08:00:00.000Z",
                  "updated_at": "2026-10-13T08:00:00.000Z",
                  "secret": "whsec_6b1d0f8e2a4c47b9a3e5d7f1c9b2a4e6"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      }
    },
    "/webhooks/{webhook_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "getWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Retrieve a webhook endpoint",
        "x-scopes": [
          "webhooks:read"
        ],
        "responses": {
          "200": {
            "description": "The endpoint.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
                  "url": "https://example.com/voximate/webhooks",
                  "events": [
                    "call.completed",
                    "call.failed"
                  ],
                  "status": "active",
                  "description": "CRM sync",
                  "created_at": "2026-10-13T08:00:00.000Z",
                  "updated_at": "2026-10-13T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "patch": {
        "operationId": "updateWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Update a webhook endpoint",
        "description": "Change the URL, the events, the description, or pause and resume deliveries.",
        "x-scopes": [
          "webhooks:write"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              },
              "example": {
                "status": "paused"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The updated endpoint.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
                  "url": "https://example.com/voximate/webhooks",
                  "events": [
                    "call.completed",
                    "call.failed"
                  ],
                  "status": "paused",
                  "description": "CRM sync",
                  "created_at": "2026-10-13T08:00:00.000Z",
                  "updated_at": "2026-10-13T08:00:00.000Z"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        }
      },
      "delete": {
        "operationId": "deleteWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Delete a webhook endpoint",
        "description": "Stops all deliveries to the endpoint and deletes its signing secret.",
        "x-scopes": [
          "webhooks:write"
        ],
        "responses": {
          "200": {
            "description": "The endpoint was deleted.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Deleted"
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
                  "deleted": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/webhooks/{webhook_id}/test": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "testWebhook",
        "tags": [
          "Webhooks"
        ],
        "summary": "Send a test event",
        "description": "Sends a signed `webhook.test` event to the endpoint right now and reports what your server answered. Use it to check your signature verification before real calls arrive.",
        "x-scopes": [
          "webhooks:write"
        ],
        "responses": {
          "200": {
            "description": "What your endpoint answered.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTestResult"
                },
                "example": {
                  "object": "webhook_test",
                  "delivered": true,
                  "response_status": 200,
                  "error": null,
                  "duration_ms": 184
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/webhooks/{webhook_id}/rotate-secret": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "post": {
        "operationId": "rotateWebhookSecret",
        "tags": [
          "Webhooks"
        ],
        "summary": "Rotate the signing secret",
        "description": "Replaces the signing secret and returns the new one once. Deliveries are signed with the new secret from the next event.",
        "x-scopes": [
          "webhooks:write"
        ],
        "responses": {
          "200": {
            "description": "The endpoint with its new secret.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookEndpoint"
                },
                "example": {
                  "object": "webhook_endpoint",
                  "id": "d1e2f3a4-b5c6-4d7e-8f90-a1b2c3d4e5f6",
                  "url": "https://example.com/voximate/webhooks",
                  "events": [
                    "call.completed",
                    "call.failed"
                  ],
                  "status": "active",
                  "description": "CRM sync",
                  "created_at": "2026-10-13T08:00:00.000Z",
                  "updated_at": "2026-10-13T08:00:00.000Z",
                  "secret": "whsec_0e9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/webhooks/{webhook_id}/deliveries": {
      "parameters": [
        {
          "$ref": "#/components/parameters/WebhookId"
        }
      ],
      "get": {
        "operationId": "listWebhookDeliveries",
        "tags": [
          "Webhooks"
        ],
        "summary": "List deliveries",
        "description": "Recent delivery attempts to this endpoint, newest first, with the status code your server answered.",
        "x-scopes": [
          "webhooks:read"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "A page of deliveries.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "object",
                    "data",
                    "has_more",
                    "next_cursor"
                  ],
                  "properties": {
                    "object": {
                      "type": "string",
                      "const": "list"
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/WebhookDelivery"
                      }
                    },
                    "has_more": {
                      "type": "boolean",
                      "description": "True when another page follows this one."
                    },
                    "next_cursor": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Pass as `cursor` to fetch the next page. `null` on the last page."
                    }
                  }
                },
                "example": {
                  "object": "list",
                  "data": [
                    {
                      "object": "webhook_delivery",
                      "id": "a9b8c7d6-e5f4-4a3b-9c2d-1e0f9a8b7c6d",
                      "event_type": "call.completed",
                      "status": "delivered",
                      "response_status": 200,
                      "attempts": 1,
                      "error": null,
                      "created_at": "2026-10-12T10:07:52.000Z",
                      "delivered_at": "2026-10-12T10:07:52.000Z"
                    }
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/usage": {
      "get": {
        "operationId": "getUsage",
        "tags": [
          "Usage"
        ],
        "summary": "Retrieve usage",
        "description": "Calls and minutes for a period. Defaults to the last 30 days.",
        "x-scopes": [
          "analytics:read"
        ],
        "parameters": [
          {
            "name": "start",
            "in": "query",
            "description": "Start of the period (ISO 8601). Default: 30 days ago.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "end",
            "in": "query",
            "description": "End of the period (ISO 8601). Default: now.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Usage for the period.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/RequestId"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Usage"
                },
                "example": {
                  "object": "usage",
                  "period": {
                    "start": "2026-09-13T00:00:00.000Z",
                    "end": "2026-10-13T00:00:00.000Z"
                  },
                  "calls": 281,
                  "minutes": 577,
                  "average_duration_seconds": 126,
                  "outcomes": {
                    "resolved": 190,
                    "escalated": 12,
                    "abandoned": 21,
                    "transferred": 9,
                    "unknown": 49
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          }
        }
      }
    }
  },
  "webhooks": {
    "call.started": {
      "post": {
        "operationId": "eventCallStarted",
        "summary": "call.started",
        "description": "A call was answered and the agent is on the line.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_5f0c2b9a7d3e4c1f8a6b2d9e0c4f7a13",
                "object": "event",
                "type": "call.started",
                "api_version": "v1",
                "created_at": "2026-10-12T10:07:51.000Z",
                "data": {
                  "object": {
                    "object": "call",
                    "id": "3c27f11c-8a1e-4d55-9b0e-1f4c2a7d9e10",
                    "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                    "direction": "outbound",
                    "channel": "phone",
                    "status": "in_progress",
                    "from": "+4721000000",
                    "to": "+4712345678",
                    "started_at": "2026-10-12T10:04:12.000Z",
                    "ended_at": null,
                    "duration_seconds": null,
                    "end_reason": null,
                    "metadata": {
                      "crm_contact_id": "48213"
                    },
                    "has_recording": false,
                    "analysis": null
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Answer any 2xx within 10 seconds to acknowledge the event."
          }
        }
      }
    },
    "call.completed": {
      "post": {
        "operationId": "eventCallCompleted",
        "summary": "call.completed",
        "description": "A call has ended and its analysis is ready. `data.object` is the call, with `analysis` filled in.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_5f0c2b9a7d3e4c1f8a6b2d9e0c4f7a13",
                "object": "event",
                "type": "call.completed",
                "api_version": "v1",
                "created_at": "2026-10-12T10:07:51.000Z",
                "data": {
                  "object": {
                    "object": "call",
                    "id": "3c27f11c-8a1e-4d55-9b0e-1f4c2a7d9e10",
                    "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                    "direction": "outbound",
                    "channel": "phone",
                    "status": "completed",
                    "from": "+4721000000",
                    "to": "+4712345678",
                    "started_at": "2026-10-12T10:04:12.000Z",
                    "ended_at": "2026-10-12T10:07:33.000Z",
                    "duration_seconds": 201,
                    "end_reason": "caller_hangup",
                    "metadata": {
                      "crm_contact_id": "48213"
                    },
                    "has_recording": true,
                    "analysis": {
                      "summary": "The caller booked a check-up on Tuesday 14 October at 12:00.",
                      "outcome": "resolved",
                      "sentiment": "positive",
                      "action_items": [
                        "Send booking confirmation by SMS"
                      ],
                      "created_at": "2026-10-12T10:07:51.000Z"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Answer any 2xx within 10 seconds to acknowledge the event."
          }
        }
      }
    },
    "call.failed": {
      "post": {
        "operationId": "eventCallFailed",
        "summary": "call.failed",
        "description": "A call out was never connected. `data.reason` says why: `no_answer` (it rang out or was declined), `busy`, or `not_connected` (the number or the network refused it). Sent once per call.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_5f0c2b9a7d3e4c1f8a6b2d9e0c4f7a13",
                "object": "event",
                "type": "call.failed",
                "api_version": "v1",
                "created_at": "2026-10-12T10:07:51.000Z",
                "data": {
                  "object": {
                    "object": "call",
                    "id": "3c27f11c-8a1e-4d55-9b0e-1f4c2a7d9e10",
                    "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                    "direction": "outbound",
                    "channel": "phone",
                    "status": "failed",
                    "from": "+4721000000",
                    "to": "+4712345678",
                    "started_at": "2026-10-12T10:04:12.000Z",
                    "ended_at": "2026-10-12T10:07:33.000Z",
                    "duration_seconds": 0,
                    "end_reason": "caller_hangup",
                    "metadata": {
                      "crm_contact_id": "48213"
                    },
                    "has_recording": false,
                    "analysis": null
                  },
                  "reason": "no_answer"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Answer any 2xx within 10 seconds to acknowledge the event."
          }
        }
      }
    },
    "call.transferred": {
      "post": {
        "operationId": "eventCallTransferred",
        "summary": "call.transferred",
        "description": "The agent transferred the caller to a person or another number.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_5f0c2b9a7d3e4c1f8a6b2d9e0c4f7a13",
                "object": "event",
                "type": "call.transferred",
                "api_version": "v1",
                "created_at": "2026-10-12T10:07:51.000Z",
                "data": {
                  "object": {
                    "object": "call",
                    "id": "3c27f11c-8a1e-4d55-9b0e-1f4c2a7d9e10",
                    "agent_id": "7c3f1e90-5a44-4b21-9c07-2ed5b8f41a66",
                    "direction": "outbound",
                    "channel": "phone",
                    "status": "in_progress",
                    "from": "+4721000000",
                    "to": "+4712345678",
                    "started_at": "2026-10-12T10:04:12.000Z",
                    "ended_at": "2026-10-12T10:07:33.000Z",
                    "duration_seconds": 201,
                    "end_reason": "caller_hangup",
                    "metadata": {
                      "crm_contact_id": "48213"
                    },
                    "has_recording": true,
                    "analysis": null
                  },
                  "transferred_to": "+4712345670"
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Answer any 2xx within 10 seconds to acknowledge the event."
          }
        }
      }
    },
    "webhook.test": {
      "post": {
        "operationId": "eventWebhookTest",
        "summary": "webhook.test",
        "description": "Sent by \"Send test event\" in the dashboard and by `POST /webhooks/{webhook_id}/test`.",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/Event"
              },
              "example": {
                "id": "evt_0d1c2b3a4f5e6d7c8b9a0f1e2d3c4b5a",
                "object": "event",
                "type": "webhook.test",
                "api_version": "v1",
                "created_at": "2026-10-13T08:01:00.000Z",
                "data": {
                  "message": "This is a test event from Voximate."
                }
              }
            }
          }
        },
        "responses": {
          "2XX": {
            "description": "Answer any 2xx within 10 seconds to acknowledge the event."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "vox_live_…",
        "description": "Create a key in the dashboard under Settings → API keys and send it as `Authorization: Bearer vox_live_…`. A key acts with the role of the person who created it and only reaches what its scopes allow."
      }
    },
    "headers": {
      "RequestId": {
        "description": "Unique id of this request. Quote it when you contact support.",
        "schema": {
          "type": "string"
        }
      }
    },
    "parameters": {
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "How many items to return, 1 to 100.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "description": "The `next_cursor` from the previous page.",
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "description": "Any unique string (a UUID is ideal). Retrying a request with the same key within 24 hours returns the first answer instead of doing the work again.",
        "schema": {
          "type": "string",
          "maxLength": 255
        }
      },
      "AgentId": {
        "name": "agent_id",
        "in": "path",
        "required": true,
        "description": "The agent id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "CallId": {
        "name": "call_id",
        "in": "path",
        "required": true,
        "description": "The call id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "PhoneNumberId": {
        "name": "phone_number_id",
        "in": "path",
        "required": true,
        "description": "The phone number id (not the number itself).",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "WebhookId": {
        "name": "webhook_id",
        "in": "path",
        "required": true,
        "description": "The webhook endpoint id.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request is malformed: a missing field, a wrong type, an unknown parameter or an id that is not a UUID.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "parameter_invalid",
                "message": "`to` must be a phone number in E.164 format, for example +4712345678.",
                "param": "to"
              },
              "request_id": "req_8f14e45fceea167a"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "No API key, or the key is invalid, expired or revoked.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "authentication_error",
                "code": "api_key_invalid",
                "message": "Invalid, expired or revoked API key.",
                "param": null
              },
              "request_id": "req_8f14e45fceea167a"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key is valid but lacks the scope this operation needs (`missing_scope`), or — for adding, changing, testing or removing a webhook endpoint — was not made by a workspace owner or admin (`role_required`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "permission_error",
                "code": "missing_scope",
                "message": "This API key needs the calls:write scope.",
                "param": null
              },
              "request_id": "req_8f14e45fceea167a"
            }
          }
        }
      },
      "NotFound": {
        "description": "Nothing with that id exists in your workspace.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "not_found_error",
                "code": "resource_missing",
                "message": "No agent with that id.",
                "param": "agent_id"
              },
              "request_id": "req_8f14e45fceea167a"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "A Voximate service did not answer (`upstream_unavailable`); retrying is safe. On `POST /calls` the code is `call_outcome_unknown` instead: the call may already be ringing, so look for it with `GET /calls` before trying again with a new Idempotency-Key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "api_error",
                "code": "call_outcome_unknown",
                "message": "We could not confirm whether the call started, and it may already be ringing. Look for it with GET /calls before trying again; a new attempt needs a new Idempotency-Key.",
                "param": null
              },
              "request_id": "req_8f14e45fceea167a"
            }
          }
        }
      },
      "Conflict": {
        "description": "The Idempotency-Key was already used with a different request, or that request is still running.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "idempotency_error",
                "code": "idempotency_key_reused",
                "message": "This Idempotency-Key was used with a different request.",
                "param": null
              },
              "request_id": "req_8f14e45fceea167a"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "The request is well-formed but cannot be carried out in the current state.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "invalid_request_error",
                "code": "agent_not_published",
                "message": "The agent must be published before it can place calls.",
                "param": "agent_id"
              },
              "request_id": "req_8f14e45fceea167a"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests, or too many calls started in a short time. Wait the number of seconds in the Retry-After header.",
        "headers": {
          "Retry-After": {
            "description": "Seconds to wait before retrying.",
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "error": {
                "type": "rate_limit_error",
                "code": "call_rate_limited",
                "message": "Too many outbound calls in the last minute. Try again shortly.",
                "param": null
              },
              "request_id": "req_8f14e45fceea167a"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "request_id"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "code",
              "message",
              "param"
            ],
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "invalid_request_error",
                  "authentication_error",
                  "permission_error",
                  "not_found_error",
                  "idempotency_error",
                  "rate_limit_error",
                  "api_error"
                ],
                "description": "The broad category. Branch on this."
              },
              "code": {
                "type": "string",
                "description": "A stable, specific code, for example `missing_scope`."
              },
              "message": {
                "type": "string",
                "description": "A human-readable explanation. Wording may change."
              },
              "param": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "The parameter the error is about, when there is one."
              }
            }
          },
          "request_id": {
            "type": "string",
            "description": "Same as the `X-Request-Id` header."
          }
        }
      },
      "Deleted": {
        "type": "object",
        "required": [
          "object",
          "id",
          "deleted"
        ],
        "properties": {
          "object": {
            "type": "string"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "deleted": {
            "type": "boolean",
            "const": true
          }
        }
      },
      "ApiKeyInfo": {
        "type": "object",
        "required": [
          "object",
          "id",
          "workspace_id",
          "workspace_name",
          "scopes"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "api_key"
          },
          "id": {
            "type": "string",
            "format": "uuid",
            "description": "The key id (never the secret)."
          },
          "workspace_id": {
            "type": "string",
            "format": "uuid",
            "description": "Your workspace."
          },
          "workspace_name": {
            "type": [
              "string",
              "null"
            ],
            "description": "The workspace name shown in the dashboard; null if it could not be read just now."
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "What the key may do, for example `calls:write`."
          }
        }
      },
      "Agent": {
        "type": "object",
        "required": [
          "object",
          "id",
          "name",
          "description",
          "status",
          "language",
          "system_prompt",
          "first_message",
          "outbound_first_message",
          "voice",
          "llm",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "agent"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "published",
              "unpublished",
              "archived"
            ],
            "description": "Only a `published` agent answers phone calls and can place outbound calls."
          },
          "language": {
            "type": [
              "string",
              "null"
            ],
            "description": "BCP 47 tag, for example `nb-NO` or `en-US`."
          },
          "system_prompt": {
            "type": [
              "string",
              "null"
            ],
            "description": "The instructions the agent follows on every call."
          },
          "first_message": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the agent says when it picks up."
          },
          "outbound_first_message": {
            "type": [
              "string",
              "null"
            ],
            "description": "What the agent says first on calls it makes. When `null`, those calls open with `first_message`. A call can set its own with `first_message` on `POST /calls`."
          },
          "voice": {
            "type": "object",
            "required": [
              "provider",
              "voice_id"
            ],
            "properties": {
              "provider": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "voice_id": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "llm": {
            "type": "object",
            "required": [
              "provider",
              "model"
            ],
            "properties": {
              "provider": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "model": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "AgentCreate": {
        "type": "object",
        "required": [
          "name"
        ],
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": "string",
            "maxLength": 1000
          },
          "language": {
            "type": "string",
            "description": "BCP 47 tag. Default `nb-NO`.",
            "maxLength": 20
          },
          "system_prompt": {
            "type": "string",
            "maxLength": 50000
          },
          "first_message": {
            "type": "string",
            "maxLength": 500
          },
          "outbound_first_message": {
            "type": "string",
            "maxLength": 500,
            "description": "What it says first on calls it makes."
          },
          "voice_id": {
            "type": "string",
            "description": "A voice id from the dashboard voice picker.",
            "maxLength": 200
          }
        }
      },
      "AgentUpdate": {
        "type": "object",
        "minProperties": 1,
        "additionalProperties": false,
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 1000
          },
          "language": {
            "type": "string",
            "maxLength": 20
          },
          "system_prompt": {
            "type": "string",
            "maxLength": 50000
          },
          "first_message": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500
          },
          "outbound_first_message": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500,
            "description": "`null` removes it."
          },
          "voice_id": {
            "type": "string",
            "maxLength": 200
          }
        }
      },
      "Call": {
        "type": "object",
        "required": [
          "object",
          "id",
          "agent_id",
          "direction",
          "channel",
          "status",
          "from",
          "to",
          "started_at",
          "ended_at",
          "duration_seconds",
          "end_reason",
          "metadata",
          "has_recording",
          "analysis"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "call"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "agent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ]
          },
          "channel": {
            "type": "string",
            "enum": [
              "phone",
              "web"
            ],
            "description": "`phone` for calls over the phone network, `web` for browser and widget calls."
          },
          "status": {
            "type": "string",
            "enum": [
              "queued",
              "ringing",
              "in_progress",
              "completed",
              "failed",
              "no_answer",
              "busy",
              "canceled"
            ]
          },
          "from": {
            "type": [
              "string",
              "null"
            ],
            "description": "The calling number (E.164), when known."
          },
          "to": {
            "type": [
              "string",
              "null"
            ],
            "description": "The called number (E.164), when known."
          },
          "started_at": {
            "type": "string",
            "format": "date-time"
          },
          "ended_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "duration_seconds": {
            "type": [
              "integer",
              "null"
            ]
          },
          "end_reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Why the call ended, for example `caller_hangup`."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            },
            "description": "The `metadata` you sent when you started the call."
          },
          "has_recording": {
            "type": [
              "boolean",
              "null"
            ],
            "description": "Whether a recording exists. `null` in lists, where it is not looked up."
          },
          "analysis": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/CallAnalysis"
              },
              {
                "type": "null"
              }
            ],
            "description": "Filled in shortly after the call ends. Always `null` in lists."
          }
        }
      },
      "CallAnalysis": {
        "type": "object",
        "required": [
          "summary",
          "outcome",
          "sentiment",
          "action_items",
          "created_at"
        ],
        "properties": {
          "summary": {
            "type": "string"
          },
          "outcome": {
            "type": [
              "string",
              "null"
            ],
            "description": "For example `resolved`, `escalated`, `abandoned`."
          },
          "sentiment": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "positive",
              "neutral",
              "negative",
              null
            ]
          },
          "action_items": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "CallCreate": {
        "type": "object",
        "required": [
          "agent_id",
          "to"
        ],
        "additionalProperties": false,
        "properties": {
          "agent_id": {
            "type": "string",
            "format": "uuid",
            "description": "A published agent."
          },
          "to": {
            "type": "string",
            "pattern": "^\\+[1-9]\\d{6,14}$",
            "description": "The number to call, E.164."
          },
          "from": {
            "type": "string",
            "pattern": "^\\+[1-9]\\d{6,14}$",
            "description": "One of your numbers, E.164. Optional when the agent has exactly one number assigned; required when it has several."
          },
          "metadata": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "maxLength": 500
            },
            "maxProperties": 20,
            "description": "Up to 20 string values, returned on the call and in its webhooks. Use it for your own ids."
          },
          "ring_timeout_seconds": {
            "type": "integer",
            "minimum": 10,
            "maximum": 120,
            "description": "How long to let it ring before the call counts as not answered. Default 30."
          },
          "first_message": {
            "type": "string",
            "maxLength": 500,
            "description": "What the agent says first on this call, instead of its own greeting. Send an empty string to have the agent wait for the person to speak first. Left out: the agent's `outbound_first_message`, or its `first_message` when it has none."
          }
        }
      },
      "TranscriptEntry": {
        "type": "object",
        "required": [
          "index",
          "role",
          "text"
        ],
        "properties": {
          "index": {
            "type": "integer"
          },
          "role": {
            "type": "string",
            "enum": [
              "agent",
              "caller"
            ]
          },
          "text": {
            "type": "string"
          }
        }
      },
      "PhoneNumber": {
        "type": "object",
        "required": [
          "object",
          "id",
          "number",
          "label",
          "agent_id",
          "status",
          "capabilities",
          "created_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "phone_number"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "number": {
            "type": "string",
            "description": "E.164."
          },
          "label": {
            "type": [
              "string",
              "null"
            ]
          },
          "agent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid",
            "description": "The agent that answers it, or `null`."
          },
          "status": {
            "type": "string"
          },
          "capabilities": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "PhoneNumberUpdate": {
        "type": "object",
        "required": [
          "agent_id"
        ],
        "additionalProperties": false,
        "properties": {
          "agent_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          }
        }
      },
      "WebhookEndpoint": {
        "type": "object",
        "required": [
          "object",
          "id",
          "url",
          "events",
          "status",
          "description",
          "created_at",
          "updated_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "webhook_endpoint"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventType"
            }
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "disabled"
            ]
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "secret": {
            "type": [
              "string",
              "null"
            ],
            "description": "The signing secret. Returned only when the endpoint is created and when the secret is rotated. An `Idempotency-Key` replay of the create answers `null` here: the secret is kept only in the vault, never with the stored answer. Rotate it if it was lost."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookCreate": {
        "type": "object",
        "required": [
          "url",
          "events"
        ],
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "A public https URL."
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/EventType"
            }
          },
          "description": {
            "type": "string",
            "maxLength": 500
          }
        }
      },
      "WebhookUpdate": {
        "type": "object",
        "minProperties": 1,
        "additionalProperties": false,
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true,
            "items": {
              "$ref": "#/components/schemas/EventType"
            }
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 500
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused"
            ]
          }
        }
      },
      "WebhookTestResult": {
        "type": "object",
        "required": [
          "object",
          "delivered",
          "response_status",
          "error",
          "duration_ms"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "webhook_test"
          },
          "delivered": {
            "type": "boolean",
            "description": "True when your endpoint answered 2xx."
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "duration_ms": {
            "type": "integer"
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "required": [
          "object",
          "id",
          "event_type",
          "status",
          "response_status",
          "attempts",
          "error",
          "created_at",
          "delivered_at"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "webhook_delivery"
          },
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "event_type": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "delivered",
              "failed",
              "pending"
            ]
          },
          "response_status": {
            "type": [
              "integer",
              "null"
            ]
          },
          "attempts": {
            "type": "integer"
          },
          "error": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "delivered_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Usage": {
        "type": "object",
        "required": [
          "object",
          "period",
          "calls",
          "minutes",
          "average_duration_seconds",
          "outcomes"
        ],
        "properties": {
          "object": {
            "type": "string",
            "const": "usage"
          },
          "period": {
            "type": "object",
            "required": [
              "start",
              "end"
            ],
            "properties": {
              "start": {
                "type": "string",
                "format": "date-time"
              },
              "end": {
                "type": "string",
                "format": "date-time"
              }
            }
          },
          "calls": {
            "type": "integer"
          },
          "minutes": {
            "type": "integer",
            "description": "Call minutes in the period, rounded."
          },
          "average_duration_seconds": {
            "type": "integer"
          },
          "outcomes": {
            "type": "object",
            "additionalProperties": {
              "type": "integer"
            },
            "description": "Calls per outcome from each call’s AI analysis (resolved, escalated, abandoned, transferred, unknown). Calls without an analysis yet are not counted, so the total can be below `calls`."
          }
        }
      },
      "EventType": {
        "type": "string",
        "enum": [
          "call.started",
          "call.completed",
          "call.failed",
          "call.transferred"
        ],
        "description": "`webhook.test` is sent only by the test button and needs no subscription."
      },
      "Event": {
        "type": "object",
        "required": [
          "id",
          "object",
          "type",
          "api_version",
          "created_at",
          "data"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Unique per event. The same event retried keeps its id: use it to drop duplicates."
          },
          "object": {
            "type": "string",
            "const": "event"
          },
          "type": {
            "type": "string"
          },
          "api_version": {
            "type": "string",
            "const": "v1"
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object",
            "description": "For call events, `data.object` is the call."
          }
        }
      }
    }
  }
}