{
  "openapi": "3.0.3",
  "info": {
    "title": "Drive Health operational API",
    "version": "1.0.0",
    "description": "Server-to-server API for organizations integrating with Drive Health. It starts chat and voice conversations and reads the calls, chats, transcripts, and recordings those conversations produce. Authenticate every request with an organization API key."
  },
  "servers": [
    {
      "url": "https://backend.drivehealth.ai",
      "description": "Production. Use the API origin supplied for your environment."
    }
  ],
  "tags": [
    {
      "name": "Chat",
      "description": "Start a chat with a caregiver, exchange messages, and end the session. These routes also answer on the compatibility mount `/v1/chat/...`."
    },
    {
      "name": "Voice",
      "description": "Start phone calls from an owned number and register browser voice calls."
    },
    {
      "name": "Results",
      "description": "Read the calls, chat sessions, transcripts, and recordings your organization owns."
    }
  ],
  "security": [
    { "organizationBearer": [] },
    { "organizationApiKey": [] }
  ],
  "paths": {
    "/api/v1/chat/create": {
      "post": {
        "operationId": "createChatSession",
        "summary": "Create a chat session",
        "description": "Start a chat with a caregiver. The caregiver must belong to your organization. The session it creates is owned by that same organization and appears in the chat results.",
        "tags": ["Chat"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChatCreateRequest" },
              "example": { "assistant_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The chat session was created.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatCreateResponse" },
                "example": {
                  "err": false,
                  "msg": "Success",
                  "results": { "chat_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f" }
                }
              }
            }
          },
          "400": {
            "description": "The caregiver is missing or is not in your organization.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "examples": {
                  "missingAssistant": {
                    "summary": "No assistant_id",
                    "value": { "err": true, "msg": "assistant_id is required" }
                  },
                  "unknownAssistant": {
                    "summary": "Caregiver not found",
                    "value": { "err": true, "msg": "Assistant not found" }
                  }
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/v1/chat/message": {
      "post": {
        "operationId": "sendChatMessage",
        "summary": "Send a message",
        "description": "Send a message to a chat session and wait for the caregiver's reply.",
        "tags": ["Chat"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChatMessageRequest" },
              "example": {
                "chat_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f",
                "message": "What time is my appointment?"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The caregiver's reply.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatReplyResponse" },
                "example": {
                  "err": false,
                  "msg": "Success",
                  "results": {
                    "response": "Your appointment is on Thursday at 2pm.",
                    "chat_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input, a chat session your organization does not own, or a model failure.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "examples": {
                  "missingMessage": {
                    "summary": "No message",
                    "value": { "err": true, "msg": "message is required" }
                  },
                  "unknownChat": {
                    "summary": "Chat session not found",
                    "value": { "err": true, "msg": "Chat session not found" }
                  },
                  "modelFailure": {
                    "summary": "Model failure",
                    "value": { "err": true, "msg": "LLM error" }
                  }
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/v1/chat/message/stream": {
      "post": {
        "operationId": "streamChatMessage",
        "summary": "Stream a reply",
        "description": "Send a message and receive the caregiver's reply as server-sent events, one JSON object per `data:` frame. The credential and the chat's ownership are checked before the stream opens, so a refused request gets an ordinary error response rather than a stream. Once the stream is open, only model failures appear inside it, as `{\"error\": \"LLM error\", \"chat_id\": \"...\"}` followed by the end of the stream. The transcript is written when the stream completes; a client that abandons the stream leaves the turn unrecorded.",
        "tags": ["Chat"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChatMessageRequest" },
              "example": {
                "chat_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f",
                "message": "What time is my appointment?"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A stream of reply chunks that ends with a `done` frame.",
            "content": {
              "text/event-stream": {
                "schema": { "type": "string" },
                "example": "data: {\"chunk\": \"Your appointment is \", \"chat_id\": \"9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f\"}\n\ndata: {\"chunk\": \"on Thursday at 2pm.\", \"chat_id\": \"9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f\"}\n\ndata: {\"done\": true, \"chat_id\": \"9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f\"}\n\n"
              }
            }
          },
          "400": {
            "description": "Invalid input or a chat session your organization does not own. Returned before any stream opens.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "example": { "err": true, "msg": "Chat session not found" }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/v1/chat/{chat_id}": {
      "get": {
        "operationId": "getChatSession",
        "summary": "Read a chat session",
        "description": "Read one chat session and its message history.",
        "tags": ["Chat"],
        "parameters": [
          {
            "name": "chat_id",
            "in": "path",
            "required": true,
            "description": "ID of a chat session your organization owns.",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "The chat session with its history.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatSessionResponse" },
                "example": {
                  "err": false,
                  "msg": "Success",
                  "results": {
                    "chat_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f",
                    "assistant_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                    "assistant_name": "Appointments",
                    "status": "active",
                    "user_message_count": 1,
                    "assistant_message_count": 2,
                    "history": [
                      { "role": "assistant", "content": "Hello, how can I help?" },
                      { "role": "user", "content": "What time is my appointment?" },
                      { "role": "assistant", "content": "Your appointment is on Thursday at 2pm." }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "The chat session was not found in your organization.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "example": { "err": true, "msg": "Chat session not found" }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/v1/chat/end": {
      "post": {
        "operationId": "endChatSession",
        "summary": "End a chat session",
        "description": "End a chat session. Ending marks the session; it does not erase it, and the transcript stays readable.",
        "tags": ["Chat"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChatEndRequest" },
              "example": { "chat_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f" }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The chat session was ended.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/MessageEnvelope" },
                "example": { "err": false, "msg": "Chat ended" }
              }
            }
          },
          "400": {
            "description": "Invalid input or a chat session your organization does not own.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "example": { "err": true, "msg": "Chat session not found" }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/calls/make-outbound": {
      "post": {
        "operationId": "startOutboundCall",
        "summary": "Start an outbound call",
        "description": "Start a phone call from a number your organization owns. The caregiver attached to that number runs the call. Use the returned `call_id` to read the result rather than guessing which row in the call list is yours. The call runs only when workspace balance, caregiver readiness, and the concurrency limit allow it; a refused call creates no record.",
        "tags": ["Voice"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/OutboundCallRequest" },
              "example": {
                "from_number": "+15551110000",
                "to_number": "+15552220000",
                "variables": [{ "var_name": "patient_name", "var_value": "Alex" }]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The call was initiated.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CallStartedResponse" },
                "example": {
                  "err": false,
                  "msg": "Call initiated successfully",
                  "results": { "call_id": "3c2b1a09-8f7e-4d6c-9b8a-7d6c5b4a3f2e" }
                }
              }
            }
          },
          "400": {
            "description": "The number is not owned by your organization, or a call precondition failed.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "examples": {
                  "unknownNumber": {
                    "summary": "Number not owned",
                    "value": { "err": true, "msg": "From number not found." }
                  },
                  "concurrency": {
                    "summary": "Over the concurrency limit",
                    "value": { "err": true, "msg": "Maximum concurrency limit reached." }
                  }
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/calls/web/register": {
      "post": {
        "operationId": "registerWebCall",
        "summary": "Register a web call",
        "description": "Register a browser voice call and receive a LiveKit token for it. The token joins the LiveKit room for that call and nothing else. Call this from your backend and return only the token and `call_id` to the browser, never the organization API key. The call runs only when workspace balance, caregiver readiness, and the concurrency limit allow it; a refused call creates no record.",
        "tags": ["Voice"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/WebCallRequest" },
              "example": { "assistant_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d", "variables": [] }
            }
          }
        },
        "responses": {
          "201": {
            "description": "The web call was registered.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/WebCallResponse" },
                "example": {
                  "err": false,
                  "msg": "Success",
                  "results": {
                    "call_id": "3c2b1a09-8f7e-4d6c-9b8a-7d6c5b4a3f2e",
                    "token": "eyJEXAMPLE.LIVEKIT.TOKEN"
                  }
                }
              }
            }
          },
          "400": {
            "description": "A call precondition failed.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "example": { "err": true, "msg": "Maximum concurrency limit reached." }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" },
          "412": {
            "description": "The caregiver was not found in your organization.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "example": { "err": true, "msg": "AI Assistant not found." }
              }
            }
          }
        }
      }
    },
    "/api/calls": {
      "get": {
        "operationId": "listCalls",
        "summary": "List calls",
        "description": "List calls owned by your organization. Filters narrow the list within your organization; they cannot reach past it.",
        "tags": ["Results"],
        "parameters": [
          { "$ref": "#/components/parameters/Page" },
          { "$ref": "#/components/parameters/Limit" },
          {
            "name": "status",
            "in": "query",
            "description": "Return only calls with this status, for example `completed`.",
            "schema": { "type": "string" }
          },
          { "$ref": "#/components/parameters/AssistantFilter" }
        ],
        "responses": {
          "200": {
            "description": "A page of calls. An empty `results` array is a successful response with no matching calls.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CallListPage" },
                "example": {
                  "count": 1,
                  "next": null,
                  "previous": null,
                  "results": [
                    {
                      "call_id": "3c2b1a09-8f7e-4d6c-9b8a-7d6c5b4a3f2e",
                      "protocol": "web",
                      "from_number": null,
                      "to_number": null,
                      "start_time": "2026-10-20T14:02:11Z",
                      "end_time": "2026-10-20T14:05:42Z",
                      "call_duration_seconds": 211,
                      "status": "completed",
                      "transcript": "Hello, how can I help?",
                      "transcript_object": null,
                      "sentiment": "neutral",
                      "who_hung_up": "caller",
                      "resolved": false,
                      "notes": null,
                      "call_analysis": null,
                      "call_recording_url": "https://backend.drivehealth.ai/api/calls/recording/3c2b1a09-8f7e-4d6c-9b8a-7d6c5b4a3f2e"
                    }
                  ]
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/calls/{call_id}": {
      "get": {
        "operationId": "getCall",
        "summary": "Get a call",
        "description": "Read one call your organization owns.",
        "tags": ["Results"],
        "parameters": [
          {
            "name": "call_id",
            "in": "path",
            "required": true,
            "description": "ID of a call your organization owns.",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "The call record.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/CallResponse" },
                "example": {
                  "err": false,
                  "msg": "Success",
                  "results": {
                    "call_id": "3c2b1a09-8f7e-4d6c-9b8a-7d6c5b4a3f2e",
                    "protocol": "web",
                    "status": "completed",
                    "call_duration_seconds": 211,
                    "resolved": false,
                    "call_recording_url": "https://backend.drivehealth.ai/api/calls/recording/3c2b1a09-8f7e-4d6c-9b8a-7d6c5b4a3f2e"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The call was not found in your organization.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "example": { "err": true, "msg": "Call record not found." }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/chats/sessions": {
      "get": {
        "operationId": "listChatSessions",
        "summary": "List chat sessions",
        "description": "List chat sessions owned by your organization. Filters narrow the list within your organization; they cannot reach past it.",
        "tags": ["Results"],
        "parameters": [
          { "$ref": "#/components/parameters/Page" },
          { "$ref": "#/components/parameters/Limit" },
          { "$ref": "#/components/parameters/AssistantFilter" }
        ],
        "responses": {
          "200": {
            "description": "A page of chat sessions.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatSessionListPage" },
                "example": {
                  "count": 1,
                  "next": null,
                  "previous": null,
                  "results": [
                    {
                      "chat_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f",
                      "assistant_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                      "assistant_name": "Appointments",
                      "status": "active",
                      "user_message_count": 1,
                      "assistant_message_count": 2,
                      "created_at": "2026-10-20T14:02:11Z",
                      "updated_at": "2026-10-20T14:03:05Z"
                    }
                  ]
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/chats/sessions/{chat_id}": {
      "get": {
        "operationId": "getChatResult",
        "summary": "Get a chat result",
        "description": "Read one chat session your organization owns, with its stored transcript.",
        "tags": ["Results"],
        "parameters": [
          {
            "name": "chat_id",
            "in": "path",
            "required": true,
            "description": "ID of a chat session your organization owns.",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "The chat session.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChatResultResponse" },
                "example": {
                  "err": false,
                  "msg": "Success",
                  "results": {
                    "chat_id": "9f8e7d6c-5b4a-4938-8271-6a5b4c3d2e1f",
                    "assistant_id": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
                    "assistant_name": "Appointments",
                    "status": "active",
                    "user_message_count": 1,
                    "assistant_message_count": 2,
                    "created_at": "2026-10-20T14:02:11Z",
                    "updated_at": "2026-10-20T14:03:05Z"
                  }
                }
              }
            }
          },
          "400": {
            "description": "The chat session was not found in your organization.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "example": { "err": true, "msg": "Chat session not found" }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    },
    "/api/calls/recording/{call_id}": {
      "get": {
        "operationId": "getCallRecording",
        "summary": "Download a recording",
        "description": "Download the recording of a call your organization owns. The `call_recording_url` on a call record already points here, on the current API host. The response is the audio itself: `audio/ogg` for recordings Drive Health stored and `audio/wav` for recordings fetched from the telephony provider, so read the `Content-Type` header. Fetch it from your backend; never place the organization key in a browser `audio` element or link.",
        "tags": ["Results"],
        "parameters": [
          {
            "name": "call_id",
            "in": "path",
            "required": true,
            "description": "ID of the call whose recording to download.",
            "schema": { "type": "string", "format": "uuid" }
          }
        ],
        "responses": {
          "200": {
            "description": "The recording audio.",
            "content": {
              "audio/ogg": {
                "schema": { "type": "string", "format": "binary" }
              },
              "audio/wav": {
                "schema": { "type": "string", "format": "binary" }
              }
            }
          },
          "400": {
            "description": "The call was not found in your organization, or it has no recording.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorEnvelope" },
                "examples": {
                  "unknownCall": {
                    "summary": "Call not found",
                    "value": { "err": true, "msg": "Call record not found." }
                  },
                  "recordingDisabled": {
                    "summary": "Recording disabled",
                    "value": { "err": true, "msg": "Call recording disabled." }
                  },
                  "noRecording": {
                    "summary": "No recording",
                    "value": { "err": true, "msg": "Recording not found." }
                  }
                }
              }
            }
          },
          "403": { "$ref": "#/components/responses/Refused" }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "organizationBearer": {
        "type": "http",
        "scheme": "bearer",
        "description": "An organization API key starting with `dh_`, sent as `Authorization: Bearer dh_your_api_key`."
      },
      "organizationApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Alternative to the Authorization header. Send one credential per request."
      }
    },
    "parameters": {
      "Page": {
        "name": "page",
        "in": "query",
        "description": "Page number, starting at 1.",
        "schema": { "type": "integer", "minimum": 1, "default": 1 }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "description": "Number of records per page.",
        "schema": { "type": "integer", "minimum": 1, "default": 10 }
      },
      "AssistantFilter": {
        "name": "assistant_id",
        "in": "query",
        "description": "Return only records for this caregiver.",
        "schema": { "type": "string", "format": "uuid" }
      }
    },
    "responses": {
      "Refused": {
        "description": "Refused before the endpoint ran, with `detail` instead of the standard envelope: the key is missing, invalid, or revoked; more than one credential was presented; or a selector names a different organization.",
        "content": {
          "application/json": {
            "schema": { "$ref": "#/components/schemas/Refusal" },
            "examples": {
              "invalidKey": {
                "summary": "Invalid or revoked key",
                "value": { "detail": "Unauthorized" }
              },
              "noCredential": {
                "summary": "No credential",
                "value": { "detail": "Authentication credentials were not provided." }
              },
              "conflictingCredentials": {
                "summary": "More than one credential",
                "value": {
                  "detail": "More than one credential was presented. Send an organization key or a session token, not both."
                }
              },
              "foreignSelector": {
                "summary": "Selector names another organization",
                "value": {
                  "detail": "This key belongs to a different organization than the request selected."
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "ErrorEnvelope": {
        "type": "object",
        "required": ["err", "msg"],
        "properties": {
          "err": { "type": "boolean", "example": true },
          "msg": { "type": "string", "description": "What went wrong." }
        }
      },
      "MessageEnvelope": {
        "type": "object",
        "required": ["err", "msg"],
        "properties": {
          "err": { "type": "boolean", "example": false },
          "msg": { "type": "string" }
        }
      },
      "Refusal": {
        "type": "object",
        "required": ["detail"],
        "properties": {
          "detail": { "type": "string", "description": "Why the request was refused." }
        }
      },
      "CallVariable": {
        "type": "object",
        "required": ["var_name", "var_value"],
        "properties": {
          "var_name": { "type": "string", "example": "patient_name" },
          "var_value": { "type": "string", "example": "Alex" }
        }
      },
      "ChatCreateRequest": {
        "type": "object",
        "required": ["assistant_id"],
        "properties": {
          "assistant_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the caregiver to chat with. It must belong to your organization."
          }
        }
      },
      "ChatMessageRequest": {
        "type": "object",
        "required": ["chat_id", "message"],
        "properties": {
          "chat_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of a chat session your organization owns."
          },
          "message": { "type": "string", "description": "The message to send." }
        }
      },
      "ChatEndRequest": {
        "type": "object",
        "required": ["chat_id"],
        "properties": {
          "chat_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of a chat session your organization owns."
          }
        }
      },
      "ChatCreateResponse": {
        "type": "object",
        "required": ["err", "msg", "results"],
        "properties": {
          "err": { "type": "boolean", "example": false },
          "msg": { "type": "string", "example": "Success" },
          "results": {
            "type": "object",
            "required": ["chat_id"],
            "properties": {
              "chat_id": { "type": "string", "format": "uuid", "description": "ID of the new chat session." }
            }
          }
        }
      },
      "ChatReplyResponse": {
        "type": "object",
        "required": ["err", "msg", "results"],
        "properties": {
          "err": { "type": "boolean", "example": false },
          "msg": { "type": "string", "example": "Success" },
          "results": {
            "type": "object",
            "required": ["response", "chat_id"],
            "properties": {
              "response": { "type": "string", "description": "The caregiver's reply." },
              "chat_id": { "type": "string", "format": "uuid" }
            }
          }
        }
      },
      "ChatHistoryEntry": {
        "type": "object",
        "properties": {
          "role": { "type": "string", "description": "Who wrote the turn, for example `user` or `assistant`." },
          "content": { "type": "string" }
        }
      },
      "ChatSession": {
        "type": "object",
        "description": "A chat session your organization owns. Records include further fields that this reference does not describe yet.",
        "additionalProperties": true,
        "properties": {
          "chat_id": { "type": "string", "format": "uuid" },
          "assistant_id": { "type": "string", "format": "uuid", "description": "The caregiver in the chat." },
          "assistant_name": { "type": "string" },
          "status": { "type": "string", "description": "Session status, for example `active`." },
          "user_message_count": { "type": "integer", "minimum": 0 },
          "assistant_message_count": { "type": "integer", "minimum": 0 },
          "transcript": { "type": "string", "nullable": true, "description": "The stored transcript as text." },
          "transcript_object": { "description": "The stored transcript as structured turns, or null." },
          "created_at": { "type": "string", "format": "date-time" },
          "updated_at": { "type": "string", "format": "date-time" }
        }
      },
      "ChatSessionWithHistory": {
        "allOf": [
          { "$ref": "#/components/schemas/ChatSession" },
          {
            "type": "object",
            "properties": {
              "history": {
                "type": "array",
                "description": "The conversation's turns in order.",
                "items": { "$ref": "#/components/schemas/ChatHistoryEntry" }
              }
            }
          }
        ]
      },
      "ChatSessionResponse": {
        "type": "object",
        "required": ["err", "msg", "results"],
        "properties": {
          "err": { "type": "boolean", "example": false },
          "msg": { "type": "string", "example": "Success" },
          "results": { "$ref": "#/components/schemas/ChatSessionWithHistory" }
        }
      },
      "ChatResultResponse": {
        "type": "object",
        "required": ["err", "msg", "results"],
        "properties": {
          "err": { "type": "boolean", "example": false },
          "msg": { "type": "string", "example": "Success" },
          "results": { "$ref": "#/components/schemas/ChatSession" }
        }
      },
      "ChatSessionListPage": {
        "type": "object",
        "required": ["count", "next", "previous", "results"],
        "properties": {
          "count": { "type": "integer", "minimum": 0, "description": "Total number of matching chat sessions." },
          "next": { "type": "string", "format": "uri", "nullable": true, "description": "Next page URL, or null." },
          "previous": { "type": "string", "format": "uri", "nullable": true, "description": "Previous page URL, or null." },
          "results": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/ChatSession" }
          }
        }
      },
      "OutboundCallRequest": {
        "type": "object",
        "required": ["from_number", "to_number"],
        "properties": {
          "from_number": {
            "type": "string",
            "description": "A phone number your organization owns. The caregiver attached to it runs the call.",
            "example": "+15551110000"
          },
          "to_number": {
            "type": "string",
            "description": "The phone number to call.",
            "example": "+15552220000"
          },
          "variables": {
            "type": "array",
            "description": "Values the caregiver can use during the call.",
            "items": { "$ref": "#/components/schemas/CallVariable" },
            "default": []
          }
        }
      },
      "WebCallRequest": {
        "type": "object",
        "required": ["assistant_id"],
        "properties": {
          "assistant_id": {
            "type": "string",
            "format": "uuid",
            "description": "ID of the caregiver to talk to. It must belong to your organization."
          },
          "variables": {
            "type": "array",
            "description": "Values the caregiver can use during the call.",
            "items": { "$ref": "#/components/schemas/CallVariable" },
            "default": []
          }
        }
      },
      "CallStartedResponse": {
        "type": "object",
        "required": ["err", "msg", "results"],
        "properties": {
          "err": { "type": "boolean", "example": false },
          "msg": { "type": "string", "example": "Call initiated successfully" },
          "results": {
            "type": "object",
            "required": ["call_id"],
            "properties": {
              "call_id": { "type": "string", "format": "uuid", "description": "ID of the new call." }
            }
          }
        }
      },
      "WebCallResponse": {
        "type": "object",
        "required": ["err", "msg", "results"],
        "properties": {
          "err": { "type": "boolean", "example": false },
          "msg": { "type": "string", "example": "Success" },
          "results": {
            "type": "object",
            "required": ["call_id", "token"],
            "properties": {
              "call_id": { "type": "string", "format": "uuid", "description": "ID of the new call." },
              "token": {
                "type": "string",
                "description": "Short-lived LiveKit token that joins this call's room and nothing else."
              }
            }
          }
        }
      },
      "CallRecord": {
        "type": "object",
        "description": "A call your organization owns. Records include further fields that this reference does not describe yet.",
        "additionalProperties": true,
        "properties": {
          "call_id": { "type": "string", "format": "uuid" },
          "protocol": {
            "type": "string",
            "description": "How the call was carried: `twilio`, `telnyx`, `web`, or `sip`."
          },
          "from_number": { "type": "string", "nullable": true, "description": "Calling number, when the call has one." },
          "to_number": { "type": "string", "nullable": true, "description": "Called number, when the call has one." },
          "start_time": { "type": "string", "format": "date-time", "nullable": true },
          "end_time": { "type": "string", "format": "date-time", "nullable": true },
          "call_duration_seconds": { "type": "integer", "minimum": 0, "nullable": true },
          "status": {
            "type": "string",
            "description": "Call status, for example `completed`, `failed`, `busy`, or `no-answer`."
          },
          "transcript": { "type": "string", "nullable": true, "description": "The conversation as text." },
          "transcript_object": { "description": "The conversation as structured turns, or null." },
          "sentiment": {
            "type": "string",
            "nullable": true,
            "description": "Sentiment from call analysis, for example `positive`, `neutral`, or `negative`."
          },
          "who_hung_up": {
            "type": "string",
            "nullable": true,
            "description": "Which side ended the call, for example `caller` or `callee`."
          },
          "resolved": { "type": "boolean", "description": "Whether the call is marked resolved." },
          "notes": { "type": "string", "nullable": true, "maxLength": 150 },
          "call_analysis": {
            "type": "object",
            "nullable": true,
            "additionalProperties": true,
            "description": "Analysis of the call. Its fields are not described yet."
          },
          "call_recording_url": {
            "type": "string",
            "format": "uri",
            "nullable": true,
            "description": "Authorized recording URL on the current API host. Fetch it with your organization key."
          }
        }
      },
      "CallResponse": {
        "type": "object",
        "required": ["err", "msg", "results"],
        "properties": {
          "err": { "type": "boolean", "example": false },
          "msg": { "type": "string", "example": "Success" },
          "results": { "$ref": "#/components/schemas/CallRecord" }
        }
      },
      "CallListPage": {
        "type": "object",
        "required": ["count", "next", "previous", "results"],
        "properties": {
          "count": { "type": "integer", "minimum": 0, "description": "Total number of matching calls." },
          "next": { "type": "string", "format": "uri", "nullable": true, "description": "Next page URL, or null." },
          "previous": { "type": "string", "format": "uri", "nullable": true, "description": "Previous page URL, or null." },
          "results": {
            "type": "array",
            "items": { "$ref": "#/components/schemas/CallRecord" }
          }
        }
      }
    }
  }
}
