{
  "openapi": "3.0.3",
  "info": {
    "title": "TelAPI — selected HTTP operations",
    "version": "0.9.17-patch1",
    "description": "Selected operations from the stored 0.9.17-patch1 WebRTC snapshot. Incomplete API reference; not a fresh export or a declaration of compatibility with other releases."
  },
  "paths": {
    "/api/v1/sessions/token": {
      "post": {
        "summary": "Request a session token",
        "tags": [
          "Sessions"
        ],
        "description": "Issues a runtime session id and a short-lived WebSocket token for the requested SDK mode.\n\nAfter this call, connect the browser SDK to:\n  /ws/session?sessionId={sessionId}&token={wsToken}\n\nWebSocket wire format:\n- Messages use the ChannelMessage envelope (see components.schemas.ChannelMessage).\n- The server sends an initial status message with state=connected.\n\nWebSocket close codes:\n- 4001 — missing sessionId or token\n- 4003 — invalid token or expired session\n- 4000 — superseded by a newer connection\n- 4500 — internal server error\n\nAuthentication: requires a team API key with CREATE_CALL_TOKEN scope.\n\nvoice_conversation responses also include WebRTC gateway metadata (telproDomain, webrtcGatewayUrl).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "endpointId",
                  "mode"
                ],
                "properties": {
                  "endpointId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Endpoint to open a session against. It must belong to the API key team.",
                    "example": "0f6c3d4e-8b8f-4c59-9d0e-7e5e3b1f7f0f"
                  },
                  "mode": {
                    "type": "string",
                    "enum": [
                      "text",
                      "audio_playback",
                      "voice_conversation",
                      "browser_actions",
                      "listen"
                    ],
                    "description": "Session mode to provision: text chat, browser TTS playback, WebRTC voice, browser action dispatch, or interpretation listening."
                  }
                }
              },
              "examples": {
                "request_text_capability": {
                  "summary": "Request a text session",
                  "value": {
                    "endpointId": "0f6c3d4e-8b8f-4c59-9d0e-7e5e3b1f7f0f",
                    "mode": "text"
                  }
                },
                "request_audio_playback_capability": {
                  "summary": "Request an audio playback session",
                  "value": {
                    "endpointId": "0f6c3d4e-8b8f-4c59-9d0e-7e5e3b1f7f0f",
                    "mode": "audio_playback"
                  }
                },
                "request_voice_capability": {
                  "summary": "Request a voice conversation session",
                  "value": {
                    "endpointId": "0f6c3d4e-8b8f-4c59-9d0e-7e5e3b1f7f0f",
                    "mode": "voice_conversation"
                  }
                },
                "request_browser_actions_capability": {
                  "summary": "Request a browser actions session",
                  "value": {
                    "endpointId": "0f6c3d4e-8b8f-4c59-9d0e-7e5e3b1f7f0f",
                    "mode": "browser_actions"
                  }
                }
              }
            }
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "sessionId",
                    "wsToken",
                    "wsTokenExpiresIn",
                    "expiresIn"
                  ],
                  "properties": {
                    "sessionId": {
                      "type": "string",
                      "description": "The runtime session id (also the X-Call-ID for voice)"
                    },
                    "wsToken": {
                      "type": "string",
                      "description": "WebSocket token for /ws/session authentication"
                    },
                    "wsTokenExpiresIn": {
                      "type": "number",
                      "description": "WS token validity in seconds (5 min)"
                    },
                    "expiresIn": {
                      "type": "number",
                      "description": "Session token validity in seconds"
                    },
                    "telproDomain": {
                      "type": "string",
                      "description": "WebRTC gateway / TURN / STUN host (voice_conversation only)"
                    },
                    "webrtcGatewayUrl": {
                      "type": "string",
                      "description": "WebSocket URL of the WebRTC gateway (voice_conversation only)"
                    },
                    "traceId": {
                      "type": "string",
                      "description": "OpenTelemetry trace id returned for voice_conversation sessions."
                    },
                    "spanId": {
                      "type": "string",
                      "description": "OpenTelemetry root span id returned for voice_conversation sessions."
                    }
                  }
                },
                "examples": {
                  "example_text_capability": {
                    "summary": "Text session token",
                    "value": {
                      "sessionId": "call-loc5q7g0-k7p3f9x2",
                      "wsToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                      "wsTokenExpiresIn": 300,
                      "expiresIn": 3600
                    }
                  },
                  "example_voice_capability": {
                    "summary": "Voice conversation session token",
                    "value": {
                      "sessionId": "call-loc5q7g0-k7p3f9x2",
                      "wsToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                      "wsTokenExpiresIn": 300,
                      "expiresIn": 3600,
                      "telproDomain": "telpro.example.com",
                      "webrtcGatewayUrl": "wss://telpro.example.com",
                      "traceId": "4bf92f3577b34da6a3ce929d0e0e4736",
                      "spanId": "00f067aa0ba902b7"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Request validation failed",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "VALIDATION_ERROR",
                    "message": "Request validation failed"
                  }
                }
              }
            }
          },
          "401": {
            "description": "API key is missing or invalid",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "API key is missing or invalid",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "AUTHENTICATION_ERROR",
                    "message": "API key is missing or invalid"
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden: wrong team, origin/IP rejected, missing scope, or subscription limit reached",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Forbidden: wrong team, origin/IP rejected, missing scope, or subscription limit reached",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "FORBIDDEN",
                    "message": "Forbidden: wrong team, origin/IP rejected, missing scope, or subscription limit reached"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Endpoint not found",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Endpoint not found",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "NOT_FOUND",
                    "message": "Endpoint not found"
                  }
                }
              }
            }
          },
          "409": {
            "description": "Endpoint flow is not configured or not synced for the requested mode",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Endpoint flow is not configured or not synced for the requested mode",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "FLOW_NOT_CONFIGURED",
                    "message": "Endpoint flow is not configured or not synced for the requested mode"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Too many requests",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMIT_EXCEEDED",
                    "message": "Too many requests"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Unexpected server error",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "INTERNAL_ERROR",
                    "message": "Unexpected server error"
                  }
                }
              }
            }
          },
          "503": {
            "description": "voice_conversation requested but TelPro is not configured",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "voice_conversation requested but TelPro is not configured",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "TELPRO_UNCONFIGURED",
                    "message": "voice_conversation requested but TelPro is not configured"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/runtime/capabilities": {
      "get": {
        "summary": "Discover endpoint runtime capabilities",
        "tags": [
          "Runtime"
        ],
        "description": "Returns the interaction modes, transport preferences, flow entry points, and browser actions the SDK can use for an endpoint. Requires a team API key with CREATE_CALL_TOKEN scope.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "uuid"
            },
            "example": "0f6c3d4e-8b8f-4c59-9d0e-7e5e3b1f7f0f",
            "in": "query",
            "name": "endpointId",
            "required": true,
            "description": "Endpoint to inspect. Must belong to the API key team."
          }
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "endpointId",
                    "flowDefinitionId",
                    "runtime",
                    "interactionModes",
                    "transports",
                    "flows"
                  ],
                  "properties": {
                    "endpointId": {
                      "type": "string",
                      "format": "uuid"
                    },
                    "flowDefinitionId": {
                      "type": [
                        "null",
                        "string"
                      ],
                      "format": "uuid",
                      "description": "Active flow definition id, or null when the endpoint has no linked flow."
                    },
                    "runtime": {
                      "type": "object",
                      "required": [
                        "sessionContinuity",
                        "migration"
                      ],
                      "properties": {
                        "sessionContinuity": {
                          "type": "string",
                          "enum": [
                            "supported"
                          ]
                        },
                        "migration": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "text_to_voice",
                              "api_to_media"
                            ]
                          }
                        }
                      }
                    },
                    "interactionModes": {
                      "type": "object",
                      "required": [
                        "text",
                        "audio_playback",
                        "voice_conversation",
                        "browser_actions",
                        "listen"
                      ],
                      "properties": {
                        "text": {
                          "type": "boolean"
                        },
                        "audio_playback": {
                          "type": "boolean"
                        },
                        "voice_conversation": {
                          "type": "boolean"
                        },
                        "browser_actions": {
                          "type": "boolean"
                        },
                        "listen": {
                          "type": "boolean"
                        }
                      }
                    },
                    "transports": {
                      "type": "object",
                      "required": [
                        "preferred",
                        "available"
                      ],
                      "properties": {
                        "preferred": {
                          "type": "array",
                          "description": "Transports ordered by SDK preference.",
                          "items": {
                            "type": "string",
                            "enum": [
                              "rest",
                              "websocket",
                              "existing_media",
                              "webrtc"
                            ]
                          }
                        },
                        "available": {
                          "type": "array",
                          "description": "Every transport this endpoint can support.",
                          "items": {
                            "type": "string",
                            "enum": [
                              "rest",
                              "websocket",
                              "existing_media",
                              "webrtc"
                            ]
                          }
                        }
                      }
                    },
                    "flows": {
                      "type": "object",
                      "required": [
                        "entryPoints",
                        "responseModes",
                        "sideFlows",
                        "browserActions"
                      ],
                      "properties": {
                        "entryPoints": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "phone",
                              "web_voice",
                              "web_chat"
                            ]
                          }
                        },
                        "responseModes": {
                          "type": "array",
                          "items": {
                            "type": "string",
                            "enum": [
                              "audio_stream",
                              "text_stream",
                              "json",
                              "none"
                            ]
                          }
                        },
                        "sideFlows": {
                          "type": "array",
                          "description": "Advanced side flows that are not generated Browser-Originated Action capabilities.",
                          "items": {
                            "type": "object",
                            "required": [
                              "id",
                              "triggerType"
                            ],
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "name": {
                                "type": "string"
                              },
                              "triggerType": {
                                "type": "string"
                              },
                              "messageType": {
                                "type": "string",
                                "description": "WebSocket message type when triggerType is ws_message."
                              }
                            }
                          }
                        },
                        "browserActions": {
                          "type": "array",
                          "items": {
                            "type": "object",
                            "required": [
                              "id",
                              "slug",
                              "label",
                              "type",
                              "messageType",
                              "voiceInvocable"
                            ],
                            "properties": {
                              "id": {
                                "type": "string"
                              },
                              "slug": {
                                "type": "string"
                              },
                              "label": {
                                "type": "string"
                              },
                              "type": {
                                "type": "string"
                              },
                              "messageType": {
                                "type": "string"
                              },
                              "voiceInvocable": {
                                "type": "boolean"
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "endpointId": "0f6c3d4e-8b8f-4c59-9d0e-7e5e3b1f7f0f",
                  "flowDefinitionId": "7e0dca65-b70b-461e-9d12-c18e0ab6e626",
                  "runtime": {
                    "sessionContinuity": "supported",
                    "migration": [
                      "text_to_voice",
                      "api_to_media"
                    ]
                  },
                  "interactionModes": {
                    "text": true,
                    "audio_playback": true,
                    "voice_conversation": true,
                    "browser_actions": true,
                    "listen": true
                  },
                  "transports": {
                    "preferred": [
                      "rest",
                      "websocket",
                      "existing_media",
                      "webrtc"
                    ],
                    "available": [
                      "rest",
                      "websocket",
                      "existing_media",
                      "webrtc"
                    ]
                  },
                  "flows": {
                    "entryPoints": [
                      "web_chat",
                      "web_voice"
                    ],
                    "responseModes": [
                      "json",
                      "audio_stream"
                    ],
                    "sideFlows": [],
                    "browserActions": [
                      {
                        "id": "read-selection",
                        "slug": "read-selection",
                        "label": "Read aloud",
                        "type": "readAloud",
                        "messageType": "browser.action.readAloud",
                        "voiceInvocable": true
                      }
                    ]
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Request validation failed",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "VALIDATION_ERROR",
                    "message": "Request validation failed"
                  }
                }
              }
            }
          },
          "401": {
            "description": "API key is missing or invalid",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "API key is missing or invalid",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "AUTHENTICATION_ERROR",
                    "message": "API key is missing or invalid"
                  }
                }
              }
            }
          },
          "403": {
            "description": "API key lacks the required scope or resource access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "API key lacks the required scope or resource access",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "AUTHORIZATION_ERROR",
                    "message": "API key lacks the required scope or resource access"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Endpoint not found for this team",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Endpoint not found for this team",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "ENDPOINT_NOT_FOUND",
                    "message": "Endpoint not found for this team"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Too many requests",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMIT_EXCEEDED",
                    "message": "Too many requests"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Unexpected server error",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "INTERNAL_ERROR",
                    "message": "Unexpected server error"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/endpoints": {
      "get": {
        "summary": "List team endpoints",
        "tags": [
          "Endpoints"
        ],
        "description": "Returns all endpoints belonging to the team associated with the API key. Requires a team API key with READ_TEAM_APPS scope.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]*$",
              "default": "1"
            },
            "example": "1",
            "in": "query",
            "name": "page",
            "required": false,
            "description": "Page number (1-based)"
          },
          {
            "schema": {
              "type": "string",
              "pattern": "^[1-9][0-9]*$",
              "default": "20"
            },
            "example": "20",
            "in": "query",
            "name": "limit",
            "required": false,
            "description": "Items per page (max 100)"
          }
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "endpoints",
                    "pagination"
                  ],
                  "properties": {
                    "endpoints": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "required": [
                          "id",
                          "name"
                        ],
                        "properties": {
                          "id": {
                            "type": "string",
                            "format": "uuid",
                            "description": "Endpoint id to use with runtime/session APIs."
                          },
                          "name": {
                            "type": "string",
                            "description": "Endpoint display name."
                          }
                        }
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "required": [
                        "total",
                        "page",
                        "limit",
                        "totalPages"
                      ],
                      "properties": {
                        "total": {
                          "type": "number",
                          "description": "Total matching items."
                        },
                        "page": {
                          "type": "number",
                          "description": "Current 1-based page number."
                        },
                        "limit": {
                          "type": "number",
                          "description": "Items requested per page."
                        },
                        "totalPages": {
                          "type": "number",
                          "description": "Total pages available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "endpoints": [
                    {
                      "id": "0f6c3d4e-8b8f-4c59-9d0e-7e5e3b1f7f0f",
                      "name": "Website assistant"
                    }
                  ],
                  "pagination": {
                    "total": 1,
                    "page": 1,
                    "limit": 20,
                    "totalPages": 1
                  }
                }
              }
            }
          },
          "400": {
            "description": "Request validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Request validation failed",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "VALIDATION_ERROR",
                    "message": "Request validation failed"
                  }
                }
              }
            }
          },
          "401": {
            "description": "API key is missing or invalid",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "API key is missing or invalid",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "AUTHENTICATION_ERROR",
                    "message": "API key is missing or invalid"
                  }
                }
              }
            }
          },
          "403": {
            "description": "API key lacks the required scope or resource access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "API key lacks the required scope or resource access",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "AUTHORIZATION_ERROR",
                    "message": "API key lacks the required scope or resource access"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Too many requests",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMIT_EXCEEDED",
                    "message": "Too many requests"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Unexpected server error",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "INTERNAL_ERROR",
                    "message": "Unexpected server error"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/usage/tts-characters": {
      "get": {
        "summary": "Get total TTS character consumption for the calling team",
        "tags": [
          "Usage"
        ],
        "description": "Returns the aggregated TTS character ingestion (total, cached, generated, cache-hit ratio) for the team that owns the API key, within the requested [from, to] window. Apps that are excluded from the dashboard are not included in the aggregation. Requires a team API key with the READ_TEAM_USAGE scope.",
        "parameters": [
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "from",
            "required": false,
            "description": "Start of the report window (ISO 8601). Defaults to epoch if both from and to are omitted."
          },
          {
            "schema": {
              "type": "string",
              "format": "date-time"
            },
            "in": "query",
            "name": "to",
            "required": false,
            "description": "End of the report window (ISO 8601). Defaults to \"now\" if both from and to are omitted."
          },
          {
            "schema": {
              "type": "string",
              "enum": [
                "day",
                "week",
                "month",
                "total"
              ],
              "default": "total"
            },
            "in": "query",
            "name": "timeframe",
            "required": false,
            "description": "Timeframe label echoed in the response (does not change aggregation; informational)."
          }
        ],
        "security": [
          {
            "apiKey": []
          }
        ],
        "responses": {
          "200": {
            "description": "Default Response",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "teamId",
                    "timeframe",
                    "from",
                    "to",
                    "charactersTotal",
                    "charactersFromCache",
                    "charactersGenerated"
                  ],
                  "properties": {
                    "teamId": {
                      "type": "string",
                      "format": "uuid",
                      "description": "The team the API key belongs to."
                    },
                    "timeframe": {
                      "type": "string",
                      "enum": [
                        "day",
                        "week",
                        "month",
                        "total"
                      ]
                    },
                    "from": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Resolved start of the report window."
                    },
                    "to": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Resolved end of the report window."
                    },
                    "charactersTotal": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Total TTS characters synthesised in the window (cached + generated)."
                    },
                    "charactersFromCache": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "TTS characters served from the media cache."
                    },
                    "charactersGenerated": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "TTS characters generated by the upstream provider."
                    },
                    "cacheHitRatio": {
                      "type": "number",
                      "minimum": 0,
                      "maximum": 1,
                      "description": "charactersFromCache / charactersTotal, rounded to 4 decimal places. 0 when no characters were processed."
                    }
                  }
                },
                "example": {
                  "teamId": "5e2c1f04-6a3b-4d6f-8b1d-9c1b8b1b8b1b",
                  "timeframe": "total",
                  "from": "2026-06-01T00:00:00.000Z",
                  "to": "2026-07-01T00:00:00.000Z",
                  "charactersTotal": 12345,
                  "charactersFromCache": 4321,
                  "charactersGenerated": 8024,
                  "cacheHitRatio": 0.35
                }
              }
            }
          },
          "400": {
            "description": "Request validation failed",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Request validation failed",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "VALIDATION_ERROR",
                    "message": "Request validation failed"
                  }
                }
              }
            }
          },
          "401": {
            "description": "API key is missing or invalid",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "API key is missing or invalid",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "AUTHENTICATION_ERROR",
                    "message": "API key is missing or invalid"
                  }
                }
              }
            }
          },
          "403": {
            "description": "API key lacks the required scope or resource access",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "API key lacks the required scope or resource access",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "AUTHORIZATION_ERROR",
                    "message": "API key lacks the required scope or resource access"
                  }
                }
              }
            }
          },
          "429": {
            "description": "Too many requests",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Too many requests",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "RATE_LIMIT_EXCEEDED",
                    "message": "Too many requests"
                  }
                }
              }
            }
          },
          "500": {
            "description": "Unexpected server error",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "description": "Unexpected server error",
                  "required": [
                    "error"
                  ],
                  "properties": {
                    "error": {
                      "type": "object",
                      "required": [
                        "code",
                        "message"
                      ],
                      "properties": {
                        "code": {
                          "type": "string",
                          "description": "Stable machine-readable error code.",
                          "example": "VALIDATION_ERROR"
                        },
                        "message": {
                          "type": "string",
                          "description": "Human-readable error summary.",
                          "example": "Request validation failed"
                        },
                        "details": {
                          "description": "Optional structured details, usually validation issues."
                        },
                        "requestId": {
                          "type": "string",
                          "description": "Fastify request id for log correlation when available."
                        }
                      }
                    }
                  }
                },
                "example": {
                  "error": {
                    "code": "INTERNAL_ERROR",
                    "message": "Unexpected server error"
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ChannelMessage": {
        "type": "object",
        "description": "WebSocket message envelope exchanged on /ws/session. Include the payload object matching the message type.",
        "required": [
          "type",
          "sessionId",
          "messageId",
          "timestamp",
          "direction"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "chat",
              "browser_action",
              "action",
              "action_result",
              "audio",
              "status",
              "control",
              "reconnect",
              "ping",
              "pong",
              "error"
            ]
          },
          "sessionId": {
            "type": "string"
          },
          "messageId": {
            "type": "string",
            "format": "uuid"
          },
          "streamId": {
            "type": "string",
            "description": "Redis stream id included on replayed runtime-to-browser messages."
          },
          "timestamp": {
            "type": "number",
            "description": "Unix timestamp in milliseconds."
          },
          "direction": {
            "type": "string",
            "enum": [
              "to_browser",
              "to_ari"
            ]
          },
          "chat": {
            "type": "object",
            "description": "Present when type is chat.",
            "additionalProperties": true
          },
          "browserAction": {
            "type": "object",
            "description": "Present when type is browser_action.",
            "additionalProperties": true
          },
          "action": {
            "type": "object",
            "description": "Present when type is action.",
            "additionalProperties": true
          },
          "actionResult": {
            "type": "object",
            "description": "Present when type is action_result.",
            "additionalProperties": true
          },
          "audio": {
            "type": "object",
            "description": "Present when type is audio.",
            "additionalProperties": true
          },
          "status": {
            "type": "object",
            "description": "Present when type is status.",
            "additionalProperties": true
          },
          "control": {
            "type": "object",
            "description": "Present when type is control; supports enable_text_chat and disable_text_chat commands.",
            "additionalProperties": true
          },
          "reconnect": {
            "type": "object",
            "description": "Present when type is reconnect.",
            "additionalProperties": true
          },
          "error": {
            "type": "object",
            "description": "Present when type is error.",
            "additionalProperties": true
          }
        }
      }
    },
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "Team API key. Required scopes are documented on each authenticated endpoint."
      }
    }
  }
}
