# Leadlock API Reference Base URL: https://leadlock-app.onrender.com Auth: Bearer token (JWT) in Authorization header OpenAPI Version: 3.1.0 API Version: 0.1.0 --- ## Account ### GET /account/delete-request Get Deletion Request Status Return the most recent deletion request status for this tenant, or null. **Responses:** - \`200\`: Successful Response --- ### POST /account/delete-request Request Account Deletion Submit a GDPR/CCPA account deletion request. Only the account owner (not sub-account users) may request deletion. The request is captured and Leadlock is notified; Leadlock processes within the GDPR (1 month) / CCPA (45 days) SLA whichever is shorter. **Request Body:** \`DeletionRequestPayload\` (application/json) - reason: string | null **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Admin ### GET /admin/dashboard Get Admin Dashboard Get aggregated admin dashboard metrics from all external sources. **Responses:** - \`200\`: Successful Response Returns: \`AdminDashboardResponse\` --- ### GET /admin/issues List Issues List all issue reports (super admin only). **Parameters:** - \`resolved\` (query, ) — Filter by resolved status **Responses:** - \`200\`: Successful Response Returns: Array of \`IssueReportResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /admin/issues/{issue_id} Resolve Issue Resolve or unresolve an issue report. **Parameters:** - \`issue_id\` (path, string (required)) **Request Body:** \`IssueResolveRequest\` (application/json) - resolved: boolean (required) **Responses:** - \`200\`: Successful Response Returns: \`IssueReportResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /admin/rate-limits Get Rate Limit Status Get current voice API rate limit utilization per provider. **Responses:** - \`200\`: Successful Response --- ### POST /admin/rate-limits/check Trigger Quota Check Manually trigger a provider quota check (runs the scheduled job now). **Responses:** - \`200\`: Successful Response --- ### GET /admin/users List Users Get paginated list of users with analytics metrics. **Parameters:** - \`page\` (query, integer) — Page number - \`per_page\` (query, integer) — Items per page - \`search\` (query, ) — Search by email or name - \`sort_by\` (query, string) — Sort field - \`sort_order\` (query, string) — Sort order - \`plan\` (query, ) — Filter by plan - \`status\` (query, ) — Filter by health status **Responses:** - \`200\`: Successful Response Returns: \`PaginatedUsersResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /admin/users/analytics Get User Analytics Get aggregate user analytics (KPIs, charts, churn risk). **Responses:** - \`200\`: Successful Response Returns: \`UserAnalyticsAggregates\` --- ### POST /admin/users/create Create User Create a new user with email/password (super admin only). **Request Body:** \`CreateUserRequest\` (application/json) - email: string (required) - password: string (required) - plan: string [starter | pro | agency] (default: starter) - company_name: string | null **Responses:** - \`200\`: Successful Response Returns: \`CreateUserResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /admin/users/{user_id} Get User Detail Get detailed user information with full analytics. **Parameters:** - \`user_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`UserDetailResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /admin/users/{user_id}/status Update User Status Enable or disable a user account (super admin only). **Parameters:** - \`user_id\` (path, string (required)) **Request Body:** \`UpdateUserStatusRequest\` (application/json) - disabled: boolean (required) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Affiliates ### GET /affiliates/code Get Affiliate Code (Coming Soon) This feature is coming soon and is not yet available. **Responses:** - \`200\`: Successful Response Returns: \`AffiliateCodeResponse\` --- ### GET /affiliates/stats Get Affiliate Stats (Coming Soon) This feature is coming soon and is not yet available. **Responses:** - \`200\`: Successful Response Returns: \`AffiliateStatsResponse\` --- ## Agency ### GET /agency/agents List All Sub Account Agents List all agents across ALL sub-accounts. Used by agencies to view, filter, and manage agents across their entire portfolio. Returns agents enriched with sub-account name and phone count. **Responses:** - \`200\`: Successful Response Returns: \`AllSubAccountAgentsResponse\` --- ### POST /agency/agents/{agent_id}/copy Copy Agent Between Sub Accounts Copy an agent from one sub-account to another (agency-only). Verifies the agency owns both source and target sub-accounts. Creates a disabled copy with " (Copy)" suffix. Note: Returns the raw agent dict from the database insert, not AgentResponse. AgentResponse has computed fields (phone_count, text_assistants) that aren't present in the raw insert result. The frontend doesn't use this response body for rendering — it invalidates the query cache after a successful copy. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`CopyAgentToSubAccountRequest\` (application/json) - source_tenant_id: string (required) - target_tenant_id: string (required) **Responses:** - \`201\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agency/branding Get Branding Get branding settings. Works for both agencies (own settings) and sub-accounts (parent settings). **Responses:** - \`200\`: Successful Response Returns: \`BrandingSettings\` --- ### PATCH /agency/branding Update Branding Update branding settings. Only agencies can update branding. **Request Body:** \`UpdateBrandingRequest\` (application/json) - company_name: string | null - primary_color: string | null - support_email: string | null - support_url: string | null - custom_domain: string | null **Responses:** - \`200\`: Successful Response Returns: \`BrandingSettings\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agency/branding/favicon Upload Favicon Upload a favicon image. Accepts PNG, JPEG, SVG, or ICO. Maximum 5MB. **Request Body:** \`Body_upload_favicon_agency_branding_favicon_post\` (multipart/form-data) - file: string (required) **Responses:** - \`200\`: Successful Response Returns: \`LogoUploadResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agency/branding/logo Upload Logo Upload a logo image. Accepts PNG, JPEG, or SVG. Maximum 5MB. **Request Body:** \`Body_upload_logo_agency_branding_logo_post\` (multipart/form-data) - file: string (required) **Responses:** - \`200\`: Successful Response Returns: \`LogoUploadResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agency/functions List All Sub Account Functions List all custom functions across ALL sub-accounts. Used by agencies to select a function to copy/share to another sub-account. Returns functions with their source sub-account info. **Responses:** - \`200\`: Successful Response Returns: \`AllSubAccountFunctionsResponse\` --- ### GET /agency/integrations List Agency Integrations List ALL integrations owned by the agency (GHL, Twilio). Returns integrations available for assignment to sub-accounts. **Responses:** - \`200\`: Successful Response Returns: \`AgencyIntegrationsResponse\` --- ### GET /agency/my-integration Get My Integration Legacy Legacy endpoint - redirects to /my-integrations. Kept for backward compatibility. **Responses:** - \`200\`: Successful Response Returns: \`SubAccountIntegrationsResponse\` --- ### GET /agency/my-integrations Get My Integrations Get all integrations assigned to the current sub-account. Returns integrations assigned by the parent agency. **Responses:** - \`200\`: Successful Response Returns: \`SubAccountIntegrationsResponse\` --- ### GET /agency/overview Get Agency Overview Get agency dashboard overview stats. Includes aggregated metrics across all sub-accounts. **Responses:** - \`200\`: Successful Response Returns: \`AgencyOverview\` --- ### GET /agency/sub-accounts List Sub Accounts List all sub-accounts for the agency. Returns sub-accounts with billing info and usage stats. **Responses:** - \`200\`: Successful Response Returns: \`SubAccountListResponse\` --- ### POST /agency/sub-accounts Create Sub Account Create a new sub-account. Validates: - Agency has not exceeded sub_account_limit - Slug is globally unique **Request Body:** \`CreateSubAccountRequest\` (application/json) - name: string (required) - slug: string (required) - admin_email: string | null - admin_name: string | null - per_minute_rate_cents: integer (default: 20) - monthly_platform_fee_cents: integer (default: 0) - billing_start_day: integer (default: 1) - upcharge_by_provider: object | null - test_demo_upcharge_by_provider: object | null - text_upcharge_by_type: object | null **Responses:** - \`201\`: Successful Response Returns: \`SubAccountResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agency/sub-accounts/check-slug Check Slug Availability Check if a slug is available for use. Returns availability status without creating anything. Useful for real-time validation in the UI. **Request Body:** \`CheckSlugRequest\` (application/json) - slug: string (required) **Responses:** - \`200\`: Successful Response Returns: \`CheckSlugResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agency/sub-accounts/{sub_account_id} Get Sub Account Get a single sub-account with full details. **Parameters:** - \`sub_account_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`SubAccountResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /agency/sub-accounts/{sub_account_id} Update Sub Account Update a sub-account's settings. **Parameters:** - \`sub_account_id\` (path, string (required)) **Request Body:** \`UpdateSubAccountRequest\` (application/json) - name: string | null - admin_email: string | null - admin_name: string | null - per_minute_rate_cents: integer | null - monthly_platform_fee_cents: integer | null - is_active: boolean | null - billing_start_day: integer | null - upcharge_by_provider: object | null - test_demo_upcharge_by_provider: object | null - text_upcharge_by_type: object | null **Responses:** - \`200\`: Successful Response Returns: \`SubAccountResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /agency/sub-accounts/{sub_account_id} Delete Sub Account Soft-delete a sub-account (sets is_active=False). Historical data is preserved. **Parameters:** - \`sub_account_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agency/sub-accounts/{sub_account_id}/integrations Assign Integrations To Sub Account Assign multiple integrations to a sub-account. Rules: - Maximum 1 GHL integration per sub-account - Multiple Twilio/other integrations allowed - All integrations must belong to the parent agency **Parameters:** - \`sub_account_id\` (path, string (required)) **Request Body:** \`AssignIntegrationsRequest\` (application/json) - integration_ids: array (required) **Responses:** - \`200\`: Successful Response Returns: \`AssignIntegrationsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /agency/sub-accounts/{sub_account_id}/integrations Remove All Integrations From Sub Account Remove ALL integration assignments from a sub-account. **Parameters:** - \`sub_account_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /agency/sub-accounts/{sub_account_id}/integrations/{integration_id} Remove Integration From Sub Account Remove a specific integration from a sub-account. **Parameters:** - \`sub_account_id\` (path, string (required)) - \`integration_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`RemoveIntegrationResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agency/sub-accounts/{sub_account_id}/invite Send Sub Account Invite Send an invitation email to the sub-account admin. **Parameters:** - \`sub_account_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agency/sub-accounts/{sub_account_id}/usage Get Sub Account Usage Get usage records for a specific sub-account. **Parameters:** - \`sub_account_id\` (path, string (required)) - \`date_from\` (query, ) - \`date_to\` (query, ) - \`limit\` (query, integer) - \`offset\` (query, integer) **Responses:** - \`200\`: Successful Response Returns: \`UsageExportResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agency/usage Get All Usage Get usage records across all sub-accounts. **Parameters:** - \`date_from\` (query, ) - \`date_to\` (query, ) - \`limit\` (query, integer) - \`offset\` (query, integer) **Responses:** - \`200\`: Successful Response Returns: \`UsageExportResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agency/usage/export Export Usage Csv Export usage data as CSV. Returns a streaming response to handle large datasets efficiently. **Parameters:** - \`sub_account_id\` (query, ) - \`date_from\` (query, ) - \`date_to\` (query, ) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Agents ### GET /agents List Agents List all agents for the current tenant. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: returns their agents. **Responses:** - \`200\`: Successful Response Returns: \`AgentListResponse\` --- ### POST /agents Create Agent Create a new agent. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: creates agent under their tenant. Checks agent limit for the effective tenant. **Request Body:** \`AgentCreate\` (application/json) - name: string (required) - system_prompt: string (required) - greeting: string | null - greeting_outbound: string | null - voice: string (default: ara) - temperature: number (default: 0.7) - business_name: string | null - industry: string | null - ghl_phone_number: string | null - calendar_provider: string | null — Calendar provider: 'gohighlevel' - calendar_integration_id: string | null — Which GHL integration to use (for multi-account support) - calendar_id: string | null — Calendar ID from provider - tools_enabled: array | null — List of enabled tool names (e.g., ['end_call', 'book_appointment']) - timezone: string (default: America/New_York) — IANA timezone (e.g., America/New_York, America/Los_Angeles) - vad_threshold: number (default: 0.65) — VAD sensitivity (0.0-1.0, higher = less sensitive) - vad_silence_duration_ms: integer (default: 500) — Silence duration before ending turn (ms) - vad_prefix_padding_ms: integer (default: 300) — Audio capture before speech detection (ms) - enable_web_search: boolean (default: False) — Enable web search capability - enable_x_search: boolean (default: False) — Enable X (Twitter) search - x_search_handles: array | null — Allowed X handles for search (e.g., ['elonmusk', 'xai']) - enable_collections_search: boolean (default: False) — Enable document search from tenant knowledge base - knowledge_base_ids: array — Knowledge Base IDs this agent can search (when enable_collections_search=true) - enable_recording_disclosure: boolean (default: True) — Announce call recording at start of calls (required for two-party consent states) - enable_contact_intelligence: boolean (default: False) — Fetch caller context (GHL contact + call history) before answering - ai_speaks_first: boolean (default: True) — If true, AI greets caller immediately. If false, AI waits for caller to speak first. - ai_speaks_first_outbound: boolean (default: True) — If true, AI greets recipient immediately on outbound calls. - prompt_includes_contact_intelligence: boolean (default: False) — True if prompt includes Caller Intelligence section for using pre-call context - voice_provider: string (default: xai) — Voice provider: 'xai' (Grok), 'elevenlabs' (ElevenLabs), 'openai' (OpenAI), or 'gemini' (Gemini) - gemini_voice: string (default: Puck) — Gemini prebuilt voice name (30 options) - gemini_start_sensitivity: string (default: low) — Gemini start-of-speech sensitivity: low (ignores noise) or high (reacts to everything) - gemini_end_sensitivity: string (default: high) — Gemini end-of-speech sensitivity: low (patient, waits for clear silence) or high (quick cutoff). WARNING: LOW on 8kHz telephony audio causes 15-30s latency spikes. - gemini_thinking_level: string (default: none) — Gemini 3.1 thinking level: none (off, fastest), minimal (very light), low (basic reasoning), medium, high (most thorough, adds latency). - gemini_language_code: string | null — BCP-47 language code hint for Gemini speech (e.g., 'en-US', 'es-US', 'fr-FR'). None = auto-detect. - gemini_affective_dialog: boolean (default: False) — Enable emotion/tone awareness in Gemini responses (Preview feature) - gemini_proactive_audio: boolean (default: False) — Allow Gemini to stay silent when no clear request is made (Preview feature) - gemini_top_k: integer | null — Gemini top-K sampling: number of top tokens considered (1-100, None=model default) - gemini_top_p: number | null — Gemini top-P nucleus sampling threshold (0.0-1.0, None=model default) - openai_voice: string (default: alloy) — OpenAI voice ID (alloy, ash, ballad, coral, echo, sage, shimmer, verse) - openai_vad_type: string (default: semantic_vad) — OpenAI VAD type: semantic_vad (AI-based) or server_vad (volume-based) - openai_vad_eagerness: string (default: low) — OpenAI semantic VAD eagerness: low (patient) to high (responsive) - openai_noise_reduction: string (default: far_field) — OpenAI noise reduction: far_field (phone), near_field (mic), or disabled - elevenlabs_voice_id: string | null — ElevenLabs voice ID - elevenlabs_model_id: string (default: gpt-4o-mini) — LLM model ID for ElevenLabs agent (e.g., gpt-4o-mini, claude-3-haiku) - elevenlabs_speed: number (default: 1.0) — Speaking speed for ElevenLabs (0.7-1.2x) - elevenlabs_eagerness: string (default: normal) — Turn-taking eagerness for ElevenLabs: 'low', 'normal', or 'high' - elevenlabs_language: string (default: en) — Language code for ElevenLabs agent (e.g., 'en', 'es', 'fr') - elevenlabs_additional_languages: array — Additional language codes for multilingual support (e.g., ['es', 'fr']) - elevenlabs_stability: number (default: 0.5) — Voice stability for ElevenLabs (0.0=creative, 0.5=natural, 1.0=robust) - elevenlabs_max_duration_seconds: integer | null — Max call duration in seconds for ElevenLabs (None=unlimited, min 60) - elevenlabs_emotion_tags: array | null — Custom emotion tags for ElevenLabs: [{name, description}] - elevenlabs_tool_call_sound: string | null (default: typing) — Sound played during ElevenLabs tool execution: typing, elevator1-4, none - elevenlabs_pre_tool_speech: boolean | null (default: True) — Agent announces action before executing slow tools (ElevenLabs only) - xai_audio_tags: array | null — xAI audio delivery tags: ['[breath]', '[pause]', '', ...] - agent_mode: string (default: inbound) — How this agent handles calls: 'inbound', 'outbound', or 'both' - voice_enabled: boolean (default: True) — Enable voice/phone channel - text_enabled: boolean (default: False) — Enable text/SMS channel - amd_enabled: boolean (default: True) — Enable Twilio AMD for outbound calls ($0.01/call) - amd_voicemail_behavior: string (default: hangup) — Action when voicemail detected: hangup, static_message, dynamic_message, agent_decides - amd_voicemail_message: string | null — Message to leave on voicemail (supports {{variables}} for dynamic_message) - amd_voicemail_audio_url: string | null — Audio file URL to play as voicemail (alternative to TTS) - transfer_targets: array | null — Transfer targets: [{name, number, reason}] - whisper_enabled: boolean (default: False) — Enable AI-generated whisper summary when transferring calls - ghl_tags: array | null — Available tags for GHL add_tag/remove_tag: [{name}] - ghl_remove_tags: array | null — Tag rules for remove_tag: [{name, condition?}] - ghl_workflows: array | null — Available workflows for GHL trigger_workflow: [{id, name, description?}] - ghl_pipelines: array | null — Available pipelines for GHL opportunities: [{id, name, stages: [{id, name}]}] - sms_templates: array | null — SMS templates for send_sms: [{name, content}] - max_call_duration_minutes: integer (default: 30) — Max call duration in minutes (0=unlimited, max 180) - max_silence_seconds: integer (default: 120) — Max silence before ending call in seconds (0=unlimited, max 600) - calendar_configs: array | null — Calendar configurations: [{calendar_id, integration_id, label, provider}] - multi_calendar_behavior: string (default: ask_user) — Multi-calendar behavior: 'ask_user' (present options) or 'auto_first' (book first available) - variable_definitions: array | null — Template variables for prompt substitution: [{name, description?, required?, default_value?}] - tool_instructions: object | null — Per-tool usage instructions: {"tool_name": "instruction text"} - text_model: string (default: claude-haiku-4-5-20251001) — LLM model for text assistant (claude-haiku-4-5-20251001, claude-sonnet-4-6, claude-sonnet-4-5-20250929, claude-opus-4-6, gpt-5.2, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, gpt-4o, gpt-4o-mini) - channel_pivot_enabled: boolean (default: False) — Auto-send text when outbound call fails (no-answer, busy, voicemail) **Responses:** - \`201\`: Successful Response Returns: \`AgentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/share-links List Share Links List all active share links for the current tenant. **Responses:** - \`200\`: Successful Response Returns: Array of \`ShareLinkSummary\` --- ### POST /agents/test/chat Test Agent Chat Test agent in text mode. Uses xAI Chat Completions API with same Grok model as voice testing. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: tests their agent. **Request Body:** \`TestChatRequest\` (application/json) - agent_id: string (required) — Agent ID to test - messages: array (required) — Conversation history including new user message Items: ChatMessage **Responses:** - \`200\`: Successful Response Returns: \`TestChatResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/test/voice Test Agent Voice Test agent in voice mode. Uses xAI Realtime Voice API to process audio and return AI response. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: tests their agent. **Request Body:** \`TestVoiceRequest\` (application/json) - agent_id: string (required) — Agent ID to test - audio_base64: string (required) — Base64-encoded PCM16 audio at 24kHz **Responses:** - \`200\`: Successful Response Returns: \`TestVoiceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/wizard/defaults Get Wizard Defaults Get default settings for the agent wizard. Returns recommended settings for a receptionist agent. **Responses:** - \`200\`: Successful Response --- ### POST /agents/wizard/enhance-description Enhance Description Enhance a basic business description using AI. Takes a rough description and makes it more polished and professional while keeping it concise (under 50 words). **Request Body:** \`EnhanceDescriptionRequest\` (application/json) - business_name: string (required) - industry: string (required) - description: string (required) **Responses:** - \`200\`: Successful Response Returns: \`EnhanceDescriptionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/generate-all-knowledge Generate All Knowledge Endpoint Generate all knowledge sections at once. This is a convenience endpoint that generates services, pricing, team, and FAQs in a single call. Takes longer but provides everything needed for the agent prompt. **Request Body:** \`app__agents__prompt_router__GenerateAllKnowledgeRequest\` (application/json) - business_name: string (required) - industry: string (required) - description: string (default: ) — Business description for context - agent_mode: string (default: inbound) — Agent mode — outbound routes 'team' to objections generator **Responses:** - \`200\`: Successful Response Returns: \`GenerateAllKnowledgeResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/generate-expressive Generate Expressive Endpoint Generate expressive voice configuration using AI. Analyzes the agent's prompt and user preferences to generate: - Audio tags for ElevenLabs v3 expressive mode - Custom emotion tags with descriptions - A prompt section with tone/delivery guidance - The full updated prompt with the section merged in Supports presets, custom descriptions, and iterative refinement. **Request Body:** \`GenerateExpressiveRequest\` (application/json) - current_prompt: string (required) — The existing system prompt for context - preset: string | null — Preset style: empathetic_support, high_energy_sales, professional_service, friendly_fun - custom_description: string | null — Free-text description of desired emotional delivery - refinement: string | null — Refinement instruction for a previous result - previous_result: object | null — Previous AI output to refine **Responses:** - \`200\`: Successful Response Returns: \`GenerateExpressiveResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/generate-function-schema Generate Function Schema Endpoint Generate a custom function schema using AI. Takes a plain English description and generates: - Function name (snake_case) - Description for the AI to understand when to use it - JSON Schema for parameters - Recommended HTTP method (GET/POST) **Example:** ```json { "description": "Capture lead info: name, email, phone number" } ``` Returns a complete function definition ready for the custom function form. **Request Body:** \`GenerateFunctionSchemaRequest\` (application/json) - description: string (required) — Plain English description of what the function should do - webhook_purpose: string | null — Optional context about where the webhook sends data **Responses:** - \`200\`: Successful Response Returns: \`GenerateFunctionSchemaResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/generate-knowledge Generate Knowledge Generate AI suggestions for a specific knowledge section. This endpoint uses xAI to generate content for one section at a time, allowing users to iterate on each section individually. **Sections:** - `services`: Products and services offered - `pricing`: Pricing information - `team`: Team members and roles - `faqs`: Common questions and answers **Request Body:** \`app__agents__prompt_router__GenerateKnowledgeRequest\` (application/json) - business_name: string (required) - industry: string (required) - section: string (required) — Section to generate: services, pricing, team, or faqs - description: string (default: ) — Business description for context - services: string (default: ) — Existing services list (for pricing/faqs context) - agent_mode: string (default: inbound) — Agent mode — outbound routes 'team' to objections generator **Responses:** - \`200\`: Successful Response Returns: \`GenerateKnowledgeResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/import-website Import From Website Import business information from a website. This endpoint: 1. Scrapes the provided URL and discovers internal pages 2. Scrapes up to 8 key pages (about, services, pricing, team, faq) 3. Uses AI to extract business information from the combined content 4. Returns structured data ready for the wizard form **Request Body:** \`ImportWebsiteRequest\` (application/json) - url: string (required) — Website URL to scrape (e.g., https://example.com) **Responses:** - \`200\`: Successful Response Returns: \`ImportWebsiteResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/wizard/import-website-stream Import From Website Stream Import business information from a website with real-time progress streaming. Returns Server-Sent Events with progress updates: - progress: {step, current, total, detail} - result: {business_name, industry, ...} - error: {message} **Parameters:** - \`url\` (query, string (required)) — Website URL to scrape **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/wizard/industry-presets Get Industry Presets Get available industry presets. Returns a list of supported industries and their associated suggestions for services and FAQs. **Responses:** - \`200\`: Successful Response Returns: \`IndustryPresetsResponse\` --- ### POST /agents/wizard/preview-greeting-tts Preview Greeting Tts Generate a TTS audio preview of a greeting message. Calls the appropriate TTS provider API and streams back MP3 audio. xAI falls back to OpenAI TTS with voice "alloy" (no REST TTS available). **Request Body:** \`PreviewGreetingTTSRequest\` (application/json) - text: string (required) - voice_provider: string (required) - voice_id: string (required) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/preview-prompt Preview Prompt Preview the full generated prompt before creating the agent. This builds the complete receptionist prompt from the provided knowledge sections and returns it along with recommended settings. **Request Body:** \`PreviewPromptRequest\` (application/json) - business_name: string (required) - agent_name: string (default: Alex) - industry: string (default: ) - personality: string (default: friendly) - description: string (default: ) - services: string (default: ) - pricing: string (default: ) - team: string (default: ) - faqs: string (default: ) - product_offer: string (default: ) - qualification_criteria: string (default: ) - common_objections: string (default: ) - voice_provider: string (default: xai) - agent_type: string | null - sales_methodology: string | null - cta_type: string | null **Responses:** - \`200\`: Successful Response Returns: \`PreviewPromptResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/suggest-functions Suggest Functions Endpoint Get AI-powered function/tool suggestions for an agent. Analyzes industry, agent mode, and business description to recommend which tools to enable, with a reason for each suggestion. **Request Body:** \`SuggestFunctionsRequest\` (application/json) - industry: string (required) — Business industry - agent_mode: string (default: inbound) — Agent mode: inbound, outbound, or both - description: string (default: ) — Business description for context - has_ghl: boolean (default: False) — Whether GoHighLevel CRM is connected - system_prompt: string | null — Existing system prompt for deeper context **Responses:** - \`200\`: Successful Response Returns: \`SuggestFunctionsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/update-prompt Update Prompt Endpoint Update an existing system prompt using AI. Makes surgical modifications to the prompt based on the instruction, preserving the overall structure while adding/modifying specific parts. **Features:** - Preserves prompt structure - Converts negative instructions to positive framing - Adds anti-patterns to dedicated section - Optional: integrate custom functions documentation **Example:** ```json { "current_prompt": "You are a helpful assistant...", "instruction": "Add FAQ about return policy" } ``` **Request Body:** \`UpdatePromptRequest\` (application/json) - current_prompt: string (required) — The existing system prompt to modify - instruction: string (required) — Instructions for how to modify the prompt - functions: array — Optional: custom functions to integrate into the prompt Items: FunctionForUpdate - quick_action: string | null — Special action: 'integrate_functions' or 'condense' **Responses:** - \`200\`: Successful Response Returns: \`UpdatePromptResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/wizard/update-prompt-contact-intelligence Update Prompt Contact Intelligence Endpoint Update a system prompt to add or remove Contact Intelligence instructions. This endpoint helps users configure their agent prompts to leverage caller context data (name, company, previous calls, tags, etc.). **Actions:** - `add`: Injects a "## Caller Intelligence" section and updates greeting - `remove`: Removes the CI section and reverts greeting to generic **Example:** ```json { "current_prompt": "You are a helpful assistant...", "action": "add" } ``` **Request Body:** \`ContactIntelligencePromptRequest\` (application/json) - current_prompt: string (required) — The existing system prompt to modify - action: string (required) — Action to perform: 'add' to inject CI section, 'remove' to strip it **Responses:** - \`200\`: Successful Response Returns: \`UpdatePromptResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/{agent_id} Get Agent Get a specific agent by ID. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: returns their agent. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`AgentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /agents/{agent_id} Update Agent Update an agent. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: updates their agent. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`AgentUpdate\` (application/json) - name: string | null - system_prompt: string | null - greeting: string | null - greeting_outbound: string | null - voice: string | null - temperature: number | null - is_active: boolean | null - business_name: string | null - industry: string | null - ghl_phone_number: string | null - calendar_provider: string | null - calendar_integration_id: string | null - calendar_id: string | null - tools_enabled: array | null - timezone: string | null - vad_threshold: number | null - vad_silence_duration_ms: integer | null - vad_prefix_padding_ms: integer | null - enable_web_search: boolean | null - enable_x_search: boolean | null - x_search_handles: array | null - enable_collections_search: boolean | null - knowledge_base_ids: array | null - enable_recording_disclosure: boolean | null - enable_contact_intelligence: boolean | null - ai_speaks_first: boolean | null - ai_speaks_first_outbound: boolean | null - prompt_includes_contact_intelligence: boolean | null - voice_provider: string | null — Voice provider: 'xai' (Grok), 'elevenlabs' (ElevenLabs), 'openai' (OpenAI), or 'gemini' (Gemini) - gemini_voice: string | null - gemini_start_sensitivity: string | null - gemini_end_sensitivity: string | null - gemini_thinking_level: string | null - gemini_language_code: string | null - gemini_affective_dialog: boolean | null - gemini_proactive_audio: boolean | null - gemini_top_k: integer | null - gemini_top_p: number | null - openai_voice: string | null - openai_vad_type: string | null - openai_vad_eagerness: string | null - openai_noise_reduction: string | null - elevenlabs_voice_id: string | null - elevenlabs_model_id: string | null - elevenlabs_speed: number | null - elevenlabs_eagerness: string | null - elevenlabs_language: string | null - elevenlabs_additional_languages: array | null - elevenlabs_stability: number | null - elevenlabs_max_duration_seconds: integer | null - elevenlabs_emotion_tags: array | null - elevenlabs_tool_call_sound: string | null - elevenlabs_pre_tool_speech: boolean | null - xai_audio_tags: array | null - agent_mode: string | null — How this agent handles calls - voice_enabled: boolean | null - text_enabled: boolean | null - amd_enabled: boolean | null - amd_voicemail_behavior: string | null - amd_voicemail_message: string | null - amd_voicemail_audio_url: string | null - transfer_targets: array | null - whisper_enabled: boolean | null - ghl_tags: array | null - ghl_remove_tags: array | null - ghl_workflows: array | null - ghl_pipelines: array | null - sms_templates: array | null - max_call_duration_minutes: integer | null - max_silence_seconds: integer | null - calendar_configs: array | null - multi_calendar_behavior: string | null - variable_definitions: array | null - tool_instructions: object | null - text_model: string | null - channel_pivot_enabled: boolean | null **Responses:** - \`200\`: Successful Response Returns: \`AgentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /agents/{agent_id} Delete Agent Delete an agent. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: deletes their agent. Raises ValidationError if agent is linked to text assistants. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/copy-to/{target_tenant_id} Copy Agent To Sub Account Copy an agent to another sub-account (agency-only). Verifies the user's agency owns both source and target sub-accounts. Clears tenant-specific fields (calendars, knowledge bases). **Parameters:** - \`agent_id\` (path, string (required)) - \`target_tenant_id\` (path, string (required)) **Responses:** - \`201\`: Successful Response Returns: \`AgentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/duplicate Duplicate Agent Duplicate an agent within the same tenant. Creates a copy with " (Copy)" appended to name and is_active=False. ElevenLabs agent is re-synced if applicable. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`201\`: Successful Response Returns: \`AgentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/{agent_id}/functions List Agent Functions List functions attached to an agent plus available library functions. Returns two lists: - attached: Functions currently attached to this agent - available: Library functions not yet attached For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`AgentFunctionsListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/functions Create Custom Function Create a new custom function and attach it to this agent. Backward-compatible endpoint that creates in library and auto-attaches. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`CustomFunctionCreate\` (application/json) - name: string (required) — Function name in snake_case (e.g., check_inventory) - description: string (required) — Description of what the function does (shown to AI) - parameters: object — JSON Schema for function parameters - webhook_url: string (required) — Webhook URL to call (must start with http:// or https://) - webhook_method: string (default: POST) — HTTP method for webhook call - webhook_headers: object — Custom headers to include in webhook request - webhook_timeout_ms: integer (default: 5000) — Timeout for webhook call in milliseconds (1000-30000) - is_enabled: boolean (default: True) — Whether the function is enabled - speak_during_execution: boolean (default: True) — Whether AI should speak while waiting for webhook response **Responses:** - \`201\`: Successful Response Returns: \`CustomFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/functions/attach Attach Function To Agent Attach an existing library function to this agent. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`AttachFunctionRequest\` (application/json) - function_id: string (required) — ID of the function to attach - is_enabled: boolean (default: True) — Whether function is enabled for this agent **Responses:** - \`201\`: Successful Response Returns: \`AttachFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /agents/{agent_id}/functions/detach/{function_id} Detach Function From Agent Detach a function from this agent. The function remains in the library and can be re-attached later. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) - \`function_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/{agent_id}/functions/{function_id} Get Custom Function Get a specific custom function attached to this agent. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) - \`function_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`CustomFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PUT /agents/{agent_id}/functions/{function_id} Update Custom Function Update a custom function. - is_enabled changes only affect this agent - Other changes affect all agents using this function For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) - \`function_id\` (path, string (required)) **Request Body:** \`CustomFunctionUpdate\` (application/json) - name: string | null — Function name in snake_case - description: string | null — Description of what the function does - parameters: object | null — JSON Schema for function parameters - webhook_url: string | null — Webhook URL to call - webhook_method: string | null — HTTP method for webhook call - webhook_headers: object | null — Custom headers to include in webhook request - webhook_timeout_ms: integer | null — Timeout for webhook call in milliseconds - is_enabled: boolean | null — Whether the function is enabled - speak_during_execution: boolean | null — Whether AI should speak while waiting for webhook response **Responses:** - \`200\`: Successful Response Returns: \`CustomFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /agents/{agent_id}/functions/{function_id} Delete Custom Function Delete a custom function from the library. WARNING: This removes the function from ALL agents, not just this one. Use /detach to remove from only this agent. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) - \`function_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/functions/{function_id}/disable Disable Function For Agent Disable a function for this agent. The function remains attached but won't be used in voice calls. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) - \`function_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`AttachFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/functions/{function_id}/enable Enable Function For Agent Enable a function for this agent. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) - \`function_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`AttachFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/functions/{function_id}/test Test Custom Function Test a custom function by calling its webhook. Makes a real HTTP request to the webhook URL with test arguments. Returns timing information and the webhook response. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`agent_id\` (path, string (required)) - \`function_id\` (path, string (required)) **Request Body:** \`FunctionTestRequest\` (application/json) - arguments: object — Arguments to pass to the function - contact_id: string (default: test-contact-id) — GHL contact ID — always present via Contact Intelligence **Responses:** - \`200\`: Successful Response Returns: \`FunctionTestResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/{agent_id}/phone-numbers Get Agent Phone Numbers Get phone numbers assigned to an agent. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: returns phone numbers assigned to their agent. Note: Phone numbers may be owned by an agency (tenant_id = agency) but assigned to a sub-account (sub_account_id = sub_account). We need to handle both cases. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /agents/{agent_id}/share Get Share Link Get the active share link for an agent. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`CreateShareLinkResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/share Create Share Link Create a public share link for an agent. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`CreateShareLinkRequest\` (application/json) - custom_slug: string | null - expires_in_days: integer | null **Responses:** - \`200\`: Successful Response Returns: \`CreateShareLinkResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /agents/{agent_id}/share Revoke Share Link Revoke (deactivate) the share link for an agent. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /agents/{agent_id}/toggle Toggle Agent Toggle an agent's is_active status. Flips the current is_active value and returns the updated agent. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`AgentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Api ### GET /api/public/branding Get Branding By Domain Fetch public branding info for a custom domain. No auth required. **Parameters:** - \`domain\` (query, string (required)) — Custom domain to look up branding for **Responses:** - \`200\`: Successful Response Returns: \`PublicBrandingResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Appointments ### GET /appointments List Appointments List GHL calendar appointments for the current tenant. Returns appointments filtered by date range, calendar, and status. Cancelled and no-show appointments are excluded by default. **Parameters:** - \`date_from\` (query, ) — YYYY-MM-DD, default: today - \`date_to\` (query, ) — YYYY-MM-DD, default: +30 days - \`calendar_id\` (query, ) — Filter by calendar ID - \`status\` (query, ) — Filter by status - \`limit\` (query, integer) - \`offset\` (query, integer) - \`integration_id\` (query, ) — Specific GHL integration **Responses:** - \`200\`: Successful Response Returns: \`AppointmentsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /appointments/contact/{phone} List Appointments For Contact List GHL calendar appointments for a specific contact by phone number. The phone number can be in any format (+15551234567, 555-123-4567, etc.). Falls back to GHL contact search if phone is not directly on events. **Parameters:** - \`phone\` (path, string (required)) - \`date_from\` (query, ) — YYYY-MM-DD, default: today - \`date_to\` (query, ) — YYYY-MM-DD, default: +30 days - \`calendar_id\` (query, ) — Filter by calendar ID - \`status\` (query, ) — Filter by status - \`limit\` (query, integer) - \`offset\` (query, integer) - \`integration_id\` (query, ) — Specific GHL integration **Responses:** - \`200\`: Successful Response Returns: \`AppointmentsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Auth ### POST /auth/accept-invite Accept Invite Accept a sub-account invitation. Validates token inline and creates auth account if valid. Returns tokens for immediate login. Public endpoint - no auth required. Rate limited: 5 attempts per hour per IP address. **Request Body:** \`AcceptInviteRequest\` (application/json) - token: string (required) - password: string (required) — Minimum 6 characters (Supabase requirement) **Responses:** - \`200\`: Successful Response Returns: \`AuthResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /auth/api-keys List Api Keys List all API keys for the current tenant/sub-account. **Responses:** - \`200\`: Successful Response Returns: \`APIKeyListResponse\` --- ### POST /auth/api-keys Create Api Key Create a new API key for webhook authentication. Requires owner or admin role. Uses sub-account context so agency users create keys for the sub-account they're operating as. The plaintext key is only returned ONCE - store it securely! **Request Body:** \`APIKeyCreate\` (application/json) - name: string (default: Default API Key) - expires_in_days: integer | null **Responses:** - \`200\`: Successful Response Returns: \`APIKeyCreateResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /auth/api-keys/{key_id} Delete Api Key Delete an API key. Requires owner or admin role. **Parameters:** - \`key_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /auth/api-keys/{key_id}/revoke Revoke Api Key Revoke (deactivate) an API key without deleting it. Requires owner or admin role. **Parameters:** - \`key_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /auth/context Get Auth Context Return tenant context for frontend navigation. Returns: - tenant_type: 'agency' | 'sub_account' | 'direct' - current_tenant_id: UUID - parent_tenant_id: UUID | None (for sub-accounts) - available_sub_accounts: list (for agencies only) **Responses:** - \`200\`: Successful Response --- ### POST /auth/embed-sso Embed Sso Embedded SSO — authenticate via partner platform iframe integration. Accepts an encrypted payload from the partner postMessage protocol, decrypts it, maps the user to a Leadlock account, and returns JWT tokens for the session. Public endpoint - no auth required (SSO replaces login). **Request Body:** \`EmbedSSORequest\` (application/json) - payload: string (required) — Encrypted SSO payload from partner platform **Responses:** - \`200\`: Successful Response Returns: \`AuthResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /auth/forgot-password Forgot Password Send password reset email using Resend. Generates a secure token, stores hash in DB, sends email via Resend. This bypasses Supabase's email system for instant delivery. Public endpoint - no auth required. **Request Body:** \`ForgotPasswordRequest\` (application/json) - email: string (required) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /auth/login Login Login with email and password. Returns access token, refresh token, user, and tenant info. **Request Body:** \`LoginRequest\` (application/json) - email: string (required) - password: string (required) **Responses:** - \`200\`: Successful Response Returns: \`AuthResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /auth/logout Logout Logout user. Client should discard tokens. Server-side invalidation handled by Supabase. **Responses:** - \`200\`: Successful Response --- ### GET /auth/me Get Me Get current authenticated user and tenant info. Requires valid access token in Authorization header. **Responses:** - \`200\`: Successful Response Returns: \`MeResponse\` --- ### POST /auth/refresh Refresh Refresh access token using refresh token. **Request Body:** \`RefreshTokenRequest\` (application/json) - refresh_token: string (required) **Responses:** - \`200\`: Successful Response Returns: \`AuthResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /auth/reset-password Reset Password Reset password using our custom token. Verifies token from password_reset_tokens table, then updates the user's password via Supabase admin API. Public endpoint - no auth required. **Request Body:** \`ResetPasswordRequest\` (application/json) - token: string (required) — Password reset token from email link - new_password: string (required) — New password (minimum 6 characters) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /auth/signup Signup Create a new user account. Creates: - Supabase Auth user - Tenant record (direct or agency) - User record with 'owner' role Returns tokens for immediate login. **Request Body:** \`SignupRequest\` (application/json) - email: string (required) - password: string (required) — Minimum 6 characters (Supabase requirement) - company_name: string (required) - account_type: string [direct | agency] (default: direct) - tos_accepted: boolean (default: False) — User must accept Terms of Service and Privacy Policy **Responses:** - \`200\`: Successful Response Returns: \`AuthResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /auth/signup-pending Create Pending Signup Create a pending signup record and redirect to Stripe checkout. Payment-First flow: Account is NOT created until Stripe payment succeeds. Password is encrypted (not hashed) so it can be used to create the Supabase Auth user after payment. Public endpoint - no auth required. Rate limited by middleware: 5 requests per minute for /auth/* endpoints. **Request Body:** \`PendingSignupRequest\` (application/json) - email: string (required) - password: string (required) — Minimum 6 characters (Supabase requirement) - company_name: string (required) - plan: string [payg | starter | agency | pro] (default: starter) - billing_period: string [monthly | annual] (default: monthly) - tos_accepted: boolean (default: False) — User must accept Terms of Service and Privacy Policy - affiliate_code: string | null - utm_source: string | null - utm_medium: string | null - utm_campaign: string | null - utm_content: string | null - utm_term: string | null - referrer_url: string | null **Responses:** - \`200\`: Successful Response Returns: \`PendingSignupResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Billing ### GET /billing Get Subscription Status Get current subscription status and usage summary. **Responses:** - \`200\`: Successful Response Returns: \`SubscriptionStatus\` --- ### POST /billing/apply-coupon Apply Coupon Apply a promotion code to an existing subscription. Looks up the promotion code in Stripe, validates it's active, and applies the associated coupon to the subscription. **Request Body:** \`ApplyCouponRequest\` (application/json) - promotion_code: string (required) **Responses:** - \`200\`: Successful Response Returns: \`ApplyCouponResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /billing/checkout Create Checkout Session Create a Stripe Checkout session for subscription signup. Only tenant owner can initiate subscription. **Request Body:** \`CheckoutRequest\` (application/json) - plan: string (required) [payg | starter | agency | pro] - billing_period: string [monthly | annual] (default: monthly) - success_url: string | null - cancel_url: string | null **Responses:** - \`200\`: Successful Response Returns: \`CheckoutResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /billing/checkout-public Create Public Checkout Create Stripe checkout session for unauthenticated users (Stripe-first signup). Account will be created via webhook after payment succeeds. No authentication required - this is a public endpoint. **Request Body:** \`PublicCheckoutRequest\` (application/json) - email: string (required) - plan: string (required) [payg | starter | agency | pro] - billing_period: string [monthly | annual] (default: monthly) - affiliate_code: string | null **Responses:** - \`200\`: Successful Response Returns: \`CheckoutResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /billing/end-trial End Trial Early End trial immediately and start paid subscription. Converts a trial subscription to active by setting trial_end='now'. Stripe will immediately charge the customer's payment method. Only tenant owner can end trial. For sub-accounts, ends the parent agency's trial (sub-accounts share the agency's subscription and trial limits). **Responses:** - \`200\`: Successful Response Returns: \`EndTrialResponse\` --- ### GET /billing/invoices Get Invoices Get invoice history from Stripe. **Parameters:** - \`limit\` (query, integer) **Responses:** - \`200\`: Successful Response Returns: \`InvoiceListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /billing/invoices/upcoming Get Upcoming Invoice Get upcoming invoice preview. Shows what will be charged when trial ends or at next billing cycle. **Responses:** - \`200\`: Successful Response Returns: \`UpcomingInvoiceResponse\` --- ### GET /billing/limits Get Tier Limits Endpoint Get current tier limits and usage for the tenant. Returns current counts vs limits for agents, sub-accounts, team members, and share links, plus feature availability flags and voice rates. Respects sub-account context when X-Sub-Account-Id header is present. **Responses:** - \`200\`: Successful Response Returns: \`TierLimitsResponse\` --- ### GET /billing/my-billing Get My Billing Get sub-account's billing info and usage for current period. Sub-accounts don't have credit balances anymore (metered billing). Shows usage this period and confirms billing goes to parent agency. NOTE: Uses get_effective_tenant_id to support agency impersonation. When agency user is "Operating as Sub-Account", the X-Sub-Account-Id header is used to get the sub-account's billing info. **Responses:** - \`200\`: Successful Response Returns: \`SubAccountBillingResponse\` --- ### POST /billing/portal Create Portal Session Create a Stripe Customer Portal session with product filtering. Shows only relevant upgrade options based on current tier: - Starter: Agency/Pro upgrades - Agency: Pro upgrade only - Pro: White-Label addon Allows customer to manage subscription, payment methods, and view invoices. Only tenant owner can access portal. **Request Body:** \`PortalRequest\` (application/json) - return_url: string | null **Responses:** - \`200\`: Successful Response Returns: \`PortalResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /billing/trial Get Trial Status Endpoint Get current trial status including voice minutes used/remaining. Returns trial info if in trial, or is_trial=False if paid. Respects sub-account context when X-Sub-Account-Id header is present. **Responses:** - \`200\`: Successful Response Returns: \`TrialStatusResponse\` --- ### GET /billing/usage Get Usage Records Get usage records for the current billing period. **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) **Responses:** - \`200\`: Successful Response Returns: \`UsageListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Calls ### GET /calls List Calls List call logs for the tenant. Returns paginated call history with optional agent and direction filtering. Respects sub-account context when X-Sub-Account-Id header is present. **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) - \`agent_id\` (query, ) — Filter by agent - \`direction\` (query, ) — Filter by direction (inbound, outbound, test, demo) **Responses:** - \`200\`: Successful Response Returns: \`CallLogListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /calls/export Export Calls Export call logs as CSV. **Parameters:** - \`agent_id\` (query, ) — Filter by agent - \`status\` (query, ) — Filter by status - \`date_from\` (query, ) — Filter by start date - \`date_to\` (query, ) — Filter by end date - \`search\` (query, ) — Search term **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /calls/{call_id} Get Call Get details of a specific call. Respects sub-account context when X-Sub-Account-Id header is present. **Parameters:** - \`call_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`CallLogResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /calls/{call_id}/analyze Analyze Call Analyze a call transcript using AI. Returns insights about call outcome, summary, key moments, and actionable improvements. Uses xAI to analyze the transcript and provide coaching feedback. Respects sub-account context when X-Sub-Account-Id header is present. **Parameters:** - \`call_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /calls/{call_id}/recording Get Call Recording Stream recording audio for a specific call. Proxies the audio from Twilio's authenticated API so the browser can play it without needing Twilio credentials. Respects sub-account context when X-Sub-Account-Id header is present. Returns: StreamingResponse with audio/mpeg content Raises: 404: Call not found or no recording available **Parameters:** - \`call_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Chat ### GET /chat/conversations List Conversations List text conversations with pagination and filters. **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) - \`channel\` (query, ) - \`text_assistant_id\` (query, ) - \`date_from\` (query, ) - \`date_to\` (query, ) - \`search\` (query, ) **Responses:** - \`200\`: Successful Response Returns: \`TextConversationListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /chat/conversations/{conversation_id} Get Conversation Get a single conversation with assistant info. **Parameters:** - \`conversation_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`TextConversationResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /chat/conversations/{conversation_id}/messages List Messages List messages for a conversation, ordered oldest-first. **Parameters:** - \`conversation_id\` (path, string (required)) - \`limit\` (query, integer) - \`offset\` (query, integer) **Responses:** - \`200\`: Successful Response Returns: \`TextMessageListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /chat/stats Get Chat Stats Get chat dashboard statistics. **Parameters:** - \`date_from\` (query, ) - \`date_to\` (query, ) **Responses:** - \`200\`: Successful Response Returns: \`ChatStatsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Compliance ### GET /compliance/outbound Get Outbound Compliance Get outbound calling compliance status for current tenant. **Responses:** - \`200\`: Successful Response Returns: \`OutboundComplianceStatus\` --- ### POST /compliance/outbound/accept Accept Outbound Compliance Accept outbound calling terms. Records acceptance with audit trail. **Request Body:** \`AcceptOutboundTermsRequest\` (application/json) - terms_version: string (default: 1.0) **Responses:** - \`200\`: Successful Response Returns: \`OutboundComplianceStatus\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Contacts ### GET /contacts/ List Contacts List GHL contacts with call statistics. Returns paginated list of contacts enriched with: - Total call count - Last call date Uses cursor-based pagination (GHL requirement). Pass BOTH `start_after_id` and `start_after` from the previous response to get the next page. For tenants with multiple GHL accounts, use integration_id to specify which one. Use has_calls_only=true to filter to only contacts that have AI calls. **Parameters:** - \`limit\` (query, integer) - \`search\` (query, ) - \`integration_id\` (query, ) — Specific GHL integration ID for multi-account tenants - \`has_calls_only\` (query, boolean) — Only show contacts with AI calls - \`enrich\` (query, boolean) — Enrich with call stats (set false for fast search) - \`start_after_id\` (query, ) — Cursor for pagination - contact ID from previous page's next_cursor - \`start_after\` (query, ) — Cursor timestamp from previous page's next_cursor_timestamp **Responses:** - \`200\`: Successful Response Returns: \`ContactListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /contacts/with-calls List Contacts With Calls List only contacts that have AI call history. Uses inverted data flow: queries call_logs first, then fetches GHL data. This ensures ALL contacts with calls are found, not limited by GHL pagination. Supports server-side sorting and filtering: - sort_by: name, phone, email, company, calls, last_call - sort_dir: asc, desc - filter_phone/email/company: blank, not_blank **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) - \`integration_id\` (query, ) — Specific GHL integration ID for multi-account tenants - \`sort_by\` (query, ) — Sort by: name, phone, email, company, calls, last_call - \`sort_dir\` (query, ) — Sort direction: asc or desc - \`filter_phone\` (query, ) — Filter phone: blank or not_blank - \`filter_email\` (query, ) — Filter email: blank or not_blank - \`filter_company\` (query, ) — Filter company: blank or not_blank **Responses:** - \`200\`: Successful Response Returns: \`ContactListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /contacts/{phone} Get Contact Detail Get contact details with full call history. Args: phone: Phone number (URL-encoded if contains special chars) enrich: Set to "full" for pipeline, custom fields, and appointment enrichment **Parameters:** - \`phone\` (path, string (required)) - \`enrich\` (query, ) — Set to 'full' for enriched contact data **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /contacts/{phone} Patch Contact Update a GHL contact: add/remove tags, update custom fields, update pipeline stage. Each field is independently optional — partial success is OK. **Parameters:** - \`phone\` (path, string (required)) **Request Body:** \`ContactPatchRequest\` (application/json) - add_tags: array (default: []) - remove_tags: array (default: []) - custom_fields: array | null - opportunity_id: string | null - pipeline_stage_id: string | null **Responses:** - \`200\`: Successful Response Returns: \`ContactPatchResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /contacts/{phone}/conversations Get Conversation Timeline Get merged call + SMS conversation timeline for a contact. Returns chronological list merging call_logs and text_messages. Gracefully degrades to voice-only if GHL lookup fails (sms_included=false). Never returns 404 — empty timeline is valid. **Parameters:** - \`phone\` (path, string (required)) - \`limit\` (query, integer) - \`offset\` (query, integer) **Responses:** - \`200\`: Successful Response Returns: \`ConversationTimelineResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /contacts/{phone}/notes List Notes List notes for a GHL contact. **Parameters:** - \`phone\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`NotesListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /contacts/{phone}/notes Create Note Create a note on a GHL contact. **Parameters:** - \`phone\` (path, string (required)) **Request Body:** \`NoteCreateRequest\` (application/json) - body: string (required) **Responses:** - \`201\`: Successful Response Returns: \`NoteResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## D ### GET /d/showcase/{slug} Get Showcase Public endpoint: Get all active demos for a showcase page. The slug here is any demo slug — we find the agent and return all demos for it. **Parameters:** - \`slug\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /d/{slug} Get Public Demo Public endpoint: Get demo config for the demo page. No auth required. **Parameters:** - \`slug\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`PublicDemoResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /d/{slug}/chat Public Demo Chat Public text chat endpoint for demo pages. Uses the agent's system prompt + tools to generate AI text responses. No auth required — authenticates via active demo config slug. **Parameters:** - \`slug\` (path, string (required)) **Request Body:** \`DemoChatRequest\` (application/json) - messages: array (required) Items: DemoChatMessage - dynamic_variables: object | null **Responses:** - \`200\`: Successful Response Returns: \`DemoChatResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /d/{slug}/event Track Demo Event Public endpoint: Track a demo event (view, call, form submit). **Parameters:** - \`slug\` (path, string (required)) **Request Body:** \`DemoEventCreate\` (application/json) - event_type: string (required) - duration_s: integer | null - metadata: object (default: {}) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Demos ### GET /demos/ List Demos List all demo configs for the current tenant. **Responses:** - \`200\`: Successful Response Returns: Array of \`DemoConfigListItem\` --- ### POST /demos/ Create Demo Create a new demo config. **Request Body:** \`DemoConfigCreate\` (application/json) - agent_id: string (required) - channel: string (required) [phone | sms | web | orb | fb_messenger | ig_messenger | tiktok | whatsapp | fb_lead | ig_lead] - name: string (required) - config: object (default: {}) - after_cta_text: string | null - after_cta_url: string | null - webhook_url: string | null - expires_in_days: integer | null **Responses:** - \`200\`: Successful Response Returns: \`DemoConfigResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /demos/import-from-url Import From Url Import demo configuration from a website URL (non-streaming fallback). Scrapes the provided URL, extracts business information using AI, and generates personalized demo text (headline, summary, CTA). Returns all fields needed to pre-fill the demo creation wizard. Note: Prefer /import-from-url/stream for real-time progress updates. **Request Body:** \`ImportFromUrlRequest\` (application/json) - url: string (required) — Website URL to analyze (e.g., https://example.com) - channel: string (required) [phone | sms | web | orb | fb_messenger | ig_messenger | tiktok | whatsapp | fb_lead | ig_lead] — Demo channel type **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /demos/import-from-url/stream Import From Url Stream Import demo configuration from a website URL with streaming progress updates. Uses Server-Sent Events (SSE) to stream progress in real-time: - Step updates: "discovering", "scraping", "extracting", "generating" - Progress: current/total for each step - Detail: what's currently being processed Final event contains the complete ImportFromUrlResponse. **Parameters:** - \`url\` (query, string (required)) - \`channel\` (query, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /demos/templates Get Templates Get all industry demo templates. **Responses:** - \`200\`: Successful Response --- ### GET /demos/templates/{industry}/{channel} Get Template Get a specific industry/channel demo template. **Parameters:** - \`industry\` (path, string (required)) - \`channel\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /demos/webhook-test Test Webhook Url Test any webhook URL by sending a sample payload. No demo ID needed. **Request Body:** \`WebhookUrlTestRequest\` (application/json) - webhook_url: string (required) - form_fields: array | null **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /demos/{demo_id} Get Demo Get a single demo config. **Parameters:** - \`demo_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`DemoConfigResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /demos/{demo_id} Update Demo Update a demo config. **Parameters:** - \`demo_id\` (path, string (required)) **Request Body:** \`DemoConfigUpdate\` (application/json) - name: string | null - channel: string | null - config: object | null - is_active: boolean | null - after_cta_text: string | null - after_cta_url: string | null - webhook_url: string | null - expires_in_days: integer | null **Responses:** - \`200\`: Successful Response Returns: \`DemoConfigResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /demos/{demo_id} Delete Demo Delete a demo config. **Parameters:** - \`demo_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /demos/{demo_id}/analytics Get Demo Analytics Get analytics for a demo config. **Parameters:** - \`demo_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /demos/{demo_id}/duplicate Duplicate Demo Clone a demo config. **Parameters:** - \`demo_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`DemoConfigResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /demos/{demo_id}/upload-image Upload Demo Image Upload an image for a demo config (ad creative, logo, avatar, etc.). **Parameters:** - \`demo_id\` (path, string (required)) **Request Body:** \`Body_upload_demo_image_demos__demo_id__upload_image_post\` (multipart/form-data) - file: string (required) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /demos/{demo_id}/webhook-test Test Demo Webhook Send a test payload to the demo's webhook URL. **Parameters:** - \`demo_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Documents ### GET /documents List Documents List all documents for the current tenant. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: returns their documents. **Responses:** - \`200\`: Successful Response Returns: \`DocumentListResponse\` --- ### POST /documents Upload Document Upload a document to the knowledge base. Supports 100+ file types (validated by xAI). Max 48MB. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: uploads to their collection. **Request Body:** \`Body_upload_document_documents_post\` (multipart/form-data) - file: string (required) - description: string | null **Responses:** - \`201\`: Successful Response Returns: \`DocumentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /documents/search Search Documents Search documents in the knowledge base. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: searches their collection. **Request Body:** \`SearchRequest\` (application/json) - query: string (required) - max_results: integer (default: 5) **Responses:** - \`200\`: Successful Response Returns: \`SearchResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /documents/stats Get Stats Get collection statistics for the current tenant. Returns document counts, total size, and status breakdown. **Responses:** - \`200\`: Successful Response Returns: \`CollectionStatsResponse\` --- ### DELETE /documents/{document_id} Delete Document Delete a document from the knowledge base. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: deletes from their collection. **Parameters:** - \`document_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Functions ### GET /functions List Library Functions List all custom functions in the tenant's library. Returns functions with their attached agent information. For agencies: requires sub-account context (X-Sub-Account-Id header). **Responses:** - \`200\`: Successful Response Returns: \`FunctionLibraryResponse\` --- ### POST /functions Create Library Function Create a new function in the tenant's library. The function is not attached to any agent - use attach to add to agents. For agencies: requires sub-account context (X-Sub-Account-Id header). **Request Body:** \`CustomFunctionCreate\` (application/json) - name: string (required) — Function name in snake_case (e.g., check_inventory) - description: string (required) — Description of what the function does (shown to AI) - parameters: object — JSON Schema for function parameters - webhook_url: string (required) — Webhook URL to call (must start with http:// or https://) - webhook_method: string (default: POST) — HTTP method for webhook call - webhook_headers: object — Custom headers to include in webhook request - webhook_timeout_ms: integer (default: 5000) — Timeout for webhook call in milliseconds (1000-30000) - is_enabled: boolean (default: True) — Whether the function is enabled - speak_during_execution: boolean (default: True) — Whether AI should speak while waiting for webhook response **Responses:** - \`201\`: Successful Response Returns: \`CustomFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /functions/test-webhook Test Webhook Url Test a webhook URL before creating a function. Makes a real HTTP request to the provided webhook URL to verify connectivity and response. Used by the function wizard to validate webhook URLs before saving. **Request Body:** \`WebhookTestRequest\` (application/json) - webhook_url: string (required) — Webhook URL to test - webhook_method: string (default: POST) — HTTP method for webhook call - webhook_headers: object — Custom headers to include in webhook request - webhook_timeout_ms: integer (default: 5000) — Timeout for webhook call in milliseconds - function_name: string | null — Function name to include in test payload - fields: array | null — Configured fields to build sample arguments from - contact: WebhookTestContact | null — GHL contact to populate call_context with real data **Responses:** - \`200\`: Successful Response Returns: \`FunctionTestResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /functions/{function_id} Get Library Function Get a specific function from the library with attached agents info. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`function_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`FunctionWithAgentsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PUT /functions/{function_id} Update Library Function Update a function in the library. Changes affect all agents using this function. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`function_id\` (path, string (required)) **Request Body:** \`CustomFunctionUpdate\` (application/json) - name: string | null — Function name in snake_case - description: string | null — Description of what the function does - parameters: object | null — JSON Schema for function parameters - webhook_url: string | null — Webhook URL to call - webhook_method: string | null — HTTP method for webhook call - webhook_headers: object | null — Custom headers to include in webhook request - webhook_timeout_ms: integer | null — Timeout for webhook call in milliseconds - is_enabled: boolean | null — Whether the function is enabled - speak_during_execution: boolean | null — Whether AI should speak while waiting for webhook response **Responses:** - \`200\`: Successful Response Returns: \`CustomFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /functions/{function_id} Delete Library Function Delete a function from the library. Cascade removes from all agents. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`function_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /functions/{function_id}/agents List Function Agents List all agents using a specific function. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`function_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /functions/{function_id}/copy Copy Function To Sub Account Copy a function to another sub-account (agency feature). Requires agency access - the target tenant must be a sub-account of the current agency. **Parameters:** - \`function_id\` (path, string (required)) **Request Body:** \`CopyFunctionRequest\` (application/json) - target_tenant_id: string (required) — Target sub-account to copy function to **Responses:** - \`200\`: Successful Response Returns: \`CustomFunctionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /functions/{function_id}/test Test Library Function Test a library function's webhook by making a real call. For agencies: requires sub-account context (X-Sub-Account-Id header). **Parameters:** - \`function_id\` (path, string (required)) **Request Body:** \`FunctionTestRequest\` (application/json) - arguments: object — Arguments to pass to the function - contact_id: string (default: test-contact-id) — GHL contact ID — always present via Contact Intelligence **Responses:** - \`200\`: Successful Response Returns: \`FunctionTestResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Health ### GET /health Health Check Health check endpoint. Returns 503 during graceful shutdown drain. **Responses:** - \`200\`: Successful Response --- ## Integrations ### GET /integrations List Integrations List all connected integrations for the current tenant. Supports sub-account context via X-Sub-Account-Id header. For sub-accounts: Returns integrations ASSIGNED via sub_account_integrations table. For regular tenants: Returns integrations directly owned by the tenant. **Responses:** - \`200\`: Successful Response Returns: Array of \`IntegrationStatus\` --- ### GET /integrations/calendar/auth Ghl Auth Initiate Initiate GHL OAuth flow. Returns the OAuth URL for the user to authorize access. Supports agency impersonation: If X-Sub-Account-Id header is present, the integration will be created for the sub-account's tenant. **Responses:** - \`200\`: Successful Response --- ### GET /integrations/calendar/callback Ghl Auth Callback Handle GHL OAuth callback. Exchanges the authorization code for tokens and stores them. Supports two flows: - User-initiated (from our app): state parameter present with tenant_id - Marketplace install (from GHL): no state parameter, tenant resolved from token response **Parameters:** - \`code\` (query, string (required)) - \`state\` (query, ) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /integrations/ghl/calendars List Ghl Calendars List available GoHighLevel calendars for a specific integration. Args: integration_id: The UUID of the GHL integration to fetch calendars from. Use GET /integrations/ghl/integrations to list available integrations. Supports sub-account context via X-Sub-Account-Id header. **Parameters:** - \`integration_id\` (query, string (required)) **Responses:** - \`200\`: Successful Response Returns: Array of \`CalendarInfo\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /integrations/ghl/connect-api-key Connect Ghl Api Key Connect GoHighLevel using a Private Integration API key. Alternative to OAuth for when marketplace approval is pending. Validates the key against GHL API, encrypts, and stores. Args: request: API key and location ID current_user: Current authenticated user tenant_id: Current tenant ID (supports sub-account context) Returns: Success status with location name Raises: HTTPException 400: If API key is invalid or location not found **Request Body:** \`GHLApiKeyRequest\` (application/json) - api_key: string (required) — GHL Private Integration API key - location_id: string (required) — GHL Location ID **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /integrations/ghl/disconnect Disconnect Ghl DEPRECATED: Disconnect GoHighLevel integration. This endpoint deactivates ALL GHL integrations for the tenant. Use DELETE /integration/{integration_id} instead to disconnect a specific integration. Removes stored OAuth tokens and deactivates integration. NOTE: Uses the user's ACTUAL tenant_id (not sub-account context) because integrations are always owned by the tenant that connected them. **Responses:** - \`200\`: Successful Response --- ### GET /integrations/ghl/integrations List Ghl Integrations List all GoHighLevel integrations available to the tenant. Includes both: - Integrations owned directly by this tenant - Integrations assigned to this sub-account from parent agency Supports sub-account context via X-Sub-Account-Id header. **Responses:** - \`200\`: Successful Response Returns: Array of \`GHLIntegrationInfo\` --- ### GET /integrations/ghl/phone-numbers List Ghl Phone Numbers List phone numbers from GoHighLevel location. NOTE: GHL API does not support adding phone numbers programmatically. This is display-only - users must manually import numbers via GHL UI. Args: integration_id: Optional specific GHL integration ID to fetch numbers from. If not provided, uses first active GHL integration. Returns: List of phone numbers formatted for frontend: - phone_number: E.164 format - friendly_name: Display name - capabilities: {voice: bool, sms: bool, mms: bool} Supports sub-account context via X-Sub-Account-Id header. **Parameters:** - \`integration_id\` (query, ) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /integrations/ghl/status Get Ghl Status Get GoHighLevel integration connection status. Returns connection status and location information. Supports sub-account context via X-Sub-Account-Id header. Checks both: - Integrations owned directly by this tenant - Integrations assigned to this sub-account from parent agency **Responses:** - \`200\`: Successful Response --- ### GET /integrations/ghl/{integration_id}/custom-fields List Ghl Custom Fields List available custom fields from GoHighLevel location. Returns all custom fields configured in the GHL location that can be updated via the update_custom_fields tool. **Parameters:** - \`integration_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /integrations/ghl/{integration_id}/location-details Get Ghl Location Details Fetch full location details from GoHighLevel API. Returns location name, email, phone, address, and other details to auto-fill sub-account creation form. Supports both direct ownership and junction table assignment for sub-accounts. **Parameters:** - \`integration_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /integrations/ghl/{integration_id}/pipelines List Ghl Pipelines List available pipelines from GoHighLevel location. Returns all pipelines and their stages configured in the GHL location that can be used with create_opportunity/update_opportunity_stage tools. **Parameters:** - \`integration_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /integrations/ghl/{integration_id}/tags List Ghl Tags List available tags from GoHighLevel location. Returns all tags configured in the GHL location that can be applied to contacts via the add_tag/remove_tag tools. **Parameters:** - \`integration_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /integrations/ghl/{integration_id}/tags Create Ghl Tag Create a new tag in the GoHighLevel location. Body: { "name": "tag-name" } **Parameters:** - \`integration_id\` (path, string (required)) **Request Body:** (application/json) - (object) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /integrations/ghl/{integration_id}/workflows List Ghl Workflows List available workflows from GoHighLevel location. Returns all workflows configured in the GHL location that can be triggered via the trigger_workflow tool. **Parameters:** - \`integration_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /integrations/integration/{integration_id} Disconnect Integration By Id Disconnect a specific integration by ID. This removes the stored tokens but doesn't revoke access at the provider. Allows disconnecting individual integrations when multiple of the same provider exist. NOTE: Uses the user's ACTUAL tenant_id (not sub-account context) because integrations are always owned by the tenant that connected them, not sub-accounts. Sub-accounts only have integration ASSIGNMENTS via sub_account_integrations table. **Parameters:** - \`integration_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /integrations/twilio/connect Connect Twilio Connect tenant's Twilio account with API credentials. Unlike OAuth integrations, this accepts credentials directly. Credentials are validated by testing API connection before saving. Args: request: Account SID and Auth Token current_user: Current authenticated user tenant_id: Current tenant ID Returns: Success status and saved integration data Raises: HTTPException 400: If credentials are invalid **Request Body:** \`TwilioCredentialsRequest\` (application/json) - account_name: string (required) — Friendly name for this Twilio account - account_sid: string (required) — Twilio Account SID (ACxxxxxx...) - auth_token: string (required) — Twilio Auth Token **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /integrations/twilio/disconnect Disconnect Twilio Disconnect tenant's Twilio account. Removes stored credentials from database. Phone numbers provisioned with this account will stop working. Args: current_user: Current authenticated user tenant_id: Current tenant ID Returns: Success status Raises: HTTPException 404: If no Twilio integration found **Responses:** - \`200\`: Successful Response --- ### GET /integrations/twilio/status Get Twilio Status Check Twilio integration status with live credential validation. Makes a real Twilio API call to verify credentials are valid and the account is in good standing (not suspended, negative balance, etc.). Args: current_user: Current authenticated user tenant_id: Current tenant ID Returns: Connection status, health status, masked account SID, metadata **Responses:** - \`200\`: Successful Response --- ### DELETE /integrations/{provider} Disconnect Integration DEPRECATED: Disconnect an integration by provider name. This endpoint deletes ALL integrations of the given provider type. Use DELETE /integration/{integration_id} instead to delete a specific integration. This removes the stored tokens but doesn't revoke access at the provider. NOTE: Uses the user's ACTUAL tenant_id (not sub-account context) because integrations are always owned by the tenant that connected them. **Parameters:** - \`provider\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Issues ### POST /issues/ Create Issue Submit an issue report with optional screenshot. **Request Body:** \`Body_create_issue_issues__post\` (multipart/form-data) - message: string (required) - url: string | null - page_name: string | null - browser_info: string | null - image: string | null **Responses:** - \`201\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Knowledge Bases ### GET /knowledge-bases List Knowledge Bases List all Knowledge Bases for the current tenant. For agencies: requires sub-account context (X-Sub-Account-Id header). For direct tenants: returns their Knowledge Bases. **Responses:** - \`200\`: Successful Response Returns: \`KnowledgeBaseListResponse\` --- ### POST /knowledge-bases Create Knowledge Base Create a new Knowledge Base. Creates an xAI collection for document storage. **Request Body:** \`KnowledgeBaseCreate\` (application/json) - name: string (required) — Name of the Knowledge Base **Responses:** - \`201\`: Successful Response Returns: \`KnowledgeBaseResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id} Get Knowledge Base Get a specific Knowledge Base by ID. **Parameters:** - \`kb_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`KnowledgeBaseResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /knowledge-bases/{kb_id} Update Knowledge Base Update a Knowledge Base (rename). **Parameters:** - \`kb_id\` (path, string (required)) **Request Body:** \`KnowledgeBaseUpdate\` (application/json) - name: string (required) — New name for the Knowledge Base **Responses:** - \`200\`: Successful Response Returns: \`KnowledgeBaseResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /knowledge-bases/{kb_id} Delete Knowledge Base Delete a Knowledge Base and all its documents. This also removes the KB from any agents that reference it. **Parameters:** - \`kb_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/documents List Kb Documents List all documents in a specific Knowledge Base. **Parameters:** - \`kb_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`DocumentListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/documents Upload Kb Document Upload a document to a specific Knowledge Base. Supports 100+ file types (validated by xAI). Max 48MB. **Parameters:** - \`kb_id\` (path, string (required)) **Request Body:** \`Body_upload_kb_document_knowledge_bases__kb_id__documents_post\` (multipart/form-data) - file: string (required) - description: string | null **Responses:** - \`201\`: Successful Response Returns: \`DocumentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/faqs List Faq Sources List all FAQ sources for a KB with their pairs. **Parameters:** - \`kb_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: Array of \`FAQSourceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/faqs Create Faq Source Create an FAQ source with optional initial pairs. **Parameters:** - \`kb_id\` (path, string (required)) **Request Body:** \`FAQSourceCreate\` (application/json) - name: string (required) - pairs: array Items: FAQPairCreate **Responses:** - \`201\`: Successful Response Returns: \`FAQSourceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/faqs/{source_id} Get Faq Source Get an FAQ source with all its pairs. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`FAQSourceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/faqs/{source_id}/generate Generate Faqs Use AI to generate FAQ pairs from provided content. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Request Body:** \`GenerateFAQRequest\` (application/json) - content: string (required) — Content to extract FAQs from - num_pairs: integer (default: 10) **Responses:** - \`200\`: Successful Response Returns: Array of \`FAQPairResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/faqs/{source_id}/pairs Add Faq Pairs Add FAQ pairs to an existing FAQ source. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Request Body:** (application/json) Array of FAQPairCreate **Responses:** - \`200\`: Successful Response Returns: Array of \`FAQPairResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /knowledge-bases/{kb_id}/faqs/{source_id}/pairs/{pair_id} Update Faq Pair Update a single FAQ pair. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) - \`pair_id\` (path, string (required)) **Request Body:** \`FAQPairUpdate\` (application/json) - question: string | null - answer: string | null - sort_order: integer | null **Responses:** - \`200\`: Successful Response Returns: \`FAQPairResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /knowledge-bases/{kb_id}/faqs/{source_id}/pairs/{pair_id} Delete Faq Pair Delete a single FAQ pair. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) - \`pair_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/rich-text List Rich Texts List all rich text sources for a KB. **Parameters:** - \`kb_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: Array of \`RichTextResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/rich-text Create Rich Text Create a rich text source and sync to xAI. **Parameters:** - \`kb_id\` (path, string (required)) **Request Body:** \`RichTextCreate\` (application/json) - name: string (required) - content: string (required) — Rich text / markdown content **Responses:** - \`201\`: Successful Response Returns: \`RichTextResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/rich-text/{source_id} Get Rich Text Get a rich text source. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`RichTextResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /knowledge-bases/{kb_id}/rich-text/{source_id} Update Rich Text Update a rich text source and re-sync to xAI. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Request Body:** \`RichTextUpdate\` (application/json) - name: string | null - content: string | null **Responses:** - \`200\`: Successful Response Returns: \`RichTextResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/sources List Sources List all sources for a Knowledge Base, optionally filtered by type. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_type\` (query, ) **Responses:** - \`200\`: Successful Response Returns: \`SourceListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /knowledge-bases/{kb_id}/sources/{source_id} Delete Source Delete a KB source and its linked xAI document. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/stats Get Kb Stats Get statistics for a specific Knowledge Base. **Parameters:** - \`kb_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`CollectionStatsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/tables List Tables List all table sources for a KB. **Parameters:** - \`kb_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: Array of \`TableSourceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/tables Create Table Source Create a table source and sync to xAI. **Parameters:** - \`kb_id\` (path, string (required)) **Request Body:** \`TableSourceCreate\` (application/json) - name: string (required) - headers: array (required) - table_data: array **Responses:** - \`201\`: Successful Response Returns: \`TableSourceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/tables/parse-csv Parse Csv Parse a CSV file and return headers + rows (does not create a source). **Parameters:** - \`kb_id\` (path, string (required)) **Request Body:** \`Body_parse_csv_knowledge_bases__kb_id__tables_parse_csv_post\` (multipart/form-data) - file: string (required) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/tables/{source_id} Get Table Source Get a table source. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`TableSourceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /knowledge-bases/{kb_id}/tables/{source_id} Update Table Source Update a table source and re-sync to xAI. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Request Body:** \`TableSourceUpdate\` (application/json) - name: string | null - headers: array | null - table_data: array | null **Responses:** - \`200\`: Successful Response Returns: \`TableSourceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/web-crawlers List Web Crawlers List all web crawler sources for a KB. **Parameters:** - \`kb_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: Array of \`WebCrawlerResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/web-crawlers Create Web Crawler Create a web crawler source and trigger initial crawl. **Parameters:** - \`kb_id\` (path, string (required)) **Request Body:** \`WebCrawlerCreate\` (application/json) - name: string (required) - root_url: string (required) — URL to crawl - schedule_interval: string | null — Recrawl interval: 'daily', 'weekly', 'monthly', or None **Responses:** - \`201\`: Successful Response Returns: \`WebCrawlerResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /knowledge-bases/{kb_id}/web-crawlers/{source_id} Get Web Crawler Get a web crawler source. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`WebCrawlerResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /knowledge-bases/{kb_id}/web-crawlers/{source_id}/recrawl Trigger Recrawl Trigger a re-crawl of the web source. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`WebCrawlerResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /knowledge-bases/{kb_id}/web-crawlers/{source_id}/schedule Update Crawl Schedule Update the recrawl schedule for a web crawler source. **Parameters:** - \`kb_id\` (path, string (required)) - \`source_id\` (path, string (required)) **Request Body:** \`WebCrawlerScheduleUpdate\` (application/json) - schedule_interval: string | null — Recrawl interval: 'daily', 'weekly', 'monthly', or None **Responses:** - \`200\`: Successful Response Returns: \`WebCrawlerResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Notifications ### GET /notifications/in-app List In App Notifications List in-app notifications for the current tenant (or sub-account context). **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) **Responses:** - \`200\`: Successful Response Returns: \`NotificationListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /notifications/in-app/aggregate List Aggregate Notifications List notifications across all sub-accounts (agency owners only). Uses get_current_tenant_id (not effective) so we always query from the agency owner's perspective, even when in sub-account context. **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) **Responses:** - \`200\`: Successful Response Returns: \`NotificationListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /notifications/in-app/aggregate/unread-count Get Aggregate Unread Count Get aggregate unread count across all sub-accounts. **Responses:** - \`200\`: Successful Response Returns: \`UnreadCountResponse\` --- ### DELETE /notifications/in-app/clear Clear Read Notifications Delete all read notifications for the tenant. Keeps unread ones. **Responses:** - \`200\`: Successful Response --- ### PATCH /notifications/in-app/read-all Mark All Notifications Read Mark all notifications as read. **Responses:** - \`200\`: Successful Response --- ### GET /notifications/in-app/unread-count Get Unread Count Get unread notification count for badge polling. **Responses:** - \`200\`: Successful Response Returns: \`UnreadCountResponse\` --- ### DELETE /notifications/in-app/{notification_id} Delete Notification Delete a single notification. **Parameters:** - \`notification_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /notifications/in-app/{notification_id}/read Mark Notification Read Mark a single notification as read. **Parameters:** - \`notification_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /notifications/settings Get Notification Settings Get notification settings for the current tenant. Returns default settings if none exist (creating them in the process). **Responses:** - \`200\`: Successful Response Returns: \`NotificationSettingsResponse\` --- ### PATCH /notifications/settings Update Notification Settings Update notification settings for the current tenant. Only provided fields are updated; others remain unchanged. **Request Body:** \`NotificationSettingsUpdate\` (application/json) - email_new_call: boolean | null - email_call_summary: boolean | null - email_low_balance: boolean | null - email_weekly_digest: boolean | null - additional_emails: array | null - quiet_hours_enabled: boolean | null - quiet_hours_start: string | null - quiet_hours_end: string | null - quiet_hours_timezone: string | null - notification_frequency: string | null - sms_enabled: boolean | null **Responses:** - \`200\`: Successful Response Returns: \`NotificationSettingsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Onboarding ### PUT /onboarding/navigate/{step} Navigate To Step Navigate to a specific step (back button / sidebar click). Only allows navigating to completed steps or current step. **Parameters:** - \`step\` (path, integer (required)) **Responses:** - \`200\`: Successful Response Returns: \`OnboardingProgress\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /onboarding/progress Get Onboarding Progress Get current onboarding progress for the tenant. Creates a new record if none exists. **Responses:** - \`200\`: Successful Response Returns: \`OnboardingProgress\` --- ### PUT /onboarding/progress/{step} Update Onboarding Progress Update onboarding progress for a specific step. Marks the step as complete and advances to the next step. **Parameters:** - \`step\` (path, integer (required)) **Request Body:** \`StepUpdateRequest\` (application/json) - account_type: string | null - business_name: string | null - industry: string | null - connected: boolean | null - purchased: boolean | null - created: boolean | null - completed: boolean | null - deployed: boolean | null - skipped: boolean | null - agent_id: string | null - ghl_integration_id: string | null - phone_number_id: string | null - sub_account_id: string | null **Responses:** - \`200\`: Successful Response Returns: \`OnboardingProgress\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /onboarding/reset Reset Onboarding Progress Reset onboarding progress to step 1. Useful for testing or allowing users to restart the wizard. **Responses:** - \`200\`: Successful Response Returns: \`OnboardingProgress\` --- ### POST /onboarding/skip/{step} Skip Onboarding Step Skip an optional onboarding step. Only steps 2 (CRM), 3 (Phone), and 7 (Complete) can be skipped. **Parameters:** - \`step\` (path, integer (required)) **Responses:** - \`200\`: Successful Response Returns: \`OnboardingProgress\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Outbound ### POST /outbound/agents/{agent_id}/call Initiate Outbound Call Initiate an outbound call from a voice agent. The agent will call the specified phone number and handle the conversation using its configured AI settings. Args: agent_id: The agent to handle the call request: Call details including recipient number Returns: Call details including call_sid for tracking **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`OutboundCallRequest\` (application/json) - to_number: string (required) — Recipient phone number in E.164 format (e.g., +14155551234) - from_phone_number_id: string | null — Specific phone number to call from. If not provided, uses agent's primary number. - ghl_contact_id: string | null — GHL contact ID for pre-flight conversation checks **Responses:** - \`200\`: Successful Response Returns: \`OutboundCallResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /outbound/trigger Trigger Outbound Call Trigger an outbound call via webhook (for GHL, Zapier, etc.). Authentication: API Key (X-API-Key header) or JWT Bearer token. This endpoint is designed for external automation triggers like: - GoHighLevel workflow webhooks - Zapier/Make integrations - Custom automation scripts Args: request: Webhook payload with agent_id, to_number, and optional context Returns: Call details including call_sid for tracking Example cURL: ``` curl -X POST https://leadlock-app.onrender.com/outbound/trigger \ -H "X-API-Key: sk_live_xxx" \ -H "Content-Type: application/json" \ -d '{ "agent_id": "uuid-here", "to_number": "+14155551234", "context": { "first_name": "John", "source": "GHL New Lead" } }' ``` **Request Body:** \`WebhookTriggerRequest\` (application/json) - agent_id: string (required) — Agent ID to handle the call - to_number: string (required) — Recipient phone number in E.164 format - from_phone_number_id: string | null — Specific phone number to call from - ghl_contact_id: string | null — GHL contact ID for pre-flight conversation checks - context: WebhookCallContext | null — Context to personalize the call (injected into agent prompt) - dynamic_variables: object | null — Variables to substitute in prompt: {'customer_name': 'John', 'order_id': '12345'}. All values must be strings. **Responses:** - \`200\`: Successful Response Returns: \`OutboundCallResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Phone Numbers ### GET /phone-numbers List Phone Numbers List all phone numbers owned by the tenant. For sub-accounts (or agencies viewing as sub-account), only shows numbers assigned to them. **Parameters:** - \`sub_account_id\` (query, ) — Filter by sub-account **Responses:** - \`200\`: Successful Response Returns: \`PhoneNumberListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /phone-numbers/available-for-assignment Get Available For Assignment Get all phone numbers available for assignment to sub-accounts. Only returns agency's own numbers (not sub-account imported ones). **Responses:** - \`200\`: Successful Response --- ### POST /phone-numbers/backfill-sms-webhooks Backfill Sms Webhooks One-time backfill: set SMS webhook URL on all Twilio SMS-capable numbers for the current tenant. Safe to call multiple times (idempotent). **Responses:** - \`200\`: Successful Response --- ### POST /phone-numbers/import Import Phone Numbers Import one or more phone numbers from Twilio account. Imports numbers with automatic webhook configuration for voice calls. Limited to 10 numbers per request to avoid rate limits and timeouts. **Request Body:** \`ImportNumbersRequest\` (application/json) - phone_number_sids: array (required) — List of Twilio phone number SIDs to import - configure_sip: boolean (default: True) — DEPRECATED - No longer used (kept for API compatibility) **Responses:** - \`200\`: Successful Response Returns: Array of \`PhoneNumberResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /phone-numbers/import/ghl Import Ghl Phone Numbers Import one or more GoHighLevel phone numbers. GHL numbers are imported as SMS-capable (no voice) for future SMS/chat integration via Lead Connector. Limited to 10 numbers per request. **Request Body:** \`ImportGHLNumbersRequest\` (application/json) - phone_numbers: array (required) — List of GHL phone numbers to import **Responses:** - \`200\`: Successful Response Returns: Array of \`PhoneNumberResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /phone-numbers/refresh-a2p-status Refresh All A2P Status Refresh A2P status for all phone numbers belonging to current tenant. This endpoint: - Checks A2P status for ALL tenant phone numbers - Updates database with current status - Returns summary of results Use cases: - After completing A2P registration in Twilio/GHL - Periodic status verification - Troubleshooting messaging issues **Responses:** - \`200\`: Successful Response --- ### GET /phone-numbers/twilio/list List Twilio Numbers List all numbers in client's Twilio account. Returns numbers with import status indicating whether each number is already imported, available for import, or unavailable. **Responses:** - \`200\`: Successful Response --- ### GET /phone-numbers/{phone_number_id} Get Phone Number Get details of a specific phone number. **Parameters:** - \`phone_number_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`PhoneNumberResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /phone-numbers/{phone_number_id} Update Phone Number Update a phone number's properties. Use this to assign a phone number to an agent or update its friendly name. **Parameters:** - \`phone_number_id\` (path, string (required)) **Request Body:** \`PhoneNumberUpdate\` (application/json) - agent_id: string | null — Assign to agent - friendly_name: string | null — Display name **Responses:** - \`200\`: Successful Response Returns: \`PhoneNumberResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /phone-numbers/{phone_number_id} Release Phone Number Delete a phone number from Leadlock. IMPORTANT: This only removes the number from Leadlock's database. The number remains in your Twilio/GoHighLevel account and can be re-imported. To permanently release a number from Twilio (so it can be purchased by others), use the Twilio Console. **Parameters:** - \`phone_number_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /phone-numbers/{phone_number_id}/assign Assign Phone Number Assign a phone number to a sub-account. Pass sub_account_id=null to unassign. Only agencies can use this endpoint. **Parameters:** - \`phone_number_id\` (path, string (required)) **Request Body:** \`AssignPhoneNumberRequest\` (application/json) - sub_account_id: string | null — Sub-account ID to assign to, or None to unassign **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /phone-numbers/{phone_number_id}/check-a2p Check A2P Status Check and update A2P registration status for a phone number. This endpoint: - Queries Twilio/GHL API to check A2P status - Updates database with current status - Returns A2P details and messaging_enabled flag Use this after completing A2P registration to verify status. **Parameters:** - \`phone_number_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /phone-numbers/{phone_number_id}/test-sms Send Test Sms Send a test SMS message using the specified phone number. This endpoint: - Validates phone number is SMS-capable - Validates A2P registration (required for US numbers) - Routes to Twilio or GoHighLevel based on phone number source - Returns delivery status Requirements: - Phone number must be sms_capable = true - Phone number must have messaging_enabled = true (A2P verified) - Recipient number must be in E.164 format (+14155551234) NOTE: Uses get_effective_tenant_id so sub-account users (or agency users impersonating a sub-account) are correctly attributed in text metering (FORGE text-agent-metering Step 9, 2026-04-08 — Site #10 / Issue #148 pattern). Args: phone_number_id: UUID of phone number to send from to: Recipient phone number (E.164 format) message: Message text (optional, defaults to test message) Returns: SMSResult with delivery status and provider details **Parameters:** - \`phone_number_id\` (path, string (required)) - \`to\` (query, string (required)) — Recipient phone number (E.164 format, e.g., +14155551234) - \`message\` (query, string) — Message text **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Scheduled Calls ### GET /scheduled-calls List Scheduled Calls List scheduled calls for the current tenant. Supports filtering by status, agent, and date range. Returns soonest calls first. **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) - \`status\` (query, ) — Filter by status: pending, dialing, completed, failed, cancelled - \`agent_id\` (query, ) — Filter by agent - \`start_date\` (query, ) — Filter by scheduled_for >= start_date - \`end_date\` (query, ) — Filter by scheduled_for <= end_date **Responses:** - \`200\`: Successful Response Returns: \`ScheduledCallListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /scheduled-calls Create Scheduled Call Create a new scheduled call (manual scheduling from UI). For AI-driven scheduling, use the schedule_callback function during a call. **Request Body:** \`ScheduledCallCreate\` (application/json) - agent_id: string (required) - to_phone_number: string (required) — Recipient phone number in E.164 format - scheduled_for: string (required) — When to call (ISO 8601 format, will be stored as UTC) - timezone: string (default: UTC) — User's timezone for display purposes - contact_id: string | null — GHL contact ID if known - contact_name: string | null — Contact name for display - phone_number_id: string | null — Specific phone number to call from (uses agent default if not provided) - is_callback: boolean (default: False) — True if this is a return call - previous_call_log_id: string | null — ID of the call that requested this callback - callback_context: string | null — Summary of previous conversation for context-aware greeting **Responses:** - \`201\`: Successful Response Returns: \`ScheduledCallResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /scheduled-calls/{scheduled_call_id} Get Scheduled Call Get a specific scheduled call by ID. **Parameters:** - \`scheduled_call_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`ScheduledCallResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /scheduled-calls/{scheduled_call_id} Update Scheduled Call Update a scheduled call. Only pending calls can be updated. **Parameters:** - \`scheduled_call_id\` (path, string (required)) **Request Body:** \`ScheduledCallUpdate\` (application/json) - scheduled_for: string | null - timezone: string | null - status: string | null - contact_name: string | null **Responses:** - \`200\`: Successful Response Returns: \`ScheduledCallResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /scheduled-calls/{scheduled_call_id} Delete Scheduled Call Delete a scheduled call. **Parameters:** - \`scheduled_call_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /scheduled-calls/{scheduled_call_id}/cancel Cancel Scheduled Call Cancel a pending scheduled call. **Parameters:** - \`scheduled_call_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`ScheduledCallResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /scheduled-calls/{scheduled_call_id}/retry Retry Scheduled Call Retry a failed scheduled call. If no new time is provided, schedules for 5 minutes from now. **Parameters:** - \`scheduled_call_id\` (path, string (required)) **Request Body:** \`ScheduledCallRetry\` (application/json) - scheduled_for: string | null — New time to schedule. If not provided, schedules immediately. **Responses:** - \`200\`: Successful Response Returns: \`ScheduledCallResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /scheduled-calls/{scheduled_call_id}/trigger Trigger Scheduled Call Immediately trigger a pending scheduled call. Bypasses the scheduler wait and dials right away. **Parameters:** - \`scheduled_call_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`ScheduledCallResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Sequences ### GET /sequences List Sequences List sequences for the current tenant. **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) - \`is_active\` (query, ) **Responses:** - \`200\`: Successful Response Returns: \`SequenceListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /sequences Create Sequence Create a new sequence. **Request Body:** \`SequenceCreate\` (application/json) - name: string (required) - description: string | null - agent_id: string (required) - phone_number_id: string (required) - active_tag: string | null - continuous_add: boolean (default: True) - steps: array (required) Items: SequenceStep - max_attempts: integer (default: 6) - stop_on_booking: boolean (default: True) - stop_on_reply: boolean (default: False) - operating_hours: OperatingHours | null - template_id: string | null - qualification_criteria: string | null **Responses:** - \`201\`: Successful Response Returns: \`SequenceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /sequences/templates Get Templates List available sequence templates. **Responses:** - \`200\`: Successful Response --- ### POST /sequences/webhook/trigger Webhook Enrollment Trigger GHL workflow triggers enrollment via this webhook. Accepts API key via Authorization header (preferred) or query param (legacy). The Authorization header avoids key exposure in server/proxy access logs. **Parameters:** - \`api_key\` (query, ) — Tenant API key (prefer Authorization header) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /sequences/{sequence_id} Get Sequence Get a sequence by ID. **Parameters:** - \`sequence_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`SequenceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /sequences/{sequence_id} Update Sequence Update a sequence. **Parameters:** - \`sequence_id\` (path, string (required)) **Request Body:** \`SequenceUpdate\` (application/json) - name: string | null - description: string | null - agent_id: string | null - phone_number_id: string | null - active_tag: string | null - continuous_add: boolean | null - steps: array | null - max_attempts: integer | null - stop_on_booking: boolean | null - stop_on_reply: boolean | null - operating_hours: OperatingHours | null - qualification_criteria: string | null **Responses:** - \`200\`: Successful Response Returns: \`SequenceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /sequences/{sequence_id} Delete Sequence Delete a sequence. Must be inactive first. **Parameters:** - \`sequence_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /sequences/{sequence_id}/activate Activate Sequence Activate a sequence. **Parameters:** - \`sequence_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`SequenceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /sequences/{sequence_id}/deactivate Deactivate Sequence Deactivate a sequence. **Parameters:** - \`sequence_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`SequenceResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /sequences/{sequence_id}/enrollments List Enrollments List enrollments for a sequence. **Parameters:** - \`sequence_id\` (path, string (required)) - \`limit\` (query, integer) - \`offset\` (query, integer) - \`status\` (query, ) **Responses:** - \`200\`: Successful Response Returns: \`EnrollmentListResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /sequences/{sequence_id}/enrollments Enroll Contact Enroll a single contact into a sequence. **Parameters:** - \`sequence_id\` (path, string (required)) **Request Body:** \`EnrollmentCreate\` (application/json) - contact_phone: string (required) — E.164 format - contact_name: string | null - contact_email: string | null - contact_id: string | null - timezone: string (default: UTC) **Responses:** - \`201\`: Successful Response Returns: \`EnrollmentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /sequences/{sequence_id}/enrollments/csv Csv Import Bulk enroll contacts from CSV data. **Parameters:** - \`sequence_id\` (path, string (required)) **Request Body:** \`CSVImportRequest\` (application/json) - rows: array (required) — Parsed CSV rows with mapped field names - field_mapping: object (required) — CSV column → schema field mapping **Responses:** - \`200\`: Successful Response Returns: \`CSVImportResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /sequences/{sequence_id}/enrollments/{enrollment_id} Cancel Enrollment Cancel an enrollment. **Parameters:** - \`sequence_id\` (path, string (required)) - \`enrollment_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /sequences/{sequence_id}/enrollments/{enrollment_id}/dispositions Get Enrollment Dispositions Get disposition log for an enrollment. **Parameters:** - \`sequence_id\` (path, string (required)) - \`enrollment_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /sequences/{sequence_id}/stats Get Stats Get enrollment stats for a sequence. **Parameters:** - \`sequence_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`SequenceStats\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Setup ### GET /setup/status Get Setup Status Get setup completion status derived from real tenant data. **Responses:** - \`200\`: Successful Response Returns: \`SetupStatusResponse\` --- ## Share ### GET /share/{slug} Get Public Agent Public endpoint: Get agent info for the demo page. No auth required. **Parameters:** - \`slug\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`PublicAgentResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Stats ### GET /stats Get Dashboard Stats Get dashboard statistics for the current tenant. Returns aggregated stats including: - Total calls this month - Total minutes used this month - Number of active agents - Conversion rate (calls that booked appointments) - Last 5 recent calls - 7-day usage trend **Responses:** - \`200\`: Successful Response Returns: \`DashboardStats\` --- ### GET /stats/analytics Get Analytics Get analytics data for the interactive dashboard. Returns summary stats, daily call volume trends, status/direction breakdowns, and per-agent performance — all in one response. **Parameters:** - \`date_from\` (query, ) — Start date (YYYY-MM-DD) - \`date_to\` (query, ) — End date (YYYY-MM-DD) - \`agent_id\` (query, ) — Filter by agent ID **Responses:** - \`200\`: Successful Response Returns: \`AnalyticsResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Tenants ### GET /tenants/me Get Current Tenant Get current tenant details with usage stats. **Responses:** - \`200\`: Successful Response Returns: \`TenantDetailResponse\` --- ### PATCH /tenants/me Update Tenant Update current tenant settings. Uses get_effective_tenant_id so agency owners editing a sub-account's settings (webhook, etc.) write to the sub-account, not the parent. **Request Body:** \`TenantUpdate\` (application/json) - name: string | null - webhook_url: string | null - webhook_enabled: boolean | null - ghl_conversation_sync_enabled: boolean | null **Responses:** - \`200\`: Successful Response Returns: \`TenantResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /tenants/me/webhook Get Webhook Settings Get webhook configuration for the effective tenant (sub-account aware). **Responses:** - \`200\`: Successful Response Returns: \`WebhookSettingsResponse\` --- ### POST /tenants/me/webhook-test Test Webhook Send a test payload to the configured webhook URL (sub-account aware). **Responses:** - \`200\`: Successful Response --- ## Test ### GET /test/active-sessions List Active Sessions List active voice sessions (for testing). **Responses:** - \`200\`: Successful Response --- ### POST /test/kill-xai/{call_sid} Kill Xai Connection Kill xAI connection to test graceful degradation. **Parameters:** - \`call_sid\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Testing ### GET /testing/agents/{agent_id}/analysis-history Get Analysis History Get historical diagnosis scores for an agent, for trend charting. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /testing/agents/{agent_id}/analyze-calls Analyze Calls Analyze one or more call transcripts with custom criteria. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`AnalyzeCallsRequest\` (application/json) - call_ids: array (required) - criteria: array (default: []) Items: AnalysisCriterion - model: string (default: openai/gpt-4o) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /testing/agents/{agent_id}/analyze-calls-stream Analyze Calls Stream Analyze call transcripts with SSE streaming progress. Returns Server-Sent Events: - progress: {current, total, call_id, status} - call_result: per-call analysis result - call_error: per-call error - complete: final summary - error: fatal error **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`AnalyzeCallsRequest\` (application/json) - call_ids: array (required) - criteria: array (default: []) Items: AnalysisCriterion - model: string (default: openai/gpt-4o) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /testing/agents/{agent_id}/apply-prompt Apply Prompt Apply a prompt suggestion to the agent's system prompt. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`ApplyPromptRequest\` (application/json) - original_text: string (required) - suggested_text: string (required) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /testing/agents/{agent_id}/coaching-plan Generate Coaching Plan Generate a coaching plan from diagnosis findings. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** (application/json) - (object) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /testing/agents/{agent_id}/rewrite-prompt Rewrite Prompt Holistically rewrite the agent's prompt incorporating all suggestions. Returns preview. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`RewritePromptRequest\` (application/json) - suggestions: array (required) — List of suggestion objects from suggest-prompt - model: string (default: openai/gpt-4o) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /testing/agents/{agent_id}/save-rewritten-prompt Save Rewritten Prompt Save an approved rewritten prompt to the agent. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`SaveRewrittenPromptRequest\` (application/json) - rewritten_prompt: string (required) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /testing/agents/{agent_id}/simulate Run Simulation Run a bot-vs-bot simulation against an agent. Returns immediately with running status. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`ScenarioRequest\` (application/json) - scenario_name: string | null - persona: string | null - description: string | null - criteria: array (default: []) Items: ScenarioCriterion - judge_model: string (default: openai/gpt-4o) - simulator_model: string (default: openai/gpt-4o-mini) - max_turns: integer (default: 10) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /testing/agents/{agent_id}/simulations Get Agent Simulations List simulation runs for an agent. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /testing/agents/{agent_id}/suggest-prompt Suggest Prompt Generate prompt improvement suggestions from analysis/simulation results. **Parameters:** - \`agent_id\` (path, string (required)) **Request Body:** \`SuggestPromptRequest\` (application/json) - analysis_ids: array (default: []) — Call analysis IDs to base suggestions on - simulation_id: string | null - failures: array (default: []) — Inline failure data: [{name, reasoning, call_summary}] - model: string (default: openai/gpt-4o) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /testing/agents/{agent_id}/suggested-criteria Get Agent Suggested Criteria Return criteria relevant to this agent's enabled tools and feature flags. **Parameters:** - \`agent_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /testing/byok-keys Get Byok Keys List all BYOK keys for the current tenant (no secrets returned). **Responses:** - \`200\`: Successful Response --- ### POST /testing/byok-keys Create Key Add a new BYOK key. Validates the key before storing. **Request Body:** \`BYOKKeyCreate\` (application/json) - provider: string (required) - api_key: string (required) - label: string (default: ) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /testing/byok-keys/{provider} Remove Key Delete a BYOK key. **Parameters:** - \`provider\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /testing/criteria-library Get Criteria Library Return the full criteria library with categories. Static data, cacheable. **Responses:** - \`200\`: Successful Response --- ### POST /testing/generate-scenario Generate Scenario Generate a simulation scenario from a natural language description using AI. **Request Body:** \`GenerateScenarioRequest\` (application/json) - description: string (required) — Natural language scenario description - model: string (default: openai/gpt-4o) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /testing/scenarios Get Scenarios List available pre-built scenarios. **Responses:** - \`200\`: Successful Response --- ### GET /testing/simulations/{run_id} Get Simulation Get a simulation run by ID (poll for completion). **Parameters:** - \`run_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Text Assistants ### GET /text-assistants List Text Assistants List all text assistants for the current tenant. **Responses:** - \`200\`: Successful Response Returns: \`TextAssistantListResponse\` --- ### POST /text-assistants Create Text Assistant Create a new text assistant. **Request Body:** \`TextAssistantCreate\` (application/json) - name: string (required) - agent_id: string (required) — Link to a voice agent. Required - inherits prompt and functions from agent. - active_tag: string | null — GHL contact tag that activates this assistant - mode: string (default: always_on) - business_hours: object | null - timezone: string (default: America/New_York) - enabled_channels: EnabledChannels | null - human_takeover_timeout_hours: integer (default: 24) - delayed_trigger_enabled: boolean (default: False) - schedule_text_back_enabled: boolean (default: True) - ghl_integration_id: string | null - calendar_integration_id: string | null - calendar_id: string | null - text_model: string (default: claude-haiku-4-5-20251001) — AI model for text message responses **Responses:** - \`201\`: Successful Response Returns: \`TextAssistantResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /text-assistants/wizard/defaults Get Wizard Defaults Get default settings for the text assistant wizard. Returns recommended settings for a text assistant. **Responses:** - \`200\`: Successful Response Returns: \`TextDefaultsResponse\` --- ### POST /text-assistants/wizard/enhance-description Enhance Description Enhance a basic business description using AI. Takes a rough description and makes it more polished and professional while keeping it concise (under 50 words). **Request Body:** \`EnhanceDescriptionRequest\` (application/json) - business_name: string (required) - industry: string (required) - description: string (required) **Responses:** - \`200\`: Successful Response Returns: \`EnhanceDescriptionResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /text-assistants/wizard/generate-all-knowledge Generate All Knowledge Endpoint Generate all knowledge sections at once. This is a convenience endpoint that generates services, pricing, team, and FAQs in a single call. Takes longer but provides everything needed for the assistant prompt. **Request Body:** \`app__text_assistant__prompt_router__GenerateAllKnowledgeRequest\` (application/json) - business_name: string (required) - industry: string (required) - description: string (default: ) — Business description for context **Responses:** - \`200\`: Successful Response Returns: \`GenerateAllKnowledgeResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /text-assistants/wizard/generate-knowledge Generate Knowledge Generate AI suggestions for a specific knowledge section. This endpoint uses xAI to generate content for one section at a time, allowing users to iterate on each section individually. **Sections:** - `services`: Products and services offered - `pricing`: Pricing information - `team`: Team members and roles - `faqs`: Common questions and answers **Request Body:** \`app__text_assistant__prompt_router__GenerateKnowledgeRequest\` (application/json) - business_name: string (required) - industry: string (required) - section: string (required) — Section to generate: services, pricing, team, or faqs - description: string (default: ) — Business description for context - services: string (default: ) — Existing services list (for pricing/faqs context) **Responses:** - \`200\`: Successful Response Returns: \`GenerateKnowledgeResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /text-assistants/wizard/industry-presets Get Industry Presets Get available industry presets. Returns a list of supported industries and their associated suggestions for services and FAQs. **Responses:** - \`200\`: Successful Response Returns: \`IndustryPresetsResponse\` --- ### POST /text-assistants/wizard/preview-prompt Preview Prompt Preview the full generated prompt before creating the text assistant. This builds the complete text assistant prompt from the provided knowledge sections and returns it along with recommended settings. **Request Body:** \`TextPreviewPromptRequest\` (application/json) - business_name: string (required) - assistant_name: string (default: Alex) - industry: string (default: ) - description: string (default: ) - services: string (default: ) - pricing: string (default: ) - team: string (default: ) - faqs: string (default: ) **Responses:** - \`200\`: Successful Response Returns: \`TextPreviewPromptResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /text-assistants/{assistant_id} Get Text Assistant Get a specific text assistant. **Parameters:** - \`assistant_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`TextAssistantResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### PATCH /text-assistants/{assistant_id} Update Text Assistant Update a text assistant. **Parameters:** - \`assistant_id\` (path, string (required)) **Request Body:** \`TextAssistantUpdate\` (application/json) - name: string | null - agent_id: string | null - is_active: boolean | null - active_tag: string | null — GHL contact tag that activates this assistant - mode: string | null - business_hours: object | null - timezone: string | null - enabled_channels: EnabledChannels | null - human_takeover_timeout_hours: integer | null - delayed_trigger_enabled: boolean | null - schedule_text_back_enabled: boolean | null - ghl_integration_id: string | null - calendar_integration_id: string | null - calendar_id: string | null - text_model: string | null - followup_config: object | null **Responses:** - \`200\`: Successful Response Returns: \`TextAssistantResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### DELETE /text-assistants/{assistant_id} Delete Text Assistant Delete a text assistant. **Parameters:** - \`assistant_id\` (path, string (required)) **Responses:** - \`204\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /text-assistants/{assistant_id}/send Send Outbound Text Send an outbound text message via this assistant. **Parameters:** - \`assistant_id\` (path, string (required)) **Request Body:** \`OutboundTextSendRequest\` (application/json) - phone_number: string | null - ghl_contact_id: string | null - message: string | null - ai_generate: boolean (default: False) - ai_context: string | null - channel: string (default: sms) **Responses:** - \`200\`: Successful Response Returns: \`OutboundTextSendResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /text-assistants/{assistant_id}/tag-contact-count Get Tag Contact Count Get the count of GHL contacts with this assistant's active tag. **Parameters:** - \`assistant_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /text-assistants/{assistant_id}/toggle Toggle Text Assistant Toggle text assistant active status. **Parameters:** - \`assistant_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response Returns: \`TextAssistantResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Text Followup ### GET /text-followup/activity List Activity List follow-up activity for the monitoring page. **Parameters:** - \`limit\` (query, integer) - \`offset\` (query, integer) - \`status\` (query, ) **Responses:** - \`200\`: Successful Response Returns: \`FollowUpActivityResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /text-followup/activity/{job_id}/cancel Cancel Job Manually cancel a pending follow-up job. **Parameters:** - \`job_id\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Tools ### POST /tools/scrape-website Scrape Website Endpoint Scrape a website and extract structured business information. Uses Jina Reader for scraping and xAI for AI extraction. **Request Body:** \`ScrapeWebsiteRequest\` (application/json) - url: string (required) — Website URL to scrape **Responses:** - \`200\`: Successful Response Returns: \`ScrapeWebsiteResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /tools/screenshot Screenshot Endpoint Capture a website screenshot and upload to storage. Uses ScreenshotOne API for capture and Supabase Storage for hosting. **Request Body:** \`ScreenshotRequest\` (application/json) - url: string (required) — Website URL to screenshot - width: integer (default: 1280) - height: integer (default: 800) - full_page: boolean (default: False) **Responses:** - \`200\`: Successful Response Returns: \`ScreenshotResponse\` - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Voice Samples ### GET /voice-samples/ List Voice Samples List all available voice samples. Returns: List of available voice names with URLs **Responses:** - \`200\`: Successful Response --- ### GET /voice-samples/gemini/{voice}.mp3 Get Gemini Voice Sample Serve pre-generated Gemini voice sample MP3. **Parameters:** - \`voice\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /voice-samples/openai/{voice}.mp3 Get Openai Voice Sample Serve pre-generated OpenAI voice sample MP3. **Parameters:** - \`voice\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /voice-samples/premium/{voice}.mp3 Get Premium Voice Sample Serve pre-generated ElevenLabs voice sample MP3. **Parameters:** - \`voice\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /voice-samples/{voice}.mp3 Get Voice Sample Serve pre-generated Standard voice sample MP3. **Parameters:** - \`voice\` (path, string (required)) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Webhooks ### GET /webhooks/events List Webhook Events Return a manifest of all supported webhook event types with payload schemas. Requires authentication (session or API key). **Responses:** - \`200\`: Successful Response --- ### POST /webhooks/ghl/app-install Handle App Install Handle GHL AppInstall webhook (marketplace lifecycle). NOTE: GHL marketplace lifecycle webhooks do NOT include signature headers, so this endpoint does not use verify_ghl_signature. This is expected GHL behavior — only conversation/message webhooks are signed. Logs the install event and reactivates existing integrations if found. New integrations are NOT created here — the existing OAuth flow handles creating the integration record with proper tenant_id and tokens. Always returns 200 to prevent GHL retries. **Responses:** - \`200\`: Successful Response --- ### POST /webhooks/ghl/app-uninstall Handle App Uninstall Handle GHL AppUninstall webhook (marketplace lifecycle). NOTE: GHL marketplace lifecycle webhooks do NOT include signature headers, so this endpoint does not use verify_ghl_signature. This is expected GHL behavior — only conversation/message webhooks are signed. Deactivates the integration for the uninstalled location. Always returns 200 to prevent GHL retries. **Responses:** - \`200\`: Successful Response --- ### POST /webhooks/ghl/conversations Handle Ghl Message Handle GHL InboundMessage webhooks. Flow: 1. Verify webhook signature 2. Find tenant by GHL location 3. Check if AI should respond 4. Add to debounce queue 5. Return 200 immediately Note: Always return 200 to prevent GHL retries. **Responses:** - \`200\`: Successful Response --- ### POST /webhooks/ghl/conversations/human-takeover Handle Human Takeover Handle OutboundMessage webhooks to detect human staff replies. When a human staff member sends a message, pause AI for that conversation. **Responses:** - \`200\`: Successful Response --- ### POST /webhooks/stripe Handle Stripe Webhook Handle incoming Stripe webhook events. Security checks (in order): 1. Verify signature header exists 2. Verify webhook secret is configured 3. Validate timestamp (CRIT-005 - replay protection) 4. Verify signature using Stripe SDK 5. Check deduplication (CRIT-003 - idempotency) 6. Validate required fields (CRIT-004) 7. Process event **Responses:** - \`200\`: Successful Response --- ### POST /webhooks/twilio/{tenant_id}/amd-status Handle Amd Status Handle AMD (Answering Machine Detection) results from Twilio. Called asynchronously by Twilio when AMD determines whether a human or machine answered the outbound call. AnsweredBy values: - human: A person answered - machine_start: Voicemail detected (haven't waited for beep) - machine_end_beep: Voicemail beep detected - machine_end_silence: Voicemail silence detected - machine_end_other: Voicemail ended another way - fax: Fax machine detected - unknown: Unable to determine Based on agent's amd_voicemail_behavior, we either: - hangup: Immediately end the call - static_message: Play pre-configured voicemail message - dynamic_message: Play message with {{variable}} substitution - agent_decides: Let the AI agent handle it (no action here) **Parameters:** - \`tenant_id\` (path, string (required)) - \`x-twilio-signature\` (header, ) **Request Body:** \`Body_handle_amd_status_webhooks_twilio__tenant_id__amd_status_post\` (application/x-www-form-urlencoded) - CallSid: string (required) - AnsweredBy: string (required) - MachineDetectionDuration: string (default: 0) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /webhooks/twilio/{tenant_id}/recording Handle Recording Ready Handle recording completion callback from Twilio. Updates the call log with the recording URL. **Parameters:** - \`tenant_id\` (path, string (required)) - \`x-twilio-signature\` (header, ) **Request Body:** \`Body_handle_recording_ready_webhooks_twilio__tenant_id__recording_post\` (application/x-www-form-urlencoded) - CallSid: string (required) - RecordingUrl: string (required) - RecordingDuration: string (default: 0) - RecordingSid: string (required) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /webhooks/twilio/{tenant_id}/sms Handle Incoming Sms Handle inbound SMS/MMS from Twilio. MMS attachments (images, voice notes) are extracted from the variable-count MediaUrl{N}/MediaContentType{N} form fields Twilio sends and passed to _process_incoming_sms for analysis via BYOK OpenAI/Anthropic. Voice-only MMS (empty Body + audio attachment) are processed after transcription. **Parameters:** - \`tenant_id\` (path, string (required)) - \`x-twilio-signature\` (header, ) **Request Body:** \`Body_handle_incoming_sms_webhooks_twilio__tenant_id__sms_post\` (application/x-www-form-urlencoded) - From: string (required) - To: string (required) - Body: string (default: ) - MessageSid: string (required) - AccountSid: string (default: ) - NumMedia: string (default: 0) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /webhooks/twilio/{tenant_id}/status Handle Call Status Handle call status updates from Twilio. Updates the call log with status changes and duration when call completes. **Parameters:** - \`tenant_id\` (path, string (required)) - \`x-twilio-signature\` (header, ) **Request Body:** \`Body_handle_call_status_webhooks_twilio__tenant_id__status_post\` (application/x-www-form-urlencoded) - CallSid: string (required) - CallStatus: string (required) - CallDuration: string | null **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /webhooks/twilio/{tenant_id}/voice Handle Incoming Voice Handle voice calls from Twilio (both inbound and outbound). For inbound: Twilio calls us when someone dials our number For outbound: Twilio calls us after we initiate via REST API Returns TwiML to connect the call to our Media Streams WebSocket. **Parameters:** - \`tenant_id\` (path, string (required)) - \`x-twilio-signature\` (header, ) **Request Body:** \`Body_handle_incoming_voice_webhooks_twilio__tenant_id__voice_post\` (application/x-www-form-urlencoded) - CallSid: string (required) - From: string (required) - To: string (required) - CallStatus: string (default: ringing) - Direction: string (default: inbound) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### GET /webhooks/twilio/{tenant_id}/whisper/{call_sid} Handle Whisper Serve whisper TwiML to Twilio when transfer recipient answers. Generates a 2-3 sentence AI summary of the call transcript and returns it as TwiML. Falls back to empty response on any error. **Parameters:** - \`tenant_id\` (path, string (required)) - \`call_sid\` (path, string (required)) - \`x-twilio-signature\` (header, ) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ### POST /webhooks/twilio/{tenant_id}/whisper/{call_sid} Handle Whisper Serve whisper TwiML to Twilio when transfer recipient answers. Generates a 2-3 sentence AI summary of the call transcript and returns it as TwiML. Falls back to empty response on any error. **Parameters:** - \`tenant_id\` (path, string (required)) - \`call_sid\` (path, string (required)) - \`x-twilio-signature\` (header, ) **Responses:** - \`200\`: Successful Response - \`422\`: Validation Error Returns: \`HTTPValidationError\` --- ## Schemas ### APIKeyCreate Request to create a new API key. - name: string (default: Default API Key) - expires_in_days: integer | null ### APIKeyCreateResponse Response after creating an API key (includes plaintext key ONCE). - id: string (required) - name: string (required) - key_prefix: string (required) - plaintext_key: string (required) - created_at: string (required) - expires_at: string | null ### APIKeyListResponse List of API keys. - keys: array (required) Items: APIKeyResponse - total: integer (required) ### APIKeyResponse API key response (without the actual key). - id: string (required) - name: string (required) - key_prefix: string (required) - created_at: string (required) - last_used_at: string | null - is_active: boolean (default: True) - expires_at: string | null ### AcceptInviteRequest Request body for accepting a sub-account invite. - token: string (required) - password: string (required) — Minimum 6 characters (Supabase requirement) ### AcceptOutboundTermsRequest Request: accept outbound calling terms. - terms_version: string (default: 1.0) ### AdminDashboardResponse Aggregated admin dashboard metrics. - stripe: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - sentry: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - ga4: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - meta: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - render: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - twilio: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - xai: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - elevenlabs: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - gemini: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - openai: object (required) — Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) - user_stats: object (required) ### AffiliateCodeResponse Response containing affiliate code and URL. - affiliate_code: string (required) - affiliate_url: string (required) ### AffiliateReferral Single referral record with commission info. - id: string (required) - referred_tenant_name: string (required) - subscription_plan: string | null (required) - commission_cents: integer (required) - status: string (required) - created_at: string (required) ### AffiliateStatsResponse Complete affiliate dashboard data. - affiliate_code: string (required) - affiliate_url: string (required) - total_referrals: integer (required) - active_referrals: integer (required) - total_earned_cents: integer (required) - pending_payout_cents: integer (required) - referrals: array (required) Items: AffiliateReferral ### AgencyIntegrationsResponse List of agency's integrations available for assignment. - integrations: array (required) Items: IntegrationInfo - total_count: integer (required) ### AgencyOverview Agency dashboard overview stats. - total_sub_accounts: integer (required) - active_sub_accounts: integer (required) - suspended_sub_accounts: integer (required) - total_agents: integer (required) - total_calls: integer (required) - total_minutes: number (required) - total_texts: integer (default: 0) - total_margin_cents: integer (required) - total_revenue_cents: integer (default: 0) - total_cost_cents: integer (default: 0) - avg_margin_pct: number (default: 0.0) - total_booked: integer (default: 0) - conversion_rate: number (default: 0.0) - calls_by_direction: object (default: {}) - top_sub_accounts: array (default: []) Items: app__agency__schemas__SubAccountSummary - daily_trend: array (default: []) Items: DailyAgencyTrend - usage_by_provider: array (default: []) Items: ProviderBreakdown ### AgentBreakdown Per-agent aggregated stats. - agent_id: string (required) - agent_name: string (required) - calls: integer (default: 0) - minutes: number (default: 0.0) - booked: integer (default: 0) - conversion_rate: number (default: 0.0) ### AgentCreate Request body for creating an agent. - name: string (required) - system_prompt: string (required) - greeting: string | null - greeting_outbound: string | null - voice: string (default: ara) - temperature: number (default: 0.7) - business_name: string | null - industry: string | null - ghl_phone_number: string | null - calendar_provider: string | null — Calendar provider: 'gohighlevel' - calendar_integration_id: string | null — Which GHL integration to use (for multi-account support) - calendar_id: string | null — Calendar ID from provider - tools_enabled: array | null — List of enabled tool names (e.g., ['end_call', 'book_appointment']) - timezone: string (default: America/New_York) — IANA timezone (e.g., America/New_York, America/Los_Angeles) - vad_threshold: number (default: 0.65) — VAD sensitivity (0.0-1.0, higher = less sensitive) - vad_silence_duration_ms: integer (default: 500) — Silence duration before ending turn (ms) - vad_prefix_padding_ms: integer (default: 300) — Audio capture before speech detection (ms) - enable_web_search: boolean (default: False) — Enable web search capability - enable_x_search: boolean (default: False) — Enable X (Twitter) search - x_search_handles: array | null — Allowed X handles for search (e.g., ['elonmusk', 'xai']) - enable_collections_search: boolean (default: False) — Enable document search from tenant knowledge base - knowledge_base_ids: array — Knowledge Base IDs this agent can search (when enable_collections_search=true) - enable_recording_disclosure: boolean (default: True) — Announce call recording at start of calls (required for two-party consent states) - enable_contact_intelligence: boolean (default: False) — Fetch caller context (GHL contact + call history) before answering - ai_speaks_first: boolean (default: True) — If true, AI greets caller immediately. If false, AI waits for caller to speak first. - ai_speaks_first_outbound: boolean (default: True) — If true, AI greets recipient immediately on outbound calls. - prompt_includes_contact_intelligence: boolean (default: False) — True if prompt includes Caller Intelligence section for using pre-call context - voice_provider: string (default: xai) — Voice provider: 'xai' (Grok), 'elevenlabs' (ElevenLabs), 'openai' (OpenAI), or 'gemini' (Gemini) - gemini_voice: string (default: Puck) — Gemini prebuilt voice name (30 options) - gemini_start_sensitivity: string (default: low) — Gemini start-of-speech sensitivity: low (ignores noise) or high (reacts to everything) - gemini_end_sensitivity: string (default: high) — Gemini end-of-speech sensitivity: low (patient, waits for clear silence) or high (quick cutoff). WARNING: LOW on 8kHz telephony audio causes 15-30s latency spikes. - gemini_thinking_level: string (default: none) — Gemini 3.1 thinking level: none (off, fastest), minimal (very light), low (basic reasoning), medium, high (most thorough, adds latency). - gemini_language_code: string | null — BCP-47 language code hint for Gemini speech (e.g., 'en-US', 'es-US', 'fr-FR'). None = auto-detect. - gemini_affective_dialog: boolean (default: False) — Enable emotion/tone awareness in Gemini responses (Preview feature) - gemini_proactive_audio: boolean (default: False) — Allow Gemini to stay silent when no clear request is made (Preview feature) - gemini_top_k: integer | null — Gemini top-K sampling: number of top tokens considered (1-100, None=model default) - gemini_top_p: number | null — Gemini top-P nucleus sampling threshold (0.0-1.0, None=model default) - openai_voice: string (default: alloy) — OpenAI voice ID (alloy, ash, ballad, coral, echo, sage, shimmer, verse) - openai_vad_type: string (default: semantic_vad) — OpenAI VAD type: semantic_vad (AI-based) or server_vad (volume-based) - openai_vad_eagerness: string (default: low) — OpenAI semantic VAD eagerness: low (patient) to high (responsive) - openai_noise_reduction: string (default: far_field) — OpenAI noise reduction: far_field (phone), near_field (mic), or disabled - elevenlabs_voice_id: string | null — ElevenLabs voice ID - elevenlabs_model_id: string (default: gpt-4o-mini) — LLM model ID for ElevenLabs agent (e.g., gpt-4o-mini, claude-3-haiku) - elevenlabs_speed: number (default: 1.0) — Speaking speed for ElevenLabs (0.7-1.2x) - elevenlabs_eagerness: string (default: normal) — Turn-taking eagerness for ElevenLabs: 'low', 'normal', or 'high' - elevenlabs_language: string (default: en) — Language code for ElevenLabs agent (e.g., 'en', 'es', 'fr') - elevenlabs_additional_languages: array — Additional language codes for multilingual support (e.g., ['es', 'fr']) - elevenlabs_stability: number (default: 0.5) — Voice stability for ElevenLabs (0.0=creative, 0.5=natural, 1.0=robust) - elevenlabs_max_duration_seconds: integer | null — Max call duration in seconds for ElevenLabs (None=unlimited, min 60) - elevenlabs_emotion_tags: array | null — Custom emotion tags for ElevenLabs: [{name, description}] - elevenlabs_tool_call_sound: string | null (default: typing) — Sound played during ElevenLabs tool execution: typing, elevator1-4, none - elevenlabs_pre_tool_speech: boolean | null (default: True) — Agent announces action before executing slow tools (ElevenLabs only) - xai_audio_tags: array | null — xAI audio delivery tags: ['[breath]', '[pause]', '', ...] - agent_mode: string (default: inbound) — How this agent handles calls: 'inbound', 'outbound', or 'both' - voice_enabled: boolean (default: True) — Enable voice/phone channel - text_enabled: boolean (default: False) — Enable text/SMS channel - amd_enabled: boolean (default: True) — Enable Twilio AMD for outbound calls ($0.01/call) - amd_voicemail_behavior: string (default: hangup) — Action when voicemail detected: hangup, static_message, dynamic_message, agent_decides - amd_voicemail_message: string | null — Message to leave on voicemail (supports {{variables}} for dynamic_message) - amd_voicemail_audio_url: string | null — Audio file URL to play as voicemail (alternative to TTS) - transfer_targets: array | null — Transfer targets: [{name, number, reason}] - whisper_enabled: boolean (default: False) — Enable AI-generated whisper summary when transferring calls - ghl_tags: array | null — Available tags for GHL add_tag/remove_tag: [{name}] - ghl_remove_tags: array | null — Tag rules for remove_tag: [{name, condition?}] - ghl_workflows: array | null — Available workflows for GHL trigger_workflow: [{id, name, description?}] - ghl_pipelines: array | null — Available pipelines for GHL opportunities: [{id, name, stages: [{id, name}]}] - sms_templates: array | null — SMS templates for send_sms: [{name, content}] - max_call_duration_minutes: integer (default: 30) — Max call duration in minutes (0=unlimited, max 180) - max_silence_seconds: integer (default: 120) — Max silence before ending call in seconds (0=unlimited, max 600) - calendar_configs: array | null — Calendar configurations: [{calendar_id, integration_id, label, provider}] - multi_calendar_behavior: string (default: ask_user) — Multi-calendar behavior: 'ask_user' (present options) or 'auto_first' (book first available) - variable_definitions: array | null — Template variables for prompt substitution: [{name, description?, required?, default_value?}] - tool_instructions: object | null — Per-tool usage instructions: {"tool_name": "instruction text"} - text_model: string (default: claude-haiku-4-5-20251001) — LLM model for text assistant (claude-haiku-4-5-20251001, claude-sonnet-4-6, claude-sonnet-4-5-20250929, claude-opus-4-6, gpt-5.2, gpt-4.1, gpt-4.1-mini, gpt-4.1-nano, gpt-4o, gpt-4o-mini) - channel_pivot_enabled: boolean (default: False) — Auto-send text when outbound call fails (no-answer, busy, voicemail) ### AgentFunctionResponse Response schema for a function attached to a specific agent. - id: string (required) - function_id: string (required) - agent_id: string (required) - is_enabled: boolean (required) - created_at: string (required) - function: object (required) — Response schema for custom function data. - id: string (required) - tenant_id: string (required) - agent_id: string | null - name: string (required) - description: string (required) - parameters: object (required) - webhook_url: string (required) - webhook_method: string (required) - webhook_headers: object (required) - webhook_timeout_ms: integer (required) - is_enabled: boolean (required) - speak_during_execution: boolean (required) - created_at: string (required) - updated_at: string (required) ### AgentFunctionsListResponse Response for listing functions attached to an agent plus available library functions. - attached: array — Functions attached to this agent Items: AgentFunctionResponse - available: array — Library functions not yet attached to this agent Items: CustomFunctionResponse - total_attached: integer (default: 0) - total_available: integer (default: 0) ### AgentListResponse List of agents response. - agents: array (required) Items: AgentResponse - total: integer (required) ### AgentResponse Agent data response. - id: string (required) - tenant_id: string (required) - name: string (required) - is_active: boolean (required) - voice: string (required) - temperature: number (required) - business_name: string | null - industry: string | null - system_prompt: string | null - greeting: string | null - greeting_outbound: string | null - ghl_phone_number: string | null - calendar_provider: string | null - calendar_integration_id: string | null - calendar_id: string | null - tools_enabled: array | null - timezone: string | null (default: America/New_York) - vad_threshold: number | null (default: 0.65) - vad_silence_duration_ms: integer | null (default: 500) - vad_prefix_padding_ms: integer | null (default: 300) - enable_web_search: boolean | null (default: False) - enable_x_search: boolean | null (default: False) - x_search_handles: array | null - enable_collections_search: boolean | null (default: False) - knowledge_base_ids: array | null - enable_recording_disclosure: boolean | null (default: True) - enable_contact_intelligence: boolean | null (default: False) - ai_speaks_first: boolean | null (default: True) - ai_speaks_first_outbound: boolean | null (default: True) - prompt_includes_contact_intelligence: boolean | null (default: False) - voice_provider: string | null (default: xai) - gemini_voice: string | null (default: Puck) - gemini_start_sensitivity: string | null (default: low) - gemini_end_sensitivity: string | null (default: high) - gemini_thinking_level: string | null (default: none) - gemini_language_code: string | null - gemini_affective_dialog: boolean | null (default: False) - gemini_proactive_audio: boolean | null (default: False) - gemini_top_k: integer | null - gemini_top_p: number | null - openai_voice: string | null (default: alloy) - openai_vad_type: string | null (default: semantic_vad) - openai_vad_eagerness: string | null (default: low) - openai_noise_reduction: string | null (default: far_field) - elevenlabs_voice_id: string | null - elevenlabs_model_id: string | null (default: gpt-4o-mini) - elevenlabs_speed: number | null (default: 1.0) - elevenlabs_eagerness: string | null (default: normal) - elevenlabs_language: string | null (default: en) - elevenlabs_additional_languages: array | null - elevenlabs_stability: number | null (default: 0.5) - elevenlabs_max_duration_seconds: integer | null - elevenlabs_emotion_tags: array | null - elevenlabs_agent_id: string | null - elevenlabs_tool_call_sound: string | null (default: typing) - elevenlabs_pre_tool_speech: boolean | null (default: True) - xai_audio_tags: array | null - agent_mode: string | null (default: inbound) - voice_enabled: boolean (default: True) - text_enabled: boolean (default: False) - amd_enabled: boolean | null (default: True) - amd_voicemail_behavior: string | null (default: hangup) - amd_voicemail_message: string | null - amd_voicemail_audio_url: string | null - transfer_targets: array | null - whisper_enabled: boolean | null (default: False) - ghl_tags: array | null - ghl_remove_tags: array | null - ghl_workflows: array | null - ghl_pipelines: array | null - sms_templates: array | null - max_call_duration_minutes: integer | null (default: 30) - max_silence_seconds: integer | null (default: 120) - calendar_configs: array | null - multi_calendar_behavior: string | null (default: ask_user) - variable_definitions: array | null - tool_instructions: object | null - text_model: string | null (default: claude-haiku-4-5-20251001) - channel_pivot_enabled: boolean | null (default: False) - phone_count: integer (default: 0) - text_assistants: array Items: LinkedTextAssistantSummary - created_at: string (required) - updated_at: string (required) ### AgentSummary Agent summary for user detail. - id: string (required) - name: string (required) - is_active: boolean (required) - created_at: string (required) ### AgentUpdate Request body for updating an agent. - name: string | null - system_prompt: string | null - greeting: string | null - greeting_outbound: string | null - voice: string | null - temperature: number | null - is_active: boolean | null - business_name: string | null - industry: string | null - ghl_phone_number: string | null - calendar_provider: string | null - calendar_integration_id: string | null - calendar_id: string | null - tools_enabled: array | null - timezone: string | null - vad_threshold: number | null - vad_silence_duration_ms: integer | null - vad_prefix_padding_ms: integer | null - enable_web_search: boolean | null - enable_x_search: boolean | null - x_search_handles: array | null - enable_collections_search: boolean | null - knowledge_base_ids: array | null - enable_recording_disclosure: boolean | null - enable_contact_intelligence: boolean | null - ai_speaks_first: boolean | null - ai_speaks_first_outbound: boolean | null - prompt_includes_contact_intelligence: boolean | null - voice_provider: string | null — Voice provider: 'xai' (Grok), 'elevenlabs' (ElevenLabs), 'openai' (OpenAI), or 'gemini' (Gemini) - gemini_voice: string | null - gemini_start_sensitivity: string | null - gemini_end_sensitivity: string | null - gemini_thinking_level: string | null - gemini_language_code: string | null - gemini_affective_dialog: boolean | null - gemini_proactive_audio: boolean | null - gemini_top_k: integer | null - gemini_top_p: number | null - openai_voice: string | null - openai_vad_type: string | null - openai_vad_eagerness: string | null - openai_noise_reduction: string | null - elevenlabs_voice_id: string | null - elevenlabs_model_id: string | null - elevenlabs_speed: number | null - elevenlabs_eagerness: string | null - elevenlabs_language: string | null - elevenlabs_additional_languages: array | null - elevenlabs_stability: number | null - elevenlabs_max_duration_seconds: integer | null - elevenlabs_emotion_tags: array | null - elevenlabs_tool_call_sound: string | null - elevenlabs_pre_tool_speech: boolean | null - xai_audio_tags: array | null - agent_mode: string | null — How this agent handles calls - voice_enabled: boolean | null - text_enabled: boolean | null - amd_enabled: boolean | null - amd_voicemail_behavior: string | null - amd_voicemail_message: string | null - amd_voicemail_audio_url: string | null - transfer_targets: array | null - whisper_enabled: boolean | null - ghl_tags: array | null - ghl_remove_tags: array | null - ghl_workflows: array | null - ghl_pipelines: array | null - sms_templates: array | null - max_call_duration_minutes: integer | null - max_silence_seconds: integer | null - calendar_configs: array | null - multi_calendar_behavior: string | null - variable_definitions: array | null - tool_instructions: object | null - text_model: string | null - channel_pivot_enabled: boolean | null ### AllSubAccountAgentsResponse All agents across all sub-accounts (for agency overview). - agents: array (required) Items: SubAccountAgentInfo - total: integer (required) ### AllSubAccountFunctionsResponse All custom functions across all sub-accounts (for agency sharing UI). - functions: array (required) Items: SubAccountFunctionInfo - total: integer (required) ### AnalysisCriterion - name: string (required) - description: string (required) ### AnalyticsKPIs KPI counts for analytics dashboard. - total_users: integer (required) - active_24h: integer (required) - active_7d: integer (required) - at_risk_count: integer (required) ### AnalyticsResponse Single response for the analytics dashboard. - summary: object (required) — Totals for the selected period. - total_calls: integer (default: 0) - total_minutes: number (default: 0.0) - total_cost_cents: integer (default: 0) - conversion_rate: number (default: 0.0) - total_texts: integer (default: 0) - daily_trend: array (required) Items: DailyTrend - status_breakdown: array (required) Items: StatusBreakdown - direction_breakdown: array (required) Items: DirectionBreakdown - agent_breakdown: array (required) Items: AgentBreakdown ### AnalyticsSummary Totals for the selected period. - total_calls: integer (default: 0) - total_minutes: number (default: 0.0) - total_cost_cents: integer (default: 0) - conversion_rate: number (default: 0.0) - total_texts: integer (default: 0) ### AnalyzeCallsRequest Analyze one or more call transcripts. Empty criteria triggers diagnosis mode. - call_ids: array (required) - criteria: array (default: []) Items: AnalysisCriterion - model: string (default: openai/gpt-4o) ### ApplyCouponRequest Request to apply a promotion code to an existing subscription. - promotion_code: string (required) ### ApplyCouponResponse Response after applying a coupon. - success: boolean (required) - discount_description: string (required) ### ApplyPromptRequest Apply a suggestion to the agent's system prompt. - original_text: string (required) - suggested_text: string (required) ### Appointment Schema for a single GHL calendar appointment. - id: string (required) - calendar_id: string (required) - calendar_name: string | null - contact_id: string | null - contact_name: string | null - contact_phone: string | null - title: string | null - start_time: string (required) - end_time: string | null - status: string (required) - notes: string | null ### AppointmentEntry A single appointment entry from GHL. - datetime: string (required) - appointment_id: string (required) ### AppointmentsResponse Response schema for appointments list endpoint. - appointments: array (required) Items: Appointment - total: integer (required) - has_more: boolean (required) - integration_id: string | null ### AssignIntegrationResponse Response after assigning integration to sub-account. - success: boolean (required) - sub_account_id: string (required) - integration_id: string (required) - provider: string (required) - account_name: string | null ### AssignIntegrationsRequest Request to assign multiple integrations to a sub-account. - integration_ids: array (required) ### AssignIntegrationsResponse Response after assigning multiple integrations to sub-account. - success: boolean (required) - sub_account_id: string (required) - assigned: array (required) Items: AssignIntegrationResponse - errors: array (default: []) ### AssignPhoneNumberRequest Request to assign a phone number to a sub-account. - sub_account_id: string | null — Sub-account ID to assign to, or None to unassign ### AttachFunctionRequest Request to attach a library function to an agent. - function_id: string (required) — ID of the function to attach - is_enabled: boolean (default: True) — Whether function is enabled for this agent ### AttachFunctionResponse Response after attaching a function to an agent. - id: string (required) - agent_id: string (required) - function_id: string (required) - is_enabled: boolean (required) - created_at: string (required) ### AuthResponse Full authentication response with tokens, user, and tenant. - access_token: string (required) - refresh_token: string (required) - token_type: string (default: bearer) - expires_in: integer (required) - user: object (required) — User data response. - id: string (required) - email: string (required) - full_name: string | null - role: string (required) - tenant_id: string (required) - created_at: string (required) - is_super_admin: boolean (default: False) - tenant: object (required) — Tenant data response. - id: string (required) - name: string (required) - slug: string (required) - tenant_type: string (required) - plan: string (required) - tier: string | null - agent_limit: integer (required) - sub_account_limit: integer (required) - is_active: boolean (required) - trial_ends_at: string | null - parent_tenant_id: string | null - stripe_subscription_id: string | null - subscription_status: string | null - effective_plan: string | null ### BYOKKeyCreate - provider: string (required) - api_key: string (required) - label: string (default: ) ### Body_create_issue_issues__post - message: string (required) - url: string | null - page_name: string | null - browser_info: string | null - image: string | null ### Body_handle_amd_status_webhooks_twilio__tenant_id__amd_status_post - CallSid: string (required) - AnsweredBy: string (required) - MachineDetectionDuration: string (default: 0) ### Body_handle_call_status_webhooks_twilio__tenant_id__status_post - CallSid: string (required) - CallStatus: string (required) - CallDuration: string | null ### Body_handle_incoming_sms_webhooks_twilio__tenant_id__sms_post - From: string (required) - To: string (required) - Body: string (default: ) - MessageSid: string (required) - AccountSid: string (default: ) - NumMedia: string (default: 0) ### Body_handle_incoming_voice_webhooks_twilio__tenant_id__voice_post - CallSid: string (required) - From: string (required) - To: string (required) - CallStatus: string (default: ringing) - Direction: string (default: inbound) ### Body_handle_recording_ready_webhooks_twilio__tenant_id__recording_post - CallSid: string (required) - RecordingUrl: string (required) - RecordingDuration: string (default: 0) - RecordingSid: string (required) ### Body_parse_csv_knowledge_bases__kb_id__tables_parse_csv_post - file: string (required) ### Body_upload_demo_image_demos__demo_id__upload_image_post - file: string (required) ### Body_upload_document_documents_post - file: string (required) - description: string | null ### Body_upload_favicon_agency_branding_favicon_post - file: string (required) ### Body_upload_kb_document_knowledge_bases__kb_id__documents_post - file: string (required) - description: string | null ### Body_upload_logo_agency_branding_logo_post - file: string (required) ### BrandingSettings Agency branding settings. - company_name: string | null - logo_url: string | null - favicon_url: string | null - primary_color: string (default: #6298B6) - support_email: string | null - support_url: string | null - custom_domain: string | null ### BusinessHoursDay Business hours configuration for a single day. - start: string (default: 09:00) - end: string (default: 17:00) - enabled: boolean (default: True) ### CSVImportRequest Bulk enrollment from CSV data. - rows: array (required) — Parsed CSV rows with mapped field names - field_mapping: object (required) — CSV column → schema field mapping ### CSVImportResponse - enrolled: integer (required) - skipped: integer (required) - errors: array (required) ### CalendarInfo Information about a calendar/event type. - id: string (required) - name: string (required) - provider: string (required) - location_id: string | null - duration_minutes: integer (default: 30) ### CallHistorySummary Summary of a call for contact detail view. - id: string (required) - direction: string (required) - status: string (required) - duration_seconds: integer | null - started_at: string | null - agent_name: string | null - has_transcript: boolean (default: False) - summary: string | null - sentiment: string | null - caller_reason: string | null - appointment_booked: boolean (default: False) ### CallLogListResponse Response schema for listing call logs. - calls: array (required) Items: CallLogResponse - total: integer (required) ### CallLogResponse Response schema for a call log entry. - id: string (required) - tenant_id: string (required) - agent_id: string | null - agent_name: string | null - phone_number_id: string | null - twilio_call_sid: string (required) - direction: string (required) [inbound | outbound | test | demo] - from_number: string (required) - to_number: string (required) - status: string (required) - started_at: string (required) - ended_at: string | null - duration_seconds: integer | null - billable_minutes: integer | null - cost_cents: integer | null - recording_url: string | null - recording_duration_seconds: integer | null - caller_name: string | null - caller_email: string | null - transcript: string | array | null - metadata: object | null - appointment_booked: boolean | null - amd_status: string | null - amd_detection_ms: integer | null - voice_provider: string | null ### ChannelConfig Per-channel configuration with optional account filtering. When accounts is empty, responds to ALL accounts for that channel. When accounts has values, only responds to those specific accounts. - enabled: boolean (default: True) - accounts: array ### ChartDataPoint Single data point for charts. - date: string (required) - value: number (required) ### ChatAssistantBreakdown Per-assistant performance metrics. - assistant_id: string (required) - assistant_name: string (required) - conversations: integer (default: 0) - messages: integer (default: 0) - response_rate: number (default: 0.0) ### ChatDailyTrend A single day's activity for the daily trend chart. - date: string (required) - conversations: integer (default: 0) - messages: integer (default: 0) - ai_messages: integer (default: 0) ### ChatMessage Single chat message in a conversation. - role: string (required) [user | assistant | system] — Message role - content: string (required) — Message content ### ChatStatsResponse Response schema for chat dashboard statistics. - total_conversations: integer (default: 0) - total_messages: integer (default: 0) - total_ai_messages: integer (default: 0) - total_contact_messages: integer (default: 0) - total_human_messages: integer (default: 0) - actions_triggered: integer (default: 0) - appointments_booked: integer (default: 0) - active_conversations: integer (default: 0) - channels: object (default: {}) - time_saved_minutes: number (default: 0.0) - response_rate: number (default: 0.0) - avg_messages_per_conversation: number (default: 0.0) - human_takeover_rate: number (default: 0.0) - daily_trend: array (default: []) Items: ChatDailyTrend - assistant_breakdown: array (default: []) Items: ChatAssistantBreakdown ### CheckSlugRequest Request to check if a slug is available. - slug: string (required) ### CheckSlugResponse Response for slug availability check. - available: boolean (required) - slug: string (required) - message: string | null ### CheckoutRequest Request to create a Stripe Checkout session. - plan: string (required) [payg | starter | agency | pro] - billing_period: string [monthly | annual] (default: monthly) - success_url: string | null - cancel_url: string | null ### CheckoutResponse Response containing Stripe Checkout URL. - checkout_url: string (required) ### ChurnRiskUser User at risk of churn. - id: string (required) - email: string (required) - full_name: string | null - tenant_name: string (required) - last_login: string | null - days_inactive: integer | null ### CollectionStatsResponse Collection statistics response. - collection_id: string | null - xai_collection_id: string | null - name: string (default: Knowledge Base) - document_count: integer (default: 0) - total_bytes: integer (default: 0) - documents_ready: integer (default: 0) - documents_processing: integer (default: 0) - documents_failed: integer (default: 0) ### ContactDetail Full contact detail with call history. - id: string (required) - first_name: string | null - last_name: string | null - phone: string | null - email: string | null - company: string | null - tags: array (default: []) - calls: array (default: []) Items: CallHistorySummary - total_calls: integer (default: 0) - stats: ContactStats | null ### ContactDetailResponse Single contact with full call history. - contact: object (required) — Full contact detail with call history. - id: string (required) - first_name: string | null - last_name: string | null - phone: string | null - email: string | null - company: string | null - tags: array (default: []) - calls: array (default: []) Items: CallHistorySummary - total_calls: integer (default: 0) - stats: ContactStats | null ### ContactIntelligencePromptRequest Request to update prompt with Contact Intelligence instructions. - current_prompt: string (required) — The existing system prompt to modify - action: string (required) — Action to perform: 'add' to inject CI section, 'remove' to strip it ### ContactListItem Contact in the list view. - id: string (required) - first_name: string | null - last_name: string | null - phone: string | null - email: string | null - company: string | null - tags: array (default: []) - total_calls: integer (default: 0) - last_call_at: string | null ### ContactListResponse Paginated contact list response. - contacts: array (required) Items: ContactListItem - total: integer (required) - next_cursor: string | null - next_cursor_timestamp: integer | null - has_more: boolean (default: False) ### ContactPatchRequest Request to update a GHL contact. - add_tags: array (default: []) - remove_tags: array (default: []) - custom_fields: array | null - opportunity_id: string | null - pipeline_stage_id: string | null ### ContactPatchResponse Result of a contact patch operation. - success: boolean (required) - tags_added: array (default: []) - tags_removed: array (default: []) - fields_updated: boolean (default: False) - stage_updated: boolean (default: False) ### ContactStats Aggregate stats for a contact's call history. - total_calls: integer (default: 0) - avg_duration_seconds: number | null - appointments_booked: integer (default: 0) - last_call_at: string | null ### ConversationEvent A single event in the conversation timeline (call or SMS). - id: string (required) - event_type: string (required) - direction: string (required) - occurred_at: string (required) - duration_seconds: integer | null - status: string | null - summary: string | null - agent_name: string | null - content: string | null - channel: string | null ### ConversationTimelineResponse Merged call + SMS timeline for a contact. - contact_phone: string (required) - events: array (required) Items: ConversationEvent - total: integer (required) - sms_included: boolean (required) ### CopyAgentToSubAccountRequest Request body for copying an agent between sub-accounts. - source_tenant_id: string (required) - target_tenant_id: string (required) ### CopyFunctionRequest Request to copy a function to another sub-account (agency feature). - target_tenant_id: string (required) — Target sub-account to copy function to ### CostByDirection Cost breakdown by call direction/type. - direction: string (required) - calls: integer (required) - minutes: integer (required) - cost_cents: integer (required) - revenue_cents: integer (required) - margin_cents: integer (required) ### CostByProvider Cost breakdown by voice provider. - provider: string (required) - provider_label: string (required) - calls: integer (required) - minutes: integer (required) - cost_cents: integer (required) - revenue_cents: integer (required) - margin_cents: integer (required) ### CreateShareLinkRequest Request to create a shareable link. - custom_slug: string | null - expires_in_days: integer | null ### CreateShareLinkResponse Response after creating a share link. - id: string (required) - slug: string (required) - share_url: string (required) - is_active: boolean (required) - expires_at: string | null ### CreateSubAccountRequest Request to create a new sub-account. - name: string (required) - slug: string (required) - admin_email: string | null - admin_name: string | null - per_minute_rate_cents: integer (default: 20) - monthly_platform_fee_cents: integer (default: 0) - billing_start_day: integer (default: 1) - upcharge_by_provider: object | null - test_demo_upcharge_by_provider: object | null - text_upcharge_by_type: object | null ### CreateUserRequest Request to create a new user account. - email: string (required) - password: string (required) - plan: string [starter | pro | agency] (default: starter) - company_name: string | null ### CreateUserResponse Response after creating a user. - id: string (required) - email: string (required) - tenant_id: string (required) - tenant_name: string (required) - plan: string (required) - created_at: string (required) ### CustomFunctionCreate Request body for creating a custom function. - name: string (required) — Function name in snake_case (e.g., check_inventory) - description: string (required) — Description of what the function does (shown to AI) - parameters: object — JSON Schema for function parameters - webhook_url: string (required) — Webhook URL to call (must start with http:// or https://) - webhook_method: string (default: POST) — HTTP method for webhook call - webhook_headers: object — Custom headers to include in webhook request - webhook_timeout_ms: integer (default: 5000) — Timeout for webhook call in milliseconds (1000-30000) - is_enabled: boolean (default: True) — Whether the function is enabled - speak_during_execution: boolean (default: True) — Whether AI should speak while waiting for webhook response ### CustomFunctionResponse Response schema for custom function data. - id: string (required) - tenant_id: string (required) - agent_id: string | null - name: string (required) - description: string (required) - parameters: object (required) - webhook_url: string (required) - webhook_method: string (required) - webhook_headers: object (required) - webhook_timeout_ms: integer (required) - is_enabled: boolean (required) - speak_during_execution: boolean (required) - created_at: string (required) - updated_at: string (required) ### CustomFunctionUpdate Request body for updating a custom function. All fields optional. - name: string | null — Function name in snake_case - description: string | null — Description of what the function does - parameters: object | null — JSON Schema for function parameters - webhook_url: string | null — Webhook URL to call - webhook_method: string | null — HTTP method for webhook call - webhook_headers: object | null — Custom headers to include in webhook request - webhook_timeout_ms: integer | null — Timeout for webhook call in milliseconds - is_enabled: boolean | null — Whether the function is enabled - speak_during_execution: boolean | null — Whether AI should speak while waiting for webhook response ### DailyAgencyTrend Daily aggregated stats for trend chart. - date: string (required) - calls: integer (required) - minutes: number (required) - revenue_cents: integer (required) - cost_cents: integer (required) - margin_cents: integer (required) ### DailyTrend One row per day in the selected range. - date: string (required) - calls: integer (default: 0) - minutes: number (default: 0.0) - cost_cents: integer (default: 0) - booked: integer (default: 0) ### DashboardStats Schema for dashboard statistics response. - total_calls: integer (required) - total_minutes: number (required) - active_agents: integer (required) - conversion_rate: number (required) - recent_calls: array (required) Items: RecentCall - usage_trend: object (required) ### DeletionRequestPayload - reason: string | null ### DemoChatMessage A single message in a demo chat conversation. - role: string (required) - content: string (required) ### DemoChatRequest Request to send a message in a demo text chat. - messages: array (required) Items: DemoChatMessage - dynamic_variables: object | null ### DemoChatResponse Response from the demo text chat endpoint. - messages: array (required) - greeting: string | null ### DemoConfigCreate Request to create a demo config. - agent_id: string (required) - channel: string (required) [phone | sms | web | orb | fb_messenger | ig_messenger | tiktok | whatsapp | fb_lead | ig_lead] - name: string (required) - config: object (default: {}) - after_cta_text: string | null - after_cta_url: string | null - webhook_url: string | null - expires_in_days: integer | null ### DemoConfigListItem Summary for the demo management grid. - id: string (required) - name: string (required) - channel: string (required) - agent_name: string (default: Unknown Agent) - slug: string (required) - config: object (default: {}) - view_count: integer (default: 0) - call_count: integer (default: 0) - created_at: string (required) - expires_at: string | null ### DemoConfigResponse Full demo config response. - id: string (required) - agent_id: string (required) - tenant_id: string (required) - slug: string (required) - name: string (required) - channel: string (required) - config: object (default: {}) - is_active: boolean (default: True) - view_count: integer (default: 0) - call_count: integer (default: 0) - demo_url: string (default: ) - after_cta_text: string | null - after_cta_url: string | null - webhook_url: string | null - created_at: string (required) - updated_at: string (required) - expires_at: string | null ### DemoConfigUpdate Request to update a demo config (all optional). - name: string | null - channel: string | null - config: object | null - is_active: boolean | null - after_cta_text: string | null - after_cta_url: string | null - webhook_url: string | null - expires_in_days: integer | null ### DemoEventCreate Request to track a demo event. - event_type: string (required) - duration_s: integer | null - metadata: object (default: {}) ### DirectionBreakdown Call count grouped by direction. - direction: string (required) - count: integer (default: 0) ### DocumentListResponse List of documents response. - documents: array (required) Items: DocumentResponse - total: integer (required) ### DocumentResponse Document data response. - id: string (required) - tenant_id: string (required) - collection_id: string (required) - xai_document_id: string | null - filename: string (required) - content_type: string (required) - file_size: integer (required) - status: string (required) - error_message: string | null - description: string | null - source_type: string | null - created_at: string (required) - updated_at: string (required) ### EmbedSSORequest Request body for embedded SSO endpoint. - payload: string (required) — Encrypted SSO payload from partner platform ### EmotionTagItem An emotion tag with name and description. - name: string (required) - description: string (required) ### EnabledChannels Per-channel AI enable/disable settings. Supports both legacy boolean format and new ChannelConfig format: - Legacy: {"sms": true, "instagram": false} - New: {"sms": {"enabled": true, "accounts": []}, "instagram": {"enabled": true, "accounts": ["@mybusiness"]}} - sms: boolean | ChannelConfig (default: True) - whatsapp: boolean | ChannelConfig (default: True) - instagram: boolean | ChannelConfig (default: True) - facebook: boolean | ChannelConfig (default: True) - tiktok: boolean | ChannelConfig (default: True) - live_chat: boolean | ChannelConfig (default: True) ### EndTrialResponse Response after ending trial early. - status: string (required) [success | error] - message: string (required) - subscription_status: string | null ### EnhanceDescriptionRequest Request to enhance a business description. - business_name: string (required) - industry: string (required) - description: string (required) ### EnhanceDescriptionResponse Response with enhanced description. - enhanced_description: string (required) ### EnrichedContactDetail Extended contact detail with GHL pipeline + custom field enrichment. - id: string (required) - first_name: string | null - last_name: string | null - phone: string | null - email: string | null - company: string | null - tags: array (default: []) - calls: array (default: []) Items: CallHistorySummary - total_calls: integer (default: 0) - stats: ContactStats | null - pipeline_stage: string | null - pipeline_name: string | null - deal_value: number | null - custom_fields: object (default: {}) - upcoming_appointments: array (default: []) Items: AppointmentEntry - past_appointments: array (default: []) Items: AppointmentEntry ### EnrichedContactDetailResponse Single contact with enriched GHL data. - contact: object (required) — Extended contact detail with GHL pipeline + custom field enrichment. - id: string (required) - first_name: string | null - last_name: string | null - phone: string | null - email: string | null - company: string | null - tags: array (default: []) - calls: array (default: []) Items: CallHistorySummary - total_calls: integer (default: 0) - stats: ContactStats | null - pipeline_stage: string | null - pipeline_name: string | null - deal_value: number | null - custom_fields: object (default: {}) - upcoming_appointments: array (default: []) Items: AppointmentEntry - past_appointments: array (default: []) Items: AppointmentEntry ### EnrollmentCreate - contact_phone: string (required) — E.164 format - contact_name: string | null - contact_email: string | null - contact_id: string | null - timezone: string (default: UTC) ### EnrollmentListResponse - enrollments: array (required) Items: EnrollmentResponse - total: integer (required) ### EnrollmentResponse - id: string (required) - tenant_id: string (required) - sequence_id: string (required) - contact_id: string | null - contact_phone: string (required) - contact_name: string | null - contact_email: string | null - current_step: integer (required) - status: string (required) - next_action_at: string | null - timezone: string (required) - total_calls: integer (required) - total_texts: integer (required) - total_attempts: integer (required) - last_call_outcome: string | null - enrolled_via: string (required) - enrolled_at: string (required) - completed_at: string | null - created_at: string (required) - updated_at: string (required) ### FAQPairCreate A single FAQ pair for creation. - question: string (required) - answer: string (required) ### FAQPairResponse FAQ pair response. - id: string (required) - source_id: string (required) - question: string (required) - answer: string (required) - sort_order: integer (default: 0) - created_at: string (required) - updated_at: string (required) ### FAQPairUpdate Update a single FAQ pair. - question: string | null - answer: string | null - sort_order: integer | null ### FAQSourceCreate Request body for creating an FAQ source. - name: string (required) - pairs: array Items: FAQPairCreate ### FAQSourceResponse FAQ source response with pairs. - id: string (required) - collection_id: string (required) - name: string (required) - source_type: string (default: faq) - pairs: array Items: FAQPairResponse - document_id: string | null - created_at: string (required) - updated_at: string (required) ### FollowUpActivityResponse - jobs: array (required) Items: FollowUpJobResponse - total: integer (required) - pending_count: integer (required) - completed_count: integer (required) - stopped_count: integer (required) - failed_count: integer (required) ### FollowUpJobResponse - id: string (required) - tenant_id: string (required) - text_conversation_id: string (required) - text_assistant_id: string (required) - ghl_conversation_id: string | null - ghl_contact_id: string | null - ghl_location_id: string | null - provider: string (default: ghl) - phone_number_id: string | null - scenario: string (required) - step_number: integer (required) - channel: string (required) - fallback_channel: string | null (required) - scheduled_for: string (required) - status: string (required) - stop_reason: string | null (required) - generated_message: string | null (required) - message_context: string | null (required) - webhook_url: string | null (required) - attempts: integer (required) - last_error: string | null (required) - executed_at: string | null (required) - created_at: string (required) - updated_at: string (required) ### ForgotPasswordRequest Request body for forgot password (sends reset email). - email: string (required) ### FunctionCallEntry A single function call executed during an AI message. - function: string (required) - arguments: object | null - result: object | null - success: boolean | null - timestamp: string | null ### FunctionCallLog A single function call log entry. - function: string (required) — Function name that was called - arguments: object (required) — Arguments passed to the function - result: (required) — Result returned from the function - success: boolean (required) — Whether the function call succeeded - timestamp: string (required) — ISO timestamp of when the call was made ### FunctionForUpdate A custom function to integrate into the prompt. - name: string (required) - description: string (required) - parameters: object ### FunctionLibraryResponse Response schema for the functions library (tenant-level). - functions: array (required) Items: FunctionWithAgentsResponse - total: integer (required) ### FunctionSuggestion A single tool suggestion with reason. - tool_name: string (required) - reason: string (required) ### FunctionTestRequest Request body for testing a custom function's webhook. - arguments: object — Arguments to pass to the function - contact_id: string (default: test-contact-id) — GHL contact ID — always present via Contact Intelligence ### FunctionTestResponse Response schema for function test result. - success: boolean (required) - status_code: integer | null - response_time_ms: number (required) - response_body: ? | null - error: string | null - signature: string | null — HMAC signature that was sent (for verification) ### FunctionWithAgentsResponse Response schema for a function with its attached agents. - id: string (required) - tenant_id: string (required) - name: string (required) - description: string (required) - parameters: object (required) - webhook_url: string (required) - webhook_method: string (required) - webhook_headers: object (required) - webhook_timeout_ms: integer (required) - speak_during_execution: boolean (required) - created_at: string (required) - updated_at: string (required) - agent_count: integer (default: 0) - agents: array ### GHLApiKeyRequest Request schema for connecting GHL with a Private Integration API key. - api_key: string (required) — GHL Private Integration API key - location_id: string (required) — GHL Location ID ### GHLIntegrationInfo Information about a GoHighLevel integration for multi-account selection. - id: string (required) - location_id: string (required) - location_name: string (required) ### GenerateAllKnowledgeResponse Response with all generated knowledge sections. - services: string (required) - pricing: string (required) - team: string (required) - faqs: string (required) ### GenerateExpressiveRequest Request to generate expressive voice configuration. - current_prompt: string (required) — The existing system prompt for context - preset: string | null — Preset style: empathetic_support, high_energy_sales, professional_service, friendly_fun - custom_description: string | null — Free-text description of desired emotional delivery - refinement: string | null — Refinement instruction for a previous result - previous_result: object | null — Previous AI output to refine ### GenerateExpressiveResponse Response with generated expressive voice configuration. - audio_tags: array (required) - emotion_tags: array (required) Items: EmotionTagItem - prompt_section: string (required) - changes_summary: string (required) - updated_prompt: string (required) ### GenerateFAQRequest Request body for AI-generating FAQ pairs from content. - content: string (required) — Content to extract FAQs from - num_pairs: integer (default: 10) ### GenerateFunctionSchemaRequest Request to generate a custom function schema using AI. - description: string (required) — Plain English description of what the function should do - webhook_purpose: string | null — Optional context about where the webhook sends data ### GenerateFunctionSchemaResponse Response with AI-generated function schema. - name: string (required) - description: string (required) - parameters: object (required) - webhook_method: string (required) ### GenerateKnowledgeResponse Response with generated knowledge section. - section: string (required) - suggestion: string (required) ### GenerateScenarioRequest Generate a simulation scenario from a natural language description. - description: string (required) — Natural language scenario description - model: string (default: openai/gpt-4o) ### HTTPValidationError - detail: array Items: ValidationError ### HealthBreakdown Breakdown of health score components. - login_recency: number (default: 0) - usage_volume: number (default: 0) - active_agents: number (default: 0) - call_volume: number (default: 0) - no_issues: number (default: 0) ### HealthScore Health score with status and breakdown. - score: integer (required) - status: string (required) [healthy | warning | at_risk] - breakdown: object (required) — Breakdown of health score components. - login_recency: number (default: 0) - usage_volume: number (default: 0) - active_agents: number (default: 0) - call_volume: number (default: 0) - no_issues: number (default: 0) ### ImportFromUrlRequest Request to import demo config from a website URL. - url: string (required) — Website URL to analyze (e.g., https://example.com) - channel: string (required) [phone | sms | web | orb | fb_messenger | ig_messenger | tiktok | whatsapp | fb_lead | ig_lead] — Demo channel type ### ImportGHLNumbersRequest Request to import GoHighLevel phone numbers. - phone_numbers: array (required) — List of GHL phone numbers to import ### ImportNumbersRequest Request to import one or more phone numbers. - phone_number_sids: array (required) — List of Twilio phone number SIDs to import - configure_sip: boolean (default: True) — DEPRECATED - No longer used (kept for API compatibility) ### ImportWebsiteRequest Request to import business info from a website. - url: string (required) — Website URL to scrape (e.g., https://example.com) ### ImportWebsiteResponse Response with extracted business information. - business_name: string | null - industry: string | null - description: string | null - services: string | null - pricing: string | null - team: string | null - faqs: string | null - urls_scraped: array - partial_success: boolean (default: False) - warnings: array ### IndustryPresetsResponse Response with available industry presets. - industries: array (required) - presets: object (required) ### IntegrationInfo Integration info for assignment. - id: string (required) - provider: string (required) - provider_account_id: string | null - account_name: string | null - location_name: string | null - is_active: boolean (required) - created_at: string (required) ### IntegrationStatus Status of an integration. - id: string (required) - provider: string (required) - is_connected: boolean (required) - is_active: boolean (required) - account_name: string | null - account_id: string | null - expires_at: string | null - calendars: array (default: []) Items: CalendarInfo ### InvoiceItem Stripe invoice item. - id: string (required) - amount_due: integer (required) - amount_paid: integer (required) - status: string (required) - period_start: string (required) - period_end: string (required) - invoice_pdf: string | null ### InvoiceListResponse Response containing list of invoices. - invoices: array (required) Items: InvoiceItem ### IssueReportResponse Issue report response. - id: string (required) - tenant_id: string (required) - user_id: string | null - user_email: string | null - tenant_name: string | null - message: string (required) - url: string | null - page_name: string | null - browser_info: string | null - image_url: string | null - created_at: string (required) - resolved: boolean (required) - resolved_at: string | null ### IssueResolveRequest Request to resolve/unresolve an issue. - resolved: boolean (required) ### KnowledgeBaseCreate Request body for creating a Knowledge Base. - name: string (required) — Name of the Knowledge Base ### KnowledgeBaseListResponse List of Knowledge Bases response. - knowledge_bases: array (required) Items: KnowledgeBaseResponse - total: integer (required) ### KnowledgeBaseResponse Knowledge Base data response. - id: string (required) - tenant_id: string (required) - xai_collection_id: string (required) - name: string (required) - document_count: integer (default: 0) - total_bytes: integer (default: 0) - created_at: string (required) - updated_at: string (required) ### KnowledgeBaseUpdate Request body for updating a Knowledge Base. - name: string (required) — New name for the Knowledge Base ### LinkedAgentSummary Summary of linked agent for display. - id: string (required) - name: string (required) - tools_enabled: array (default: []) ### LinkedTextAssistantSummary Minimal text assistant info returned with agent responses. - id: string (required) - is_active: boolean (required) - enabled_channels: object | null ### LoginRequest Request body for user login. - email: string (required) - password: string (required) ### LogoUploadResponse Response after uploading logo. - logo_url: string (required) - file_size: integer (required) ### MeResponse Response for /auth/me endpoint. - user: object (required) — User data response. - id: string (required) - email: string (required) - full_name: string | null - role: string (required) - tenant_id: string (required) - created_at: string (required) - is_super_admin: boolean (default: False) - tenant: object (required) — Tenant data response. - id: string (required) - name: string (required) - slug: string (required) - tenant_type: string (required) - plan: string (required) - tier: string | null - agent_limit: integer (required) - sub_account_limit: integer (required) - is_active: boolean (required) - trial_ends_at: string | null - parent_tenant_id: string | null - stripe_subscription_id: string | null - subscription_status: string | null - effective_plan: string | null ### MostActiveUser Most active user for leaderboard. - id: string (required) - email: string (required) - full_name: string | null - logins_30d: integer (required) ### NoteCreateRequest Request to create a note on a GHL contact. - body: string (required) ### NoteResponse A single note from GHL. - id: string (required) - body: string (required) - created_at: string | null - created_by: string | null ### NotesListResponse List of notes for a contact. - notes: array (required) Items: NoteResponse - total: integer (required) ### NotificationListResponse Paginated list of notifications. - notifications: array (required) Items: NotificationResponse - total: integer (required) - unread_count: integer (required) ### NotificationResponse Single in-app notification. - id: string (required) - tenant_id: string (required) - type: string (required) - title: string (required) - body: string (required) - metadata: object (default: {}) - is_read: boolean (required) - created_at: string (required) - source_account_name: string | null ### NotificationSettingsResponse Notification settings response with metadata. - email_new_call: boolean (default: True) - email_call_summary: boolean (default: True) - email_low_balance: boolean (default: True) - email_weekly_digest: boolean (default: False) - additional_emails: array - quiet_hours_enabled: boolean (default: False) - quiet_hours_start: string (default: 22:00:00) - quiet_hours_end: string (default: 07:00:00) - quiet_hours_timezone: string (default: America/New_York) - notification_frequency: string [immediate | daily | weekly] (default: immediate) - sms_enabled: boolean (default: False) - id: string (required) - tenant_id: string (required) - created_at: string (required) - updated_at: string (required) ### NotificationSettingsUpdate Request body for updating notification settings. - email_new_call: boolean | null - email_call_summary: boolean | null - email_low_balance: boolean | null - email_weekly_digest: boolean | null - additional_emails: array | null - quiet_hours_enabled: boolean | null - quiet_hours_start: string | null - quiet_hours_end: string | null - quiet_hours_timezone: string | null - notification_frequency: string | null - sms_enabled: boolean | null ### OnboardingProgress Onboarding progress response model. - id: string (required) - tenant_id: string (required) - current_step: integer (default: 1) - completed_steps: array (default: []) - account_type: string | null - business_name: string | null - industry: string | null - ghl_connected: boolean (default: False) - ghl_integration_id: string | null - phone_number_id: string | null - sub_account_id: string | null - agent_id: string | null - deployed: boolean (default: False) - calendar_connected: boolean (default: False) - phone_purchased: boolean (default: False) - agent_created: boolean (default: False) - test_call_completed: boolean (default: False) - completed_at: string | null - created_at: string (required) - updated_at: string (required) ### OperatingHours Business hours constraint for when the sequence can execute steps. - start: string (default: 09:00) — Start time in HH:MM 24h format - end: string (default: 17:00) — End time in HH:MM 24h format - days: array (default: [1, 2, 3, 4, 5]) — ISO weekdays (1=Mon..7=Sun) - timezone: string (default: America/New_York) — IANA timezone for the operating hours ### OutboundCallRequest Request to initiate an outbound call. - to_number: string (required) — Recipient phone number in E.164 format (e.g., +14155551234) - from_phone_number_id: string | null — Specific phone number to call from. If not provided, uses agent's primary number. - ghl_contact_id: string | null — GHL contact ID for pre-flight conversation checks ### OutboundCallResponse Response after initiating an outbound call. - call_id: string (required) — Internal call log ID - call_sid: string (required) — Twilio call SID - status: string (required) — Initial call status - from_number: string (required) — Calling from number - to_number: string (required) — Calling to number - agent_id: string (required) — Agent handling the call - initiated_at: string (required) — When call was initiated ### OutboundComplianceStatus Response: current outbound compliance status for a tenant. - outbound_enabled: boolean (required) - terms_version: string | null - accepted_at: string | null - accepted_by: string | null ### OutboundTextSendRequest Request body for sending an outbound text message. - phone_number: string | null - ghl_contact_id: string | null - message: string | null - ai_generate: boolean (default: False) - ai_context: string | null - channel: string (default: sms) ### OutboundTextSendResponse Response for outbound text send. - success: boolean (required) - messages_sent: integer (required) - messages: array (required) - conversation_id: string | null - contact_id: string | null - channel: string (required) ### PaginatedUsersResponse Paginated list of users with analytics. - items: array (required) Items: UserListItem - total: integer (required) - page: integer (required) - per_page: integer (required) - has_more: boolean (required) ### PendingSignupRequest Request body for Payment-First signup (account created after payment). - email: string (required) - password: string (required) — Minimum 6 characters (Supabase requirement) - company_name: string (required) - plan: string [payg | starter | agency | pro] (default: starter) - billing_period: string [monthly | annual] (default: monthly) - tos_accepted: boolean (default: False) — User must accept Terms of Service and Privacy Policy - affiliate_code: string | null - utm_source: string | null - utm_medium: string | null - utm_campaign: string | null - utm_content: string | null - utm_term: string | null - referrer_url: string | null ### PendingSignupResponse Response with Stripe checkout URL for Payment-First signup. - checkout_url: string (required) ### PhoneNumberListResponse Response schema for listing phone numbers. - phone_numbers: array (required) Items: PhoneNumberResponse - total: integer (required) ### PhoneNumberPurchase Request schema for purchasing a phone number. - phone_number: string (required) — E.164 format: +14155551234 ### PhoneNumberResponse Response schema for a phone number. - id: string (required) - tenant_id: string (required) - twilio_sid: string (required) - phone_number: string (required) - friendly_name: string | null - agent_id: string | null - is_active: boolean (default: True) - monthly_cost_cents: integer (required) - created_at: string (required) - sub_account_name: string | null - sub_account_id: string | null - voice_capable: boolean (default: True) - sms_capable: boolean (default: False) - mms_capable: boolean (default: False) - source: string (default: twilio) - a2p_campaign_id: string | null - a2p_status: string (default: unknown) - a2p_verified_at: string | null - a2p_last_checked: string | null - messaging_enabled: boolean (default: False) - a2p_metadata: object | null ### PhoneNumberSummary Phone number summary for user detail. - id: string (required) - phone_number: string (required) - friendly_name: string | null - created_at: string (required) ### PhoneNumberUpdate Request schema for updating a phone number. - agent_id: string | null — Assign to agent - friendly_name: string | null — Display name ### PlanDistributionItem Plan distribution for donut chart. - label: string (required) - value: integer (required) ### PortalRequest Request to create a Stripe Customer Portal session. - return_url: string | null ### PortalResponse Response containing Stripe Portal URL. - portal_url: string (required) ### PreviewGreetingTTSRequest Request to preview a greeting via TTS. - text: string (required) - voice_provider: string (required) - voice_id: string (required) ### PreviewPromptRequest Request to preview the full generated prompt. - business_name: string (required) - agent_name: string (default: Alex) - industry: string (default: ) - personality: string (default: friendly) - description: string (default: ) - services: string (default: ) - pricing: string (default: ) - team: string (default: ) - faqs: string (default: ) - product_offer: string (default: ) - qualification_criteria: string (default: ) - common_objections: string (default: ) - voice_provider: string (default: xai) - agent_type: string | null - sales_methodology: string | null - cta_type: string | null ### PreviewPromptResponse Response with the full generated prompt and recommended settings. - system_prompt: string (required) - greeting: string (required) - recommended_settings: object (required) ### ProviderBreakdown Usage breakdown by voice provider. - provider: string (required) - provider_label: string (required) - calls: integer (required) - minutes: number (required) - cost_cents: integer (required) - revenue_cents: integer (required) - margin_cents: integer (required) ### ProviderUsage Usage breakdown for a single voice provider. - provider: string (required) - provider_label: string (required) - calls: integer (required) - minutes: number (required) - rate_cents: integer (required) - cost_cents: integer (required) ### PublicAgentResponse Public-facing agent info for the demo page (no sensitive data). - agent_name: string (required) - business_name: string | null - industry: string | null - greeting: string | null - voice: string | null - voice_provider: string | null ### PublicBrandingResponse - company_name: string (required) - logo_url: string | null - favicon_url: string | null - primary_color: string (default: #6298B6) ### PublicCheckoutRequest Request for unauthenticated checkout (Stripe-first signup). - email: string (required) - plan: string (required) [payg | starter | agency | pro] - billing_period: string [monthly | annual] (default: monthly) - affiliate_code: string | null ### PublicDemoResponse Public-facing demo config for the demo page (no sensitive data). - channel: string (required) - config: object (default: {}) - agent_name: string (required) - business_name: string | null - industry: string | null - greeting: string | null - voice: string | null - voice_provider: string | null - after_cta_text: string | null - after_cta_url: string | null - branding: object | null - expires_at: string | null - variable_definitions: array | null ### RecentCall Schema for a recent call in the dashboard. - id: string (required) - from_number: string (required) - duration_seconds: integer | null - status: string (required) - started_at: string (required) - agent_id: string (required) - appointment_booked: boolean (required) ### RefreshTokenRequest Request body for token refresh. - refresh_token: string (required) ### RemoveIntegrationResponse Response after removing an integration from sub-account. - success: boolean (required) - sub_account_id: string (required) - integration_id: string (required) ### ResetPasswordRequest Request body for resetting password with token. - token: string (required) — Password reset token from email link - new_password: string (required) — New password (minimum 6 characters) ### ResourceUsage Usage for a single resource type. - current: integer (required) - limit: integer (required) - remaining: integer (required) - unlimited: boolean (required) ### RewritePromptRequest Holistically rewrite the agent's prompt incorporating all suggestions. - suggestions: array (required) — List of suggestion objects from suggest-prompt - model: string (default: openai/gpt-4o) ### RichTextCreate Request body for creating a rich text source. - name: string (required) - content: string (required) — Rich text / markdown content ### RichTextResponse Rich text source response. - id: string (required) - collection_id: string (required) - name: string (required) - source_type: string (default: rich_text) - content: string (default: ) - document_id: string | null - created_at: string (required) - updated_at: string (required) ### RichTextUpdate Update a rich text source. - name: string | null - content: string | null ### SaveRewrittenPromptRequest Save an approved rewritten prompt to the agent. - rewritten_prompt: string (required) ### ScenarioCriterion - name: string (required) — Criterion name, e.g. 'Appointment Booked' - description: string (required) — What the judge evaluates ### ScenarioRequest Run a simulation with a named scenario or custom config. - scenario_name: string | null - persona: string | null - description: string | null - criteria: array (default: []) Items: ScenarioCriterion - judge_model: string (default: openai/gpt-4o) - simulator_model: string (default: openai/gpt-4o-mini) - max_turns: integer (default: 10) ### ScheduledCallCreate Schema for creating a scheduled call. - agent_id: string (required) - to_phone_number: string (required) — Recipient phone number in E.164 format - scheduled_for: string (required) — When to call (ISO 8601 format, will be stored as UTC) - timezone: string (default: UTC) — User's timezone for display purposes - contact_id: string | null — GHL contact ID if known - contact_name: string | null — Contact name for display - phone_number_id: string | null — Specific phone number to call from (uses agent default if not provided) - is_callback: boolean (default: False) — True if this is a return call - previous_call_log_id: string | null — ID of the call that requested this callback - callback_context: string | null — Summary of previous conversation for context-aware greeting ### ScheduledCallListResponse Response schema for listing scheduled calls. - scheduled_calls: array (required) Items: ScheduledCallResponse - total: integer (required) ### ScheduledCallResponse Response schema for a scheduled call. - id: string (required) - tenant_id: string (required) - agent_id: string | null - agent_name: string | null - phone_number_id: string | null - from_phone_number: string | null - contact_id: string | null - contact_name: string | null - to_phone_number: string (required) - scheduled_for: string (required) - timezone: string (required) - status: string (required) - is_callback: boolean (default: False) - previous_call_log_id: string | null - callback_context: string | null - call_log_id: string | null - attempts: integer (default: 0) - last_error: string | null - dialed_at: string | null - source: string (default: ai_function) - confidence: number (default: 1.0) - created_by: string | null - created_at: string (required) - updated_at: string (required) ### ScheduledCallRetry Schema for retrying a failed scheduled call. - scheduled_for: string | null — New time to schedule. If not provided, schedules immediately. ### ScheduledCallUpdate Schema for updating a scheduled call. - scheduled_for: string | null - timezone: string | null - status: string | null - contact_name: string | null ### ScrapeWebsiteRequest Request to scrape a website and extract business info. - url: string (required) — Website URL to scrape ### ScrapeWebsiteResponse Extracted business information from a website. - business_name: string | null - industry: string | null - description: string | null - services: string | null - pricing: string | null - team: string | null - faqs: string | null - urls_scraped: array ### ScreenshotRequest Request to capture a website screenshot. - url: string (required) — Website URL to screenshot - width: integer (default: 1280) - height: integer (default: 800) - full_page: boolean (default: False) ### ScreenshotResponse Screenshot capture result. - screenshot_url: string (required) - width: integer (required) - height: integer (required) ### SearchRequest Request body for searching documents. - query: string (required) - max_results: integer (default: 5) ### SearchResponse Search results response. - results: array (required) Items: SearchResult - query: string (required) ### SearchResult A single search result. - document_id: string (required) - filename: string (required) - content: string (required) - score: number (required) ### SequenceCreate - name: string (required) - description: string | null - agent_id: string (required) - phone_number_id: string (required) - active_tag: string | null - continuous_add: boolean (default: True) - steps: array (required) Items: SequenceStep - max_attempts: integer (default: 6) - stop_on_booking: boolean (default: True) - stop_on_reply: boolean (default: False) - operating_hours: OperatingHours | null - template_id: string | null - qualification_criteria: string | null ### SequenceListResponse - sequences: array (required) Items: SequenceResponse - total: integer (required) ### SequenceResponse - id: string (required) - tenant_id: string (required) - name: string (required) - description: string | null - agent_id: string (required) - phone_number_id: string (required) - active_tag: string | null - continuous_add: boolean (default: True) - steps: array (required) - max_attempts: integer (required) - stop_on_booking: boolean (required) - stop_on_reply: boolean (required) - is_active: boolean (required) - operating_hours: object | null - template_id: string | null - qualification_criteria: string | null - created_at: string (required) - updated_at: string (required) - agent_name: string | null - phone_number: string | null - enrolled_count: integer (default: 0) - active_count: integer (default: 0) - booked_count: integer (default: 0) - interested_count: integer (default: 0) - qualified_count: integer (default: 0) - not_qualified_count: integer (default: 0) - booking_rate: number (default: 0.0) ### SequenceStats - enrolled_count: integer (required) - active_count: integer (required) - completed_count: integer (required) - booked_count: integer (required) - cancelled_count: integer (required) - opted_out_count: integer (required) - interested_count: integer (default: 0) - qualified_count: integer (default: 0) - not_qualified_count: integer (default: 0) - booking_rate: number (required) ### SequenceStep Single step in a sequence. Stored as JSONB array element. - type: string (required) [call | text | wait | voicemail_drop] - delay_minutes: integer (required) — Minutes to wait before executing this step - message: string | null — Message body (text and voicemail_drop steps) - config: object — Step-specific config ### SequenceUpdate - name: string | null - description: string | null - agent_id: string | null - phone_number_id: string | null - active_tag: string | null - continuous_add: boolean | null - steps: array | null - max_attempts: integer | null - stop_on_booking: boolean | null - stop_on_reply: boolean | null - operating_hours: OperatingHours | null - qualification_criteria: string | null ### SetupStatusResponse Aggregated setup status derived from actual tenant data. - tasks: object (required) - completed_count: integer (required) - total_count: integer (default: 5) - required_complete: boolean (required) - all_complete: boolean (required) ### ShareLinkSummary Summary of a share link for the demo management view. - id: string (required) - agent_id: string (required) - agent_name: string (required) - slug: string (required) - share_url: string (required) - view_count: integer (default: 0) - call_count: integer (default: 0) - created_at: string (required) - expires_at: string | null ### SignupRequest Request body for user signup. - email: string (required) - password: string (required) — Minimum 6 characters (Supabase requirement) - company_name: string (required) - account_type: string [direct | agency] (default: direct) - tos_accepted: boolean (default: False) — User must accept Terms of Service and Privacy Policy ### SourceListResponse List of sources response. - sources: array (required) Items: SourceResponse - total: integer (required) ### SourceMetrics Metrics from a single external source. - source: string (required) - available: boolean (required) - data: object (required) ### SourceResponse Generic source response (for list endpoints). - id: string (required) - collection_id: string (required) - name: string (required) - source_type: string (required) - document_id: string | null - config: object - created_at: string (required) - updated_at: string (required) ### StatusBreakdown Call count grouped by status. - status: string (required) - count: integer (default: 0) ### StepType **Type:** enum **Values:** call | text | wait | voicemail_drop ### StepUpdateRequest Generic step update request. - account_type: string | null - business_name: string | null - industry: string | null - connected: boolean | null - purchased: boolean | null - created: boolean | null - completed: boolean | null - deployed: boolean | null - skipped: boolean | null - agent_id: string | null - ghl_integration_id: string | null - phone_number_id: string | null - sub_account_id: string | null ### SubAccountAgentInfo A lightweight agent summary for the agency cross-account view. - id: string (required) - tenant_id: string (required) - name: string (required) - is_active: boolean (required) - voice_provider: string | null - voice: string | null - phone_count: integer (default: 0) - sub_account_name: string (required) - created_at: string (required) ### SubAccountBillingResponse Sub-account's view of their own billing info. - per_minute_rate_cents: integer (required) - is_suspended: boolean (required) - suspended_reason: string | null - agency_name: string (required) - calls_this_period: integer (required) - minutes_this_period: number (required) - cost_this_period_cents: integer (required) - usage_by_provider: array (default: []) Items: ProviderUsage - text_messages_count: integer (default: 0) - text_messages_cost_cents: integer (default: 0) ### SubAccountFunctionInfo A custom function from a sub-account (for sharing UI). - id: string (required) - name: string (required) - description: string (required) - webhook_url: string (required) - webhook_method: string (required) - created_at: string (required) - sub_account_id: string (required) - sub_account_name: string (required) ### SubAccountIntegrationInfo Integration assigned to a sub-account. - id: string (required) - provider: string (required) - provider_account_id: string | null - account_name: string | null - is_active: boolean (required) - assigned_at: string (required) ### SubAccountIntegrationsResponse Sub-account's assigned integrations. - has_integrations: boolean (required) - integrations: array (default: []) Items: IntegrationInfo - ghl_count: integer (default: 0) - twilio_count: integer (default: 0) ### SubAccountListResponse List of sub-accounts. - sub_accounts: array (required) Items: SubAccountResponse - total_count: integer (required) ### SubAccountResponse Sub-account with billing and stats. - id: string (required) - name: string (required) - slug: string (required) - admin_email: string | null - admin_name: string | null - is_active: boolean (required) - created_at: string (required) - per_minute_rate_cents: integer (required) - monthly_platform_fee_cents: integer (required) - is_suspended: boolean (required) - suspended_reason: string | null - billing_start_day: integer (default: 1) - upcharge_by_provider: object | null - test_demo_upcharge_by_provider: object | null - text_upcharge_by_type: object | null - integrations: array (default: []) Items: SubAccountIntegrationInfo - integration_id: string | null - total_calls: integer (default: 0) - total_minutes: number (default: 0.0) - agents_count: integer (default: 0) - total_texts: integer (default: 0) ### SubscriptionStatus Current subscription status and usage. - plan: string (required) - status: string (required) - current_period_start: string (required) - current_period_end: string (required) - cancel_at_period_end: boolean (required) - white_label_enabled: boolean (default: False) - usage: UsageSummary | null ### SuggestFunctionsRequest Request to get AI-powered function suggestions for an agent. - industry: string (required) — Business industry - agent_mode: string (default: inbound) — Agent mode: inbound, outbound, or both - description: string (default: ) — Business description for context - has_ghl: boolean (default: False) — Whether GoHighLevel CRM is connected - system_prompt: string | null — Existing system prompt for deeper context ### SuggestFunctionsResponse Response with AI-generated function suggestions. - suggestions: array (required) Items: FunctionSuggestion ### SuggestPromptRequest Generate prompt improvements from analysis. - analysis_ids: array (default: []) — Call analysis IDs to base suggestions on - simulation_id: string | null - failures: array (default: []) — Inline failure data: [{name, reasoning, call_summary}] - model: string (default: openai/gpt-4o) ### TableSourceCreate Request body for creating a table source. - name: string (required) - headers: array (required) - table_data: array ### TableSourceResponse Table source response. - id: string (required) - collection_id: string (required) - name: string (required) - source_type: string (default: table) - headers: array - table_data: array - document_id: string | null - created_at: string (required) - updated_at: string (required) ### TableSourceUpdate Update a table source. - name: string | null - headers: array | null - table_data: array | null ### TaskStatus Status of a single setup task. - complete: boolean (required) - detail: string | null ### TenantDetailResponse Detailed tenant response with stats. - id: string (required) - name: string (required) - slug: string (required) - tenant_type: string (required) - plan: string (required) - agent_limit: integer (required) - sub_account_limit: integer (required) - is_active: boolean (required) - trial_ends_at: string | null - created_at: string | null - stats: object (required) — Tenant usage statistics. - total_agents: integer (default: 0) - active_agents: integer (default: 0) - total_phone_numbers: integer (default: 0) - total_calls_this_month: integer (default: 0) - total_minutes_this_month: number (default: 0.0) ### TenantResponse Tenant data response. - id: string (required) - name: string (required) - slug: string (required) - tenant_type: string (required) - plan: string (required) - tier: string | null - agent_limit: integer (required) - sub_account_limit: integer (required) - is_active: boolean (required) - trial_ends_at: string | null - parent_tenant_id: string | null - stripe_subscription_id: string | null - subscription_status: string | null - effective_plan: string | null ### TenantStats Tenant usage statistics. - total_agents: integer (default: 0) - active_agents: integer (default: 0) - total_phone_numbers: integer (default: 0) - total_calls_this_month: integer (default: 0) - total_minutes_this_month: number (default: 0.0) ### TenantUpdate Request body for updating tenant settings. - name: string | null - webhook_url: string | null - webhook_enabled: boolean | null - ghl_conversation_sync_enabled: boolean | null ### TestChatRequest Request for text-based agent testing. - agent_id: string (required) — Agent ID to test - messages: array (required) — Conversation history including new user message Items: ChatMessage ### TestChatResponse Response from text-based agent testing. - message: object (required) — Single chat message in a conversation. - role: string (required) [user | assistant | system] — Message role - content: string (required) — Message content - model: string (required) — Model used (e.g., grok-2-1212) - usage: object | null — Token usage if available - function_calls: array | null — Function calls made during response generation ### TestVoiceRequest Request for voice-based agent testing. - agent_id: string (required) — Agent ID to test - audio_base64: string (required) — Base64-encoded PCM16 audio at 24kHz ### TestVoiceResponse Response from voice-based agent testing. - audio_base64: string (required) — Base64-encoded PCM16 audio at 24kHz from AI - transcript: string (required) — Text transcript of AI response - model: string (required) — Model used (e.g., grok-2-1212) ### TextAssistantCreate Request body for creating a text assistant. Text assistants now REQUIRE linking to a voice agent. The agent provides the AI personality (prompt, temperature, greeting). - name: string (required) - agent_id: string (required) — Link to a voice agent. Required - inherits prompt and functions from agent. - active_tag: string | null — GHL contact tag that activates this assistant - mode: string (default: always_on) - business_hours: object | null - timezone: string (default: America/New_York) - enabled_channels: EnabledChannels | null - human_takeover_timeout_hours: integer (default: 24) - delayed_trigger_enabled: boolean (default: False) - schedule_text_back_enabled: boolean (default: True) - ghl_integration_id: string | null - calendar_integration_id: string | null - calendar_id: string | null - text_model: string (default: claude-haiku-4-5-20251001) — AI model for text message responses ### TextAssistantListResponse List of text assistants response. - assistants: array (required) Items: TextAssistantResponse - total: integer (required) ### TextAssistantResponse Text assistant data response. - id: string (required) - tenant_id: string (required) - name: string (required) - is_active: boolean (required) - agent_id: string | null - linked_agent: LinkedAgentSummary | null - active_tag: string | null - system_prompt: string (required) - greeting_message: string | null - temperature: number (required) - business_name: string | null - industry: string | null - mode: string (required) - business_hours: object (required) - timezone: string (required) - enabled_channels: object (required) - human_takeover_timeout_hours: integer (required) - delayed_trigger_enabled: boolean (required) - schedule_text_back_enabled: boolean (default: True) - ghl_integration_id: string | null - calendar_integration_id: string | null - calendar_id: string | null - text_model: string (default: claude-haiku-4-5-20251001) - followup_config: object | null - created_at: string (required) - updated_at: string (required) ### TextAssistantUpdate Request body for updating a text assistant. Allows changing operational settings and optionally the linked agent. AI personality fields are managed through the linked agent. - name: string | null - agent_id: string | null - is_active: boolean | null - active_tag: string | null — GHL contact tag that activates this assistant - mode: string | null - business_hours: object | null - timezone: string | null - enabled_channels: EnabledChannels | null - human_takeover_timeout_hours: integer | null - delayed_trigger_enabled: boolean | null - schedule_text_back_enabled: boolean | null - ghl_integration_id: string | null - calendar_integration_id: string | null - calendar_id: string | null - text_model: string | null - followup_config: object | null ### TextConversationListResponse Response schema for listing conversations. - conversations: array (required) Items: TextConversationResponse - total: integer (required) ### TextConversationResponse Response schema for a text conversation. - id: string (required) - tenant_id: string (required) - text_assistant_id: string | null - assistant_name: string | null - assistant_names: array | null - ghl_conversation_id: string | null - contact_name: string | null - ghl_contact_id: string | null - channel: string (required) - is_ai_active: boolean (required) - last_inbound_at: string | null - last_outbound_at: string | null - last_human_reply_at: string | null - message_count: integer | null - function_call_count: integer | null - created_at: string (required) - updated_at: string | null ### TextDefaultsResponse Response with default text assistant settings. - defaults: object (required) ### TextMessageListResponse Response schema for listing messages in a conversation. - messages: array (required) Items: TextMessageResponse - total: integer (required) ### TextMessageResponse Response schema for a single text message. - id: string (required) - conversation_id: string (required) - role: string (required) - content: string (required) - function_calls: array | null - channel: string | null - created_at: string (required) ### TextPreviewPromptRequest Request to preview the full generated text assistant prompt. - business_name: string (required) - assistant_name: string (default: Alex) - industry: string (default: ) - description: string (default: ) - services: string (default: ) - pricing: string (default: ) - team: string (default: ) - faqs: string (default: ) ### TextPreviewPromptResponse Response with the full generated prompt and recommended settings. - system_prompt: string (required) - greeting_message: string (required) - recommended_settings: object (required) ### TierLimitsResponse Current tier limits and usage for a tenant. - tier: string (required) - agents: object (required) — Usage for a single resource type. - current: integer (required) - limit: integer (required) - remaining: integer (required) - unlimited: boolean (required) - sub_accounts: object (required) — Usage for a single resource type. - current: integer (required) - limit: integer (required) - remaining: integer (required) - unlimited: boolean (required) - team_members: object (required) — Usage for a single resource type. - current: integer (required) - limit: integer (required) - remaining: integer (required) - unlimited: boolean (required) - share_links: object — Usage for a single resource type. - current: integer (required) - limit: integer (required) - remaining: integer (required) - unlimited: boolean (required) - text_assistant_available: boolean (default: False) - demo_suite_available: boolean (default: False) - voice_rate_cents: integer (default: 0) - premium_voice_rate_cents: integer (default: 0) ### TimelineEvent Timeline event for user history. - event: string (required) - label: string (required) - timestamp: string (required) ### TrialStatusResponse Trial status for dashboard display. - is_trial: boolean (required) - trial_ends_at: string | null (required) - voice_minutes_used: integer (required) - voice_minutes_limit: integer (required) - voice_minutes_remaining: integer (required) - days_remaining: integer (required) - is_exceeded: boolean (required) ### TwilioCredentialsRequest Request schema for connecting Twilio account. - account_name: string (required) — Friendly name for this Twilio account - account_sid: string (required) — Twilio Account SID (ACxxxxxx...) - auth_token: string (required) — Twilio Auth Token ### UnreadCountResponse Lightweight unread count for badge polling. - unread_count: integer (required) ### UpcomingInvoiceResponse Upcoming invoice preview. - has_upcoming: boolean (required) - amount_due: integer | null - amount_due_formatted: string | null - currency: string | null - period_start: string | null - period_end: string | null - lines: array | null ### UpdateBrandingRequest Request to update branding settings. - company_name: string | null - primary_color: string | null - support_email: string | null - support_url: string | null - custom_domain: string | null ### UpdatePromptRequest Request to update an existing system prompt using AI. - current_prompt: string (required) — The existing system prompt to modify - instruction: string (required) — Instructions for how to modify the prompt - functions: array — Optional: custom functions to integrate into the prompt Items: FunctionForUpdate - quick_action: string | null — Special action: 'integrate_functions' or 'condense' ### UpdatePromptResponse Response with the updated system prompt and changes summary. - original_prompt: string (required) - updated_prompt: string (required) - changes_summary: string (required) - changes_made: array (required) ### UpdateSubAccountRequest Request to update a sub-account. - name: string | null - admin_email: string | null - admin_name: string | null - per_minute_rate_cents: integer | null - monthly_platform_fee_cents: integer | null - is_active: boolean | null - billing_start_day: integer | null - upcharge_by_provider: object | null - test_demo_upcharge_by_provider: object | null - text_upcharge_by_type: object | null ### UpdateUserStatusRequest Request to enable/disable a user. - disabled: boolean (required) ### UsageExportRecord Single usage record for export - matches frontend AgencyUsageRecord. - id: string (required) - sub_account_id: string (required) - sub_account_name: string (required) - sub_account_status: string (default: active) - call_log_id: string | null - date: string (required) - time: string | null - direction: string (default: inbound) - minutes: integer (required) - cost_cents: integer (required) - revenue_cents: integer (required) - margin_cents: integer (required) - voice_provider: string (default: xai) ### UsageExportResponse Usage export with records - matches frontend AgencyUsageResponse. - records: array (required) Items: UsageExportRecord - total: integer (required) - summary: object (required) — Summary stats for usage export. - total_calls: integer (required) - total_seconds: integer (required) - total_cost_cents: integer (required) - total_revenue_cents: integer (required) - total_margin_cents: integer (required) - by_provider: array (default: []) Items: CostByProvider - by_direction: array (default: []) Items: CostByDirection ### UsageExportSummary Summary stats for usage export. - total_calls: integer (required) - total_seconds: integer (required) - total_cost_cents: integer (required) - total_revenue_cents: integer (required) - total_margin_cents: integer (required) - by_provider: array (default: []) Items: CostByProvider - by_direction: array (default: []) Items: CostByDirection ### UsageListResponse Response containing list of usage records. - usage_records: array (required) Items: UsageRecord - total_count: integer (required) - total_minutes: number (required) - total_cost_cents: integer (required) - text_messages_count: integer (default: 0) - text_messages_cost_cents: integer (default: 0) ### UsageRecord Individual usage record. - id: string (required) - call_log_id: string | null - minutes: number (required) - rate_cents: integer (required) - total_cents: integer (required) - synced_to_stripe: boolean (required) - created_at: string (required) ### UsageSummary Summary of usage for the current billing period. - current_period_start: string (required) - current_period_end: string (required) - total_minutes: integer (required) - total_cost_cents: integer (required) - calls_count: integer (required) - text_messages_count: integer (default: 0) - text_messages_cost_cents: integer (default: 0) ### UserAnalyticsAggregates Aggregate analytics for dashboard charts. - kpis: object (required) — KPI counts for analytics dashboard. - total_users: integer (required) - active_24h: integer (required) - active_7d: integer (required) - at_risk_count: integer (required) - most_active: array (required) Items: MostActiveUser - plan_distribution: array (required) Items: PlanDistributionItem - churn_risk: array (required) Items: ChurnRiskUser - signups_trend: array (required) Items: ChartDataPoint ### UserDetailCharts Chart data for user detail view. - login_activity: array (required) Items: ChartDataPoint - usage_trend: array (required) Items: ChartDataPoint ### UserDetailResponse Full user detail with analytics. - user: object (required) — User info for detail view. - id: string (required) - email: string (required) - full_name: string | null - role: string (required) - created_at: string (required) - tenant: object (required) — Tenant info for detail view. - id: string (required) - name: string (required) - plan: string (required) - tenant_type: string (required) - is_active: boolean (required) - parent_tenant_id: string | null - stats: object (required) — User statistics summary. - account_age_days: integer (required) - total_minutes: number (required) - total_calls: integer (required) - logins_30d: integer (required) - health: object (required) — Health score with status and breakdown. - score: integer (required) - status: string (required) [healthy | warning | at_risk] - breakdown: object (required) — Breakdown of health score components. - login_recency: number (default: 0) - usage_volume: number (default: 0) - active_agents: number (default: 0) - call_volume: number (default: 0) - no_issues: number (default: 0) - charts: object (required) — Chart data for user detail view. - login_activity: array (required) Items: ChartDataPoint - usage_trend: array (required) Items: ChartDataPoint - agents: array (required) Items: AgentSummary - phone_numbers: array (required) Items: PhoneNumberSummary - sub_accounts: array (required) Items: app__admin__schemas__SubAccountSummary - timeline: array (required) Items: TimelineEvent ### UserDetailTenant Tenant info for detail view. - id: string (required) - name: string (required) - plan: string (required) - tenant_type: string (required) - is_active: boolean (required) - parent_tenant_id: string | null ### UserDetailUser User info for detail view. - id: string (required) - email: string (required) - full_name: string | null - role: string (required) - created_at: string (required) ### UserListItem User row with aggregated metrics for list view. - id: string (required) - email: string (required) - full_name: string | null - role: string (required) - created_at: string (required) - tenant_id: string (required) - tenant_name: string (required) - plan: string (required) - tenant_type: string (required) - is_sub_account: boolean (default: False) - logins_24h: integer (default: 0) - logins_7d: integer (default: 0) - logins_30d: integer (default: 0) - last_login: string | null - production_minutes: number (default: 0) - test_minutes: number (default: 0) - phone_minutes: number (default: 0) - call_count: integer (default: 0) - agent_count: integer (default: 0) - active_agents: integer (default: 0) - phone_numbers: integer (default: 0) - sub_accounts: integer (default: 0) - health_score: integer (required) - health_status: string (required) [healthy | warning | at_risk] - signup_source: string | null - referred_by_code: string | null ### UserResponse User data response. - id: string (required) - email: string (required) - full_name: string | null - role: string (required) - tenant_id: string (required) - created_at: string (required) - is_super_admin: boolean (default: False) ### UserStats User statistics summary. - account_age_days: integer (required) - total_minutes: number (required) - total_calls: integer (required) - logins_30d: integer (required) ### ValidationError - loc: array (required) - msg: string (required) - type: string (required) - input: - ctx: object ### VariableDefinition Definition for a template variable in agent prompts. - name: string (required) — Variable name (alphanumeric, underscore, hyphen) - description: string | null — Description of what this variable represents - required: boolean (default: False) — Whether this variable must be provided at call time - default_value: string | null — Default value if not provided (only for non-required) ### WebCrawlerCreate Request body for creating a web crawler source. - name: string (required) - root_url: string (required) — URL to crawl - schedule_interval: string | null — Recrawl interval: 'daily', 'weekly', 'monthly', or None ### WebCrawlerResponse Web crawler source response. - id: string (required) - collection_id: string (required) - name: string (required) - source_type: string (default: web_crawler) - root_url: string (required) - schedule_interval: string | null - crawl_status: string (default: pending) - pages_found: integer (default: 0) - last_crawled_at: string | null - next_crawl_at: string | null - error_message: string | null - document_id: string | null - created_at: string (required) - updated_at: string (required) ### WebCrawlerScheduleUpdate Update the recrawl schedule for a web crawler. - schedule_interval: string | null — Recrawl interval: 'daily', 'weekly', 'monthly', or None ### WebhookCallContext Optional context to pass to the agent for personalization. - first_name: string | null — Contact's first name - last_name: string | null — Contact's last name - email: string | null — Contact's email - company: string | null — Contact's company - source: string | null — Lead source (e.g., 'GHL Workflow', 'Website Form') - notes: string | null — Additional context for the agent - custom_fields: object | null — Custom key-value pairs ### WebhookSettingsResponse Response for webhook settings. - webhook_url: string | null - webhook_secret: string | null - webhook_enabled: boolean (default: False) - ghl_conversation_sync_enabled: boolean (default: False) ### WebhookTestContact A GHL contact selected by the user to populate the test payload. - id: string (required) - first_name: string | null - last_name: string | null - email: string | null - phone: string | null - company: string | null - tags: array (default: []) ### WebhookTestField A single field definition for webhook test payload generation. - name: string (required) - type: string (required) - enum_values: array | null ### WebhookTestRequest Request body for testing a webhook URL before creating a function. - webhook_url: string (required) — Webhook URL to test - webhook_method: string (default: POST) — HTTP method for webhook call - webhook_headers: object — Custom headers to include in webhook request - webhook_timeout_ms: integer (default: 5000) — Timeout for webhook call in milliseconds - function_name: string | null — Function name to include in test payload - fields: array | null — Configured fields to build sample arguments from - contact: WebhookTestContact | null — GHL contact to populate call_context with real data ### WebhookTriggerRequest Request body for webhook-triggered outbound calls. Supports two formats: - Direct: {"agent_id": "...", "to_number": "..."} (n8n, Zapier, cURL) - GHL: {"customData": {"agent_id": "...", "to_number": "..."}, ...} - agent_id: string (required) — Agent ID to handle the call - to_number: string (required) — Recipient phone number in E.164 format - from_phone_number_id: string | null — Specific phone number to call from - ghl_contact_id: string | null — GHL contact ID for pre-flight conversation checks - context: WebhookCallContext | null — Context to personalize the call (injected into agent prompt) - dynamic_variables: object | null — Variables to substitute in prompt: {'customer_name': 'John', 'order_id': '12345'}. All values must be strings. ### WebhookUrlTestRequest Request to test a webhook URL directly (no demo ID needed). - webhook_url: string (required) - form_fields: array | null ### app__admin__schemas__SubAccountSummary Sub-account summary for user detail. - id: string (required) - name: string (required) - plan: string (required) - created_at: string (required) ### app__agency__schemas__SubAccountSummary Top sub-account stats for agency dashboard. - id: string (required) - name: string (required) - calls: integer (required) - minutes: number (required) - revenue_cents: integer (required) - margin_cents: integer (required) - conversion_rate: number (required) ### app__agents__prompt_router__GenerateAllKnowledgeRequest Request to generate all knowledge sections at once. - business_name: string (required) - industry: string (required) - description: string (default: ) — Business description for context - agent_mode: string (default: inbound) — Agent mode — outbound routes 'team' to objections generator ### app__agents__prompt_router__GenerateKnowledgeRequest Request to generate a knowledge section using AI. - business_name: string (required) - industry: string (required) - section: string (required) — Section to generate: services, pricing, team, or faqs - description: string (default: ) — Business description for context - services: string (default: ) — Existing services list (for pricing/faqs context) - agent_mode: string (default: inbound) — Agent mode — outbound routes 'team' to objections generator ### app__text_assistant__prompt_router__GenerateAllKnowledgeRequest Request to generate all knowledge sections at once. - business_name: string (required) - industry: string (required) - description: string (default: ) — Business description for context ### app__text_assistant__prompt_router__GenerateKnowledgeRequest Request to generate a knowledge section using AI. - business_name: string (required) - industry: string (required) - section: string (required) — Section to generate: services, pricing, team, or faqs - description: string (default: ) — Business description for context - services: string (default: ) — Existing services list (for pricing/faqs context)