{"openapi":"3.1.0","info":{"title":"Bavlio API","description":"Outreach automation API — lead enrichment, email campaigns, LinkedIn automation, and AI agent. Full docs at https://docs.bavlio.com.","version":"1.0.0"},"paths":{"/health":{"get":{"summary":"Root Health Check","description":"Simple health check endpoint for Docker.","operationId":"root_health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/health":{"get":{"tags":["Health"],"summary":"Health Check","description":"Basic health check endpoint.\n\nThis endpoint always returns 200 OK to indicate the service is running.\nIt's used by load balancers for basic liveness checks.\n\nReturns:\n    dict: Simple health status with timestamp","operationId":"health_check_api_v1_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Check Api V1 Health Get"}}}}}}},"/api/v1/api/v1/status":{"get":{"tags":["Health"],"summary":"System Status","description":"Comprehensive system status check.\n\nChecks the status of all critical system components including\nthe workflow engine and Redis cache. Returns appropriate HTTP\nstatus codes based on service health.\n\nHTTP Status Codes:\n- 200: All services healthy or degraded (but operational)\n- 503: Critical services unavailable\n\nReturns:\n    dict: Detailed system status information","operationId":"system_status_api_v1_api_v1_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response System Status Api V1 Api V1 Status Get"}}}}}}},"/api/v1/ready":{"get":{"tags":["Health"],"summary":"Readiness Check","description":"Readiness check endpoint for container orchestration.\n\nThis endpoint checks if the service is ready to accept traffic.\nUnlike the liveness check (/health), this verifies that all\nrequired services are properly initialized.\n\nReturns:\n    dict: Readiness status with service details","operationId":"readiness_check_api_v1_ready_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Readiness Check Api V1 Ready Get"}}}}}}},"/api/v1/auth/verify":{"get":{"tags":["authentication"],"summary":"Verify Token","description":"Verify JWT token and return user information.\n\nThis endpoint validates the JWT token in the Authorization header\nand returns the user information extracted from the token.\n\nArgs:\n    user_info: Authenticated user information from JWT\n\nReturns:\n    Dictionary containing user information:\n    - user_id: User's unique identifier from Supabase\n    - email: User's email address\n    - role: User's role (default: \"user\")\n    - authenticated: Always True for valid tokens\n    - app_metadata: Application-specific metadata\n    - user_metadata: User-specific metadata","operationId":"verify_token_api_v1_auth_verify_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Verify Token Api V1 Auth Verify Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/me":{"get":{"tags":["authentication"],"summary":"Get Current User","description":"Get current user information.\n\nAlias for /verify endpoint for better API consistency.\n\nArgs:\n    user_info: Authenticated user information from JWT\n\nReturns:\n    Dictionary containing user information","operationId":"get_current_user_api_v1_auth_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Current User Api V1 Auth Me Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/welcome-email":{"post":{"tags":["authentication"],"summary":"Send Welcome Email","description":"Send a welcome email to a newly signed-up user.\n\nIdempotent: subsequent calls return {\"status\": \"already_sent\"}.\nFail-open on Redis unavailability (worst case: duplicate email).","operationId":"send_welcome_email_api_v1_auth_welcome_email_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Send Welcome Email Api V1 Auth Welcome Email Post"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/google/picker-config":{"get":{"tags":["Google OAuth"],"summary":"Get Picker Config","description":"Get Google Picker API configuration for frontend.\n\nReturns the necessary configuration for initializing Google Picker\nin the frontend, including API key and client ID.\n\nReturns:\n    Dictionary with picker configuration","operationId":"get_picker_config_api_v1_auth_google_picker_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Get Picker Config Api V1 Auth Google Picker Config Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/google/access-token":{"get":{"tags":["Google OAuth"],"summary":"Get Google Access Token","description":"Get the current Google OAuth access token for the user.\n\nThis endpoint retrieves the user's Google OAuth access token,\nrefreshing it if necessary. The token can be used for Google Picker API.\n\nReturns:\n    Dictionary with access token and token type","operationId":"get_google_access_token_api_v1_auth_google_access_token_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Get Google Access Token Api V1 Auth Google Access Token Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/google/login":{"post":{"tags":["Google OAuth"],"summary":"Google Oauth Login","description":"Initiate Google OAuth flow.\n\nThis endpoint generates a Google OAuth authorization URL for the user\nto authenticate and grant access to their Google Sheets.\n\nReturns:\n    Dictionary with authorization URL and instructions","operationId":"google_oauth_login_api_v1_auth_google_login_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Google Oauth Login Api V1 Auth Google Login Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/google/callback":{"get":{"tags":["Google OAuth"],"summary":"Google Oauth Callback","description":"Handle Google OAuth callback.\n\nThis endpoint is called by Google after the user completes authentication.\nIt exchanges the authorization code for access/refresh tokens and stores them.\n\nArgs:\n    code: Authorization code from Google\n    state: State parameter for validation\n\nReturns:\n    Redirect to frontend with success/error status","operationId":"google_oauth_callback_api_v1_auth_google_callback_get","parameters":[{"name":"code","in":"query","required":true,"schema":{"type":"string","description":"Authorization code from Google","title":"Code"},"description":"Authorization code from Google"},{"name":"state","in":"query","required":true,"schema":{"type":"string","description":"State parameter for CSRF protection","title":"State"},"description":"State parameter for CSRF protection"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/auth/google/logout":{"post":{"tags":["Google OAuth"],"summary":"Google Oauth Logout","description":"Revoke Google OAuth credentials.\n\nThis endpoint revokes the user's Google OAuth tokens and marks them\nas inactive in the database.\n\nReturns:\n    Success message","operationId":"google_oauth_logout_api_v1_auth_google_logout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Google Oauth Logout Api V1 Auth Google Logout Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/auth/google/status":{"get":{"tags":["Google OAuth"],"summary":"Google Oauth Status","description":"Get Google OAuth authentication status.\n\nThis endpoint checks if the user has valid Google OAuth credentials\nand returns their status including expiration and granted scopes.\n\nReturns:\n    Authentication status information","operationId":"google_oauth_status_api_v1_auth_google_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Google Oauth Status Api V1 Auth Google Status Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/usage":{"get":{"tags":["users"],"summary":"Get Usage Dashboard","description":"Get user's current usage statistics and quota information.\n\nThis endpoint returns comprehensive usage data including:\n- Current month's usage and remaining quota\n- Subscription tier and limits\n- Recent processing history\n- Storage usage metrics\n\nArgs:\n    user_info: Authenticated user information from JWT\n    usage_service: Usage tracking service instance\n    limit: Maximum number of history records to return (1-100)\n    offset: Number of history records to skip for pagination\n\nReturns:\n    Dictionary containing:\n    - summary: Current usage summary with quotas and limits\n    - history: List of recent processing jobs\n    - stats: Additional statistics for charts","operationId":"get_usage_dashboard_api_v1_users_usage_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Number of history records to return","default":10,"title":"Limit"},"description":"Number of history records to return"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Number of records to skip","default":0,"title":"Offset"},"description":"Number of records to skip"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Usage Dashboard Api V1 Users Usage Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/users/quota-status":{"get":{"tags":["users"],"summary":"Get Quota Status","description":"Get detailed quota status and recommendations.\n\nThis endpoint provides:\n- Current quota usage and limits\n- Warning levels and enforcement status\n- Upgrade recommendations based on usage\n\nArgs:\n    user_info: Authenticated user information from JWT\n    quota_service: Global quota service instance\n\nReturns:\n    Dictionary containing quota status and recommendations","operationId":"get_quota_status_api_v1_users_quota_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Quota Status Api V1 Users Quota Status Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/credits/balance":{"get":{"tags":["credits"],"summary":"Get Credit Balance","description":"Get current user's credit balance and package information.\n\nReturns comprehensive credit information including:\n- Total credits available\n- Credits used\n- Current active package\n- List of all active credit packages\n\nArgs:\n    current_user: Authenticated user from JWT\n    supabase_service: Supabase service instance\n\nReturns:\n    CreditBalanceResponse with complete credit information\n\nRaises:\n    HTTPException: If unable to retrieve credit balance","operationId":"get_credit_balance_api_v1_credits_balance_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditBalanceResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/credits/estimate":{"post":{"tags":["credits"],"summary":"Estimate Credits","description":"Estimate credit cost for an operation without consuming credits.\n\nProvides cost estimation based on:\n- Operation type\n- Operation count\n- User's current tier (for discounts)\n- Current pricing configuration\n\nArgs:\n    request: Credit estimation request with operation details\n    current_user: Authenticated user\n    supabase_service: Supabase service instance\n\nReturns:\n    CreditEstimateResponse with cost breakdown","operationId":"estimate_credits_api_v1_credits_estimate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditEstimateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditEstimateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/credits/transactions":{"get":{"tags":["credits"],"summary":"Get Credit Transactions","description":"Get credit transaction history for the current user.\n\nReturns detailed transaction log including:\n- Credit consumption events\n- Credit refunds\n- Package purchases\n- Balance adjustments\n\nArgs:\n    limit: Maximum transactions to return\n    offset: Pagination offset\n    operation_type: Optional filter by operation type\n    current_user: Authenticated user\n    supabase_service: Supabase service instance\n\nReturns:\n    JSON response with transaction list","operationId":"get_credit_transactions_api_v1_credits_transactions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Maximum number of transactions","default":20,"title":"Limit"},"description":"Maximum number of transactions"},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Offset for pagination","default":0,"title":"Offset"},"description":"Offset for pagination"},{"name":"operation_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by operation type","title":"Operation Type"},"description":"Filter by operation type"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/api-keys":{"get":{"tags":["API Keys"],"summary":"List Api Keys","description":"List all active API keys for the authenticated user.\n\nReturns key prefixes (not raw keys) and metadata.","operationId":"list_api_keys_api_v1_api_keys_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyListResponse"}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["API Keys"],"summary":"Create Api Key","description":"Create a new API key. Returns the raw key exactly once.\n\nRequires JWT authentication (not API key). This prevents a leaked\nAPI key from being used to mint replacement keys.","operationId":"create_api_key_api_v1_api_keys_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateApiKeyRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiKeyCreatedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/api-keys/{key_id}":{"delete":{"tags":["API Keys"],"summary":"Revoke Api Key","description":"Revoke an API key. The key is soft-deleted and immediately invalidated.\n\nRequires JWT authentication. Ownership is verified server-side.","operationId":"revoke_api_key_api_v1_api_keys__key_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"key_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Key Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/referral/code":{"get":{"tags":["referral"],"summary":"Get Referral Code","description":"Get or generate the user's referral code.","operationId":"get_referral_code_api_v1_referral_code_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CodeResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/referral/apply":{"post":{"tags":["referral"],"summary":"Apply Referral Code","description":"Apply a referral code to the current user.","operationId":"apply_referral_code_api_v1_referral_apply_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplyResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/referral/stats":{"get":{"tags":["referral"],"summary":"Get Referral Stats","description":"Get referral statistics for the current user.","operationId":"get_referral_stats_api_v1_referral_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatsResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/personalize":{"post":{"tags":["Personalization"],"summary":"Queue personalization request","description":"Queue a personalization request for background processing with enhanced validation and monitoring","operationId":"personalize_email_api_v1_personalize_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BavlioRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationJobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/personalize/bulk":{"post":{"tags":["Personalization"],"summary":"Queue bulk personalization requests","description":"Queue multiple lead-sender pairs for background personalization with enhanced validation","operationId":"bulk_personalize_api_v1_personalize_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkPersonalizationRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationJobResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/personalize/status/{job_id}":{"get":{"tags":["Personalization"],"summary":"Check personalization job status","description":"Get comprehensive status information for a personalization job","operationId":"get_personalization_status_api_v1_personalize_status__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/personalize/result/{job_id}":{"get":{"tags":["Personalization"],"summary":"Get personalization job result","description":"Retrieve the result of a completed personalization job","operationId":"get_personalization_result_api_v1_personalize_result__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BavlioResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/personalize/save-prompt":{"post":{"tags":["Personalization"],"summary":"Save a custom prompt onto a sender profile","description":"Upserts the given prompt into `sender_data.prompts[]` (named slot, default 'saved') AND mirrors it to `sender_data.custom_prompt` atomically. Used from the preview playground when a user wants future campaigns to use their iterated prompt.","operationId":"save_personalization_prompt_api_v1_personalize_save_prompt_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationSavePromptRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Save Personalization Prompt Api V1 Personalize Save Prompt Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/personalize/effective-prompt":{"get":{"tags":["Personalization"],"summary":"Resolve the prompt the playground should boot into","description":"Runs resolve_effective_prompt server-side with default_load_mode=True, returning the user's most-recently-saved named prompt if one exists, else the transitional custom_prompt, else the stock default. Single source of truth for playground boot (plan §4.7).","operationId":"get_effective_prompt_api_v1_personalize_effective_prompt_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sender_profile_id","in":"query","required":true,"schema":{"type":"string","title":"Sender Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationEffectivePromptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/personalize/default-prompt":{"get":{"tags":["Personalization"],"summary":"Fetch the default personalization prompt","description":"Returns the current default system prompt for email generation so the UI can show it as a starting point for user edits.","operationId":"get_default_prompt_api_v1_personalize_default_prompt_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Default Prompt Api V1 Personalize Default Prompt Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/personalize/preview":{"post":{"tags":["Personalization"],"summary":"Sync preview of a personalized email for a single lead","description":"Blocking endpoint. Runs find_commonalities + generate_email inline against the provided lead + sender profile. Returns subject, body, commonality, and the prompt source used. Does not create a campaign, does not queue a job.","operationId":"personalize_preview_api_v1_personalize_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationPreviewRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/personalize/preview/batch":{"post":{"tags":["Personalization"],"summary":"Batch preview (SSE) — up to 25 leads, streams results as they complete","description":"Serial backend processing (no gather) to keep per-lead cache behavior predictable and budget-flat. Streams one SSE `lead_result` event per lead and a final `done` event. Echoes `client_run_id` as `batch_id` on every event so frontends can discard stale events from prior runs.","operationId":"personalize_preview_batch_api_v1_personalize_preview_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchPreviewRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/personalize/generations":{"get":{"tags":["Personalization"],"summary":"List recent generation runs for a given prompt","operationId":"list_generation_runs_api_v1_personalize_generations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sender_profile_id","in":"query","required":true,"schema":{"type":"string","description":"Sender profile UUID","title":"Sender Profile Id"},"description":"Sender profile UUID"},{"name":"prompt_source","in":"query","required":true,"schema":{"enum":["named","custom_prompt"],"type":"string","title":"Prompt Source"}},{"name":"prompt_name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Required when prompt_source='named'; ignored otherwise.","title":"Prompt Name"},"description":"Required when prompt_source='named'; ignored otherwise."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":15,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/personalize/generations/runs/{run_id}":{"get":{"tags":["Personalization"],"summary":"Get a single run + its first 500 per-lead generations","operationId":"get_run_detail_api_v1_personalize_generations_runs__run_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/personalize/generations/runs/{run_id}/leads":{"get":{"tags":["Personalization"],"summary":"Paginated leads list for a single run (for >500-lead runs)","operationId":"get_run_leads_api_v1_personalize_generations_runs__run_id__leads_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","title":"Run Id"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunLeadsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/personalize/datasets":{"get":{"tags":["Personalization"],"summary":"List user's datasets for the inline data-source picker","operationId":"list_user_datasets_api_v1_personalize_datasets_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"include_archived","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Archived"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__routers__generation_history__DatasetListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/create":{"post":{"tags":["Session Management"],"summary":"Create processing session","description":"Create a new processing session with initial sender data","operationId":"create_session_api_v1_sessions_create_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__routers__sessions__management__CreateSessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sessions/datasets/{dataset_id}/new-session":{"post":{"tags":["Session Management"],"summary":"Create session from existing dataset","description":"Create a new session linked to an existing dataset for re-enrichment","operationId":"create_session_from_dataset_api_v1_sessions_datasets__dataset_id__new_session_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSessionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__routers__sessions__management__CreateSessionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/status":{"get":{"tags":["Session Management"],"summary":"Get session status","description":"Retrieve current status and progress information for a session","operationId":"get_session_status_api_v1_sessions__session_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/jobs/{job_id}/status":{"get":{"tags":["Session Management"],"summary":"Get job status","description":"Check the status of a background job associated with a session","operationId":"get_job_status_api_v1_sessions__session_id__jobs__job_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}":{"delete":{"tags":["Session Management"],"summary":"Delete session","description":"Clean up session data and remove all associated resources","operationId":"delete_session_api_v1_sessions__session_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Session Api V1 Sessions  Session Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/sender-data":{"post":{"tags":["Session Management"],"summary":"Update sender data","description":"Add or update sender data for an existing session","operationId":"update_sender_data_api_v1_sessions__session_id__sender_data_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSenderDataRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Sender Data Api V1 Sessions  Session Id  Sender Data Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/sender-data/bulk":{"post":{"tags":["Session Management"],"summary":"Bulk update sender data","description":"Update sender data from multiple sources (JSON objects)","operationId":"bulk_update_sender_data_api_v1_sessions__session_id__sender_data_bulk_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"merge_strategy","in":"query","required":false,"schema":{"type":"string","default":"update","title":"Merge Strategy"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Sender Sources"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderDataUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/leads":{"post":{"tags":["Session Management"],"summary":"Add leads to session","description":"Queue leads for processing in an existing session","operationId":"add_leads_to_session_api_v1_sessions__session_id__leads_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLeadsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Add Leads To Session Api V1 Sessions  Session Id  Leads Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/results":{"get":{"tags":["Session Management"],"summary":"Get session results","description":"Retrieve processing results for a completed or in-progress session","operationId":"get_session_results_api_v1_sessions__session_id__results_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionResultsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sessions/{session_id}/process":{"post":{"tags":["Session Processing"],"summary":"Start session processing","description":"Start background processing of all queued leads in a session","operationId":"start_session_processing_api_v1_sessions__session_id__process_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessingStartResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/datasets/list":{"get":{"tags":["datasets","datasets"],"summary":"List datasets with pagination","description":"Server-side paginated dataset listing with optional pipeline type filter and search","operationId":"list_datasets_api_v1_datasets_list_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"pipeline_type","in":"query","required":false,"schema":{"anyOf":[{"enum":["enrichment","personalization","extraction"],"type":"string"},{"type":"null"}],"description":"Pipeline type filter: enrichment, personalization, extraction, or null for all","title":"Pipeline Type"},"description":"Pipeline type filter: enrichment, personalization, extraction, or null for all"},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by dataset name","title":"Search"},"description":"Search by dataset name"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number (1-indexed)","default":1,"title":"Page"},"description":"Page number (1-indexed)"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page (max 100)","default":20,"title":"Page Size"},"description":"Items per page (max 100)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__routers__datasets__list__DatasetListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/datasets/{dataset_id}/download":{"get":{"tags":["datasets","datasets"],"summary":"Download dataset in specified format","description":"Download dataset rows in CSV, Excel, or JSON format with download tracking","operationId":"download_dataset_api_v1_datasets__dataset_id__download_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}},{"name":"format","in":"query","required":true,"schema":{"type":"string","pattern":"^(csv|excel|json)$","description":"Download format: csv, excel, or json","title":"Format"},"description":"Download format: csv, excel, or json"},{"name":"limit","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":10000,"minimum":1},{"type":"null"}],"description":"Optional row cap for preview/picker callers. When set, applies LIMIT at the database layer so we don't serialize/transfer the full dataset just to slice it client-side. Omit to download the full dataset (existing behavior).","title":"Limit"},"description":"Optional row cap for preview/picker callers. When set, applies LIMIT at the database layer so we don't serialize/transfer the full dataset just to slice it client-side. Omit to download the full dataset (existing behavior)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/datasets/{dataset_id}":{"patch":{"tags":["datasets","datasets"],"summary":"Update dataset metadata","description":"Update dataset fields like dataset_name","operationId":"update_dataset_api_v1_datasets__dataset_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDatasetRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDatasetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/datasets/{dataset_id}/archive":{"post":{"tags":["datasets","datasets"],"summary":"Archive a dataset","description":"Soft-delete a dataset by setting archived_at timestamp","operationId":"archive_dataset_api_v1_datasets__dataset_id__archive_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Archive Dataset Api V1 Datasets  Dataset Id  Archive Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/datasets/{dataset_id}/restore":{"post":{"tags":["datasets","datasets"],"summary":"Restore an archived dataset","description":"Un-archive a dataset by clearing archived_at timestamp","operationId":"restore_dataset_api_v1_datasets__dataset_id__restore_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Restore Dataset Api V1 Datasets  Dataset Id  Restore Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sender-profiles/":{"post":{"tags":["sender-profiles"],"summary":"Create Sender Profile","description":"Create a new sender profile.\n\nCreates a new sender profile for the authenticated user. The profile\nwill be scoped to the user and can only be accessed by them.\n\nMaximum of 5 profiles allowed per user.\n\nThe sender_data can contain ANY fields - there is no predefined schema.\nCommon fields might include full_name, company, role, etc., but you can\ninclude any fields your use case requires.\n\nArgs:\n    profile_data: The sender profile data\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    The created sender profile with generated ID\n\nRaises:\n    HTTPException: If profile creation fails or limit exceeded","operationId":"create_sender_profile_api_v1_sender_profiles__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderProfileCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderProfile"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["sender-profiles"],"summary":"List Sender Profiles","description":"List all sender profiles for the authenticated user.\n\nRetrieves all sender profiles owned by the authenticated user with\noptional pagination. Profiles are sorted by creation date (newest first).\n\nMaximum of 5 profiles per user.\n\nArgs:\n    current_user: Authenticated user information\n    settings: Application settings\n    limit: Maximum number of profiles to return (default: 100)\n    offset: Number of profiles to skip (default: 0)\n\nReturns:\n    List of sender profiles for the user","operationId":"list_sender_profiles_api_v1_sender_profiles__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SenderProfile"},"title":"Response List Sender Profiles Api V1 Sender Profiles  Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sender-profiles/{profile_id}":{"get":{"tags":["sender-profiles"],"summary":"Get Sender Profile","description":"Retrieve a specific sender profile.\n\nRetrieves a sender profile by ID if the authenticated user has access.\n\nArgs:\n    profile_id: The ID of the profile to retrieve\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    The requested sender profile\n\nRaises:\n    HTTPException: If profile not found or access denied","operationId":"get_sender_profile_api_v1_sender_profiles__profile_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderProfile"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["sender-profiles"],"summary":"Update Sender Profile","description":"Update an existing sender profile.\n\nUpdates a sender profile if the authenticated user has access.\nOnly provided fields will be updated - omitted fields remain unchanged.\n\nArgs:\n    profile_id: The ID of the profile to update\n    updates: The fields to update\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    The updated sender profile\n\nRaises:\n    HTTPException: If profile not found or access denied","operationId":"update_sender_profile_api_v1_sender_profiles__profile_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","title":"Profile Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderProfileUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SenderProfile"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["sender-profiles"],"summary":"Delete Sender Profile","description":"Delete a sender profile.\n\nDeletes a sender profile if the authenticated user has access.\n\nArgs:\n    profile_id: The ID of the profile to delete\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    None (204 No Content on success)\n\nRaises:\n    HTTPException: If profile not found or access denied","operationId":"delete_sender_profile_api_v1_sender_profiles__profile_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","title":"Profile Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sender-profiles/search/":{"get":{"tags":["sender-profiles"],"summary":"Search Sender Profiles","description":"Search sender profiles by name.\n\nSearches through the authenticated user's profiles for those matching\nthe search query. Search is case-insensitive and matches partial names.\n\nArgs:\n    query: Search query string\n    current_user: Authenticated user information\n    settings: Application settings\n    limit: Maximum number of profiles to return (default: 20)\n\nReturns:\n    List of matching sender profiles","operationId":"search_sender_profiles_api_v1_sender_profiles_search__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"query","in":"query","required":true,"schema":{"type":"string","title":"Query"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SenderProfile"},"title":"Response Search Sender Profiles Api V1 Sender Profiles Search  Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sender-profiles/default/":{"get":{"tags":["sender-profiles"],"summary":"Get Default Sender Profile","description":"Get the default sender profile for the authenticated user.\n\nRetrieves the user's default profile if one exists.\n\nArgs:\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    The default sender profile or None if no default set","operationId":"get_default_sender_profile_api_v1_sender_profiles_default__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SenderProfile"},{"type":"null"}],"title":"Response Get Default Sender Profile Api V1 Sender Profiles Default  Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"429":{"description":"Too Many Requests - Rate limit exceeded"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sender-profiles/{profile_id}/prompts":{"get":{"tags":["sender-profiles","named-prompts"],"summary":"List Named Prompts","operationId":"list_named_prompts_api_v1_sender_profiles__profile_id__prompts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","title":"Profile Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamedPromptList"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Profile not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["sender-profiles","named-prompts"],"summary":"Create Named Prompt","operationId":"create_named_prompt_api_v1_sender_profiles__profile_id__prompts_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","title":"Profile Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamedPromptCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamedPromptOut"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Profile not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sender-profiles/{profile_id}/prompts/{name}":{"patch":{"tags":["sender-profiles","named-prompts"],"summary":"Update Named Prompt","operationId":"update_named_prompt_api_v1_sender_profiles__profile_id__prompts__name__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","title":"Profile Id"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamedPromptUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NamedPromptOut"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Profile not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["sender-profiles","named-prompts"],"summary":"Delete Named Prompt","operationId":"delete_named_prompt_api_v1_sender_profiles__profile_id__prompts__name__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"profile_id","in":"path","required":true,"schema":{"type":"string","title":"Profile Id"}},{"name":"name","in":"path","required":true,"schema":{"type":"string","title":"Name"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized"},"404":{"description":"Profile not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sender-profile-chat/start":{"post":{"tags":["sender-profile-chat"],"summary":"Start Chat Session","description":"Start a new chat session for creating a sender profile.\n\nInitiates a conversational interface that guides users through\ncreating a comprehensive sender profile.\n\nReturns:\n    Initial chat message with session ID","operationId":"start_chat_session_api_v1_sender_profile_chat_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sender-profile-chat/message":{"post":{"tags":["sender-profile-chat"],"summary":"Send Chat Message","description":"Send a message in the chat session.\n\nProcesses user input and returns the next question or completes\nthe profile creation process.\n\nArgs:\n    request: Chat request with session ID and user message\n\nReturns:\n    Chat response with bot's reply","operationId":"send_chat_message_api_v1_sender_profile_chat_message_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__routers__sender_profile_chat__ChatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChatResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sender-profile-chat/session/{session_id}/history":{"get":{"tags":["sender-profile-chat"],"summary":"Get Chat History","description":"Get the chat history for a session.\n\nReturns all messages in the conversation so far.\n\nArgs:\n    session_id: The chat session ID\n\nReturns:\n    List of chat messages","operationId":"get_chat_history_api_v1_sender_profile_chat_session__session_id__history_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ChatMessage"},"title":"Response Get Chat History Api V1 Sender Profile Chat Session  Session Id  History Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sender-profile-chat/session/{session_id}":{"delete":{"tags":["sender-profile-chat"],"summary":"Cancel Chat Session","description":"Cancel a chat session.\n\nDeletes the session without creating a profile.\n\nArgs:\n    session_id: The chat session ID to cancel\n\nReturns:\n    Confirmation message","operationId":"cancel_chat_session_api_v1_sender_profile_chat_session__session_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Cancel Chat Session Api V1 Sender Profile Chat Session  Session Id  Delete"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment-chat/start":{"post":{"tags":["enrichment-chat"],"summary":"Start Enrichment Chat","description":"Start a new enrichment chat interface with enhanced initialization.\n\nEnhanced version with performance monitoring, better error handling,\nand optimized welcome message generation.\n\nFeatures:\n- Performance monitoring and timing\n- Enhanced error handling and logging\n- Optimized agent integration\n- Response time tracking\n\nReturns:\n    EnrichmentChatResponse: Initial chat message with timing information\n\nRaises:\n    HTTPException: If authentication fails or system error occurs","operationId":"start_enrichment_chat_api_v1_enrichment_chat_start_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentChatResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/enrichment-chat/message":{"post":{"tags":["enrichment-chat"],"summary":"Send Enrichment Message","description":"Send a message in the enrichment chat session with enhanced processing.\n\nEnhanced version with comprehensive validation, monitoring, and optimized\nresource management for enrichment chat interactions.\n\nFeatures:\n- Input validation and sanitization\n- Rate limiting and credit estimation\n- Performance monitoring and logging\n- Comprehensive error handling\n- Processing session integration\n\nArgs:\n    request: Validated chat request with session ID and user message\n    current_user: Authenticated user information\n    enrichment_chat_service: Service for managing chat sessions\n\nReturns:\n    EnrichmentChatResponse: Enhanced response with timing and status information\n\nRaises:\n    HTTPException: For validation errors, rate limits, or processing failures","operationId":"send_enrichment_message_api_v1_enrichment_chat_message_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentChatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentChatResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/enrichment-chat/file-uploaded/{session_id}":{"post":{"tags":["enrichment-chat"],"summary":"Notify File Uploaded","description":"Notify the chat session that a file has been uploaded.\n\nThis endpoint is called when a file is uploaded through the chat interface.\nIt stores the file information in the chat context.\n\nArgs:\n    session_id: The chat session ID (not the processing session ID)\n    file_info: Information about the uploaded file\n\nReturns:\n    Confirmation message","operationId":"notify_file_uploaded_api_v1_enrichment_chat_file_uploaded__session_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"File Info"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Notify File Uploaded Api V1 Enrichment Chat File Uploaded  Session Id  Post"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment-chat/session/{session_id}/file-data":{"get":{"tags":["enrichment-chat"],"summary":"Get Session File Data","description":"Get file data from a session for enrichment.\n\nThis endpoint retrieves the actual lead data that was uploaded\nso the agent can process it with harvest tools.\n\nArgs:\n    session_id: The session ID\n\nReturns:\n    File data including leads and metadata","operationId":"get_session_file_data_api_v1_enrichment_chat_session__session_id__file_data_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Session File Data Api V1 Enrichment Chat Session  Session Id  File Data Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment-chat/session/{session_id}/status":{"get":{"tags":["enrichment-chat"],"summary":"Get Enrichment Status","description":"Get the current status of enrichment processing.\n\nThis can handle both chat session IDs and processing session IDs.\n\nArgs:\n    session_id: The session ID (chat or processing)\n\nReturns:\n    Status information including processing state and results","operationId":"get_enrichment_status_api_v1_enrichment_chat_session__session_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Enrichment Status Api V1 Enrichment Chat Session  Session Id  Status Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/enrichment/process-file":{"post":{"tags":["enrichment-processing"],"summary":"Process File Enrichment","description":"Process file enrichment request from the agent.\n\nThis endpoint is called by the agent's process_file_enrichment tool\nto trigger background processing of LinkedIn URLs with comprehensive\nvalidation and error handling.\n\nFeatures:\n- Input validation for LinkedIn URLs and session parameters\n- Credit checking and quota verification\n- Optimized Arq job enqueueing with proper resource management\n- Comprehensive error handling and status reporting\n- Job priority and duration estimation\n\nArgs:\n    request: File processing request details with validation\n    current_user: Authenticated user with credit information\n    redis_cache: Redis cache instance for session management\n    supabase_service: Supabase service instance for job tracking\n\nReturns:\n    ProcessFileResponse with comprehensive job details\n\nRaises:\n    HTTPException: For validation errors, insufficient credits, or processing failures","operationId":"process_file_enrichment_api_v1_enrichment_process_file_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessFileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessFileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/enrichment/job/{job_id}/status":{"get":{"tags":["enrichment-processing"],"summary":"Get Enrichment Job Status","description":"Get the comprehensive status of an enrichment job.\n\nProvides detailed information about job progress, timing, resource usage,\nand results. Includes error information for failed jobs and progress\nestimates for running jobs.\n\nArgs:\n    job_id: The job ID to check (must be valid UUID format)\n    current_user: Authenticated user\n    supabase_service: Supabase service instance for job tracking\n\nReturns:\n    EnrichmentJobStatus with comprehensive job information\n\nRaises:\n    HTTPException: If job not found, access denied, or system error","operationId":"get_enrichment_job_status_api_v1_enrichment_job__job_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentJobStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user-extractions/":{"get":{"tags":["user-extractions"],"summary":"List User Extractions","description":"List all available extractions for the authenticated user.\n\nReturns all extractions from the Chrome extension (PitchBook, LinkedIn, etc.).\n\nArgs:\n    current_user: Authenticated user information\n    settings: Application settings\n    limit: Maximum number of extractions to return (default: 50)\n    offset: Number of extractions to skip (default: 0)\n    source: Optional filter by extraction source (e.g., 'PitchBook')\n\nReturns:\n    List of available extractions with metadata","operationId":"list_user_extractions_api_v1_user_extractions__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractionListResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user-extractions/{extraction_id}/info":{"get":{"tags":["user-extractions"],"summary":"Get Extraction Info","description":"Get detailed information about a specific extraction.\n\nArgs:\n    extraction_id: The ID of the extraction to retrieve\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    Detailed extraction information\n\nRaises:\n    HTTPException: If extraction not found or access denied","operationId":"get_extraction_info_api_v1_user_extractions__extraction_id__info_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"extraction_id","in":"path","required":true,"schema":{"type":"string","title":"Extraction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserExtraction"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user-extractions/{extraction_id}/process":{"post":{"tags":["user-extractions"],"summary":"Process Extraction To Session","description":"Process an extraction into a session for lead personalization.\n\nThis endpoint converts the stored extraction data (ZIP) to Excel format\nand processes it through the standard session-based pipeline.\n\nArgs:\n    extraction_id: The ID of the extraction to process\n    request: Processing configuration including session ID\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    Processing status and results\n\nRaises:\n    HTTPException: If extraction not found, access denied, or processing fails","operationId":"process_extraction_to_session_api_v1_user_extractions__extraction_id__process_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"extraction_id","in":"path","required":true,"schema":{"type":"string","title":"Extraction Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessExtractionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProcessExtractionResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user-extractions/{extraction_id}/download":{"get":{"tags":["user-extractions"],"summary":"Download Extraction","description":"Download an extraction in the specified format.\n\nThis endpoint:\n1. Fetches user_extractions record (validates ownership)\n2. Downloads JSON from extraction-files bucket using storage_path\n3. Parses JSON array of lead objects\n4. Filters columnValues.* fields and strips prefix\n5. Converts to requested format (CSV/Excel/JSON)\n6. Returns as streaming response\n\nArgs:\n    extraction_id: The ID of the extraction to download\n    format: Download format (csv, excel, or json)\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    File as a streaming response in the requested format\n\nRaises:\n    HTTPException: If extraction not found or access denied","operationId":"download_extraction_api_v1_user_extractions__extraction_id__download_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"extraction_id","in":"path","required":true,"schema":{"type":"string","title":"Extraction Id"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","pattern":"^(csv|excel|json)$","description":"Download format: csv, excel, or json","default":"excel","title":"Format"},"description":"Download format: csv, excel, or json"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user-extractions/{extraction_id}/rename":{"options":{"tags":["user-extractions"],"summary":"Rename Extraction Options","description":"Handle CORS preflight for rename endpoint.","operationId":"rename_extraction_options_api_v1_user_extractions__extraction_id__rename_options","parameters":[{"name":"extraction_id","in":"path","required":true,"schema":{"type":"string","title":"Extraction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["user-extractions"],"summary":"Rename Extraction","description":"Rename an extraction (update its title in metadata).\n\nArgs:\n    extraction_id: The ID of the extraction to rename\n    rename_request: Request body containing the new title\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    Success response with updated extraction info\n\nRaises:\n    HTTPException: If extraction not found or access denied","operationId":"rename_extraction_api_v1_user_extractions__extraction_id__rename_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"extraction_id","in":"path","required":true,"schema":{"type":"string","title":"Extraction Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RenameRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user-extractions/{extraction_id}":{"delete":{"tags":["user-extractions"],"summary":"Delete Extraction","description":"Delete a single extraction.\n\nArgs:\n    extraction_id: The ID of the extraction to delete\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    Success response with deletion confirmation\n\nRaises:\n    HTTPException: If extraction not found or access denied","operationId":"delete_extraction_api_v1_user_extractions__extraction_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"extraction_id","in":"path","required":true,"schema":{"type":"string","title":"Extraction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user-extractions/{extraction_id}/create-session":{"post":{"tags":["user-extractions"],"summary":"Create Session From Extraction","description":"Create an enrichment session from a saved extraction.\n\nThis endpoint converts an extraction (stored as JSON in Supabase storage)\ninto a new enrichment session with associated dataset and dataset_rows.\n\nFlow:\n1. Fetch user_extractions record (validate ownership)\n2. Download JSON from extraction-files bucket using storage_path\n3. Parse JSON array of lead objects\n4. Create processing_sessions record (pipeline_type=\"enrichment\")\n5. Create datasets record (source_type=\"extraction\")\n6. Create dataset_rows records (one per lead)\n7. Update user_extractions.session_id to link them\n8. Return session details\n\nArgs:\n    extraction_id: The ID of the extraction to convert\n    current_user: Authenticated user information\n    cache: Redis cache instance\n    settings: Application settings\n\nReturns:\n    CreateSessionResponse with session_id and metadata\n\nRaises:\n    HTTPException: If extraction not found, access denied, or processing fails","operationId":"create_session_from_extraction_api_v1_user_extractions__extraction_id__create_session_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"extraction_id","in":"path","required":true,"schema":{"type":"string","title":"Extraction Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__routers__user_extractions__CreateSessionResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/user-extractions/bulk-delete":{"post":{"tags":["user-extractions"],"summary":"Bulk Delete Extractions","description":"Delete multiple extractions in bulk.\n\nArgs:\n    request: Request containing list of extraction IDs to delete\n    current_user: Authenticated user information\n    settings: Application settings\n\nReturns:\n    BulkDeleteResponse with deletion results\n\nRaises:\n    HTTPException: If authentication fails","operationId":"bulk_delete_extractions_api_v1_user_extractions_bulk_delete_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeleteRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeleteResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Not Found - Extraction not found"},"429":{"description":"Too Many Requests - Rate limit exceeded"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sessions/{session_id}/upload/csv":{"post":{"tags":["File Upload (CSV/Excel)"],"summary":"Upload CSV with sender profile support","description":"Upload CSV file with option to use saved sender profiles or create new ones","operationId":"upload_csv_with_profiles_api_v1_sessions__session_id__upload_csv_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_csv_with_profiles_api_v1_sessions__session_id__upload_csv_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/upload/excel/preview":{"post":{"tags":["File Upload (CSV/Excel)"],"summary":"Preview Excel file sheets","description":"Upload an Excel file to preview all sheets with metadata and sample data","operationId":"preview_excel_sheets_api_v1_upload_excel_preview_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_preview_excel_sheets_api_v1_upload_excel_preview_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExcelPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/upload/preview":{"post":{"tags":["File Upload (CSV/Excel)"],"summary":"Preview CSV or Excel file before upload","description":"Upload a CSV or Excel file to preview its structure, columns, and sample data","operationId":"preview_file_api_v1_upload_preview_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_preview_file_api_v1_upload_preview_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnifiedPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sessions/{session_id}/upload/excel":{"post":{"tags":["File Upload (CSV/Excel)"],"summary":"Upload Excel with multi-sheet and sender profile support","description":"Upload Excel file with option to process multiple sheets, use saved sender profiles, or create new ones","operationId":"upload_excel_with_profiles_api_v1_sessions__session_id__upload_excel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_excel_with_profiles_api_v1_sessions__session_id__upload_excel_post"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionUploadResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sheets/verify-access":{"post":{"tags":["Google Sheets OAuth"],"summary":"Verify Sheet Access","description":"Verify user has access to a Google Sheet.\n\nVerifies access via Google API (source of truth for permissions).\n\nReturns:\n    Dictionary with access status and sheet metadata","operationId":"verify_sheet_access_api_v1_sheets_verify_access_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SheetAccessVerifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Verify Sheet Access Api V1 Sheets Verify Access Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sheets/{sheet_id}/info":{"get":{"tags":["Google Sheets OAuth"],"summary":"Get Sheet Info","description":"Get metadata about a Google Sheet.\n\nReturns information about the sheet including available tabs and dimensions.\n\nArgs:\n    sheet_id: Google Sheets ID\n\nReturns:\n    Sheet metadata including tabs and dimensions","operationId":"get_sheet_info_api_v1_sheets__sheet_id__info_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"sheet_id","in":"path","required":true,"schema":{"type":"string","title":"Sheet Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Sheet Info Api V1 Sheets  Sheet Id  Info Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/sheets/grant-access":{"post":{"tags":["Google Sheets OAuth"],"summary":"Grant Sheet Access","description":"Grant and record access to a Google Sheet selected via Google Picker.\n\nThis endpoint is called after a user selects a sheet through the Google Picker.\nReturns success without database recording (permissions verified via Google API).\n\nReturns:\n    Dictionary with success status and sheet details","operationId":"grant_sheet_access_api_v1_sheets_grant_access_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GrantSheetAccessRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Grant Sheet Access Api V1 Sheets Grant Access Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/sheets/import-as-extraction":{"post":{"tags":["Google Sheets OAuth"],"summary":"Import Google Sheets As Extraction","description":"Import Google Sheets data as an extraction for processing.\n\nThis endpoint imports data from a Google Sheet and creates an extraction\nrecord that can be processed through the standard extraction pipeline\n(sheet selection → column mapping → review/process).\n\nReturns:\n    Dictionary with extraction_id and metadata","operationId":"import_google_sheets_as_extraction_api_v1_sheets_import_as_extraction_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleSheetsImportRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Import Google Sheets As Extraction Api V1 Sheets Import As Extraction Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/campaigns/":{"post":{"tags":["campaigns"],"summary":"Create Campaign","description":"Create a new email campaign.\n\nCreates a campaign in DRAFT status. Use the launch endpoint to start\nsending emails.\n\nArgs:\n    request: Campaign creation request with steps configuration\n    current_user: Authenticated user information\n    service: Campaign service instance\n\nReturns:\n    Created campaign response","operationId":"create_campaign_api_v1_campaigns__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["campaigns"],"summary":"List Campaigns","description":"List all campaigns for the authenticated user.\n\nArgs:\n    current_user: Authenticated user information\n    service: Campaign service instance\n    status_filter: Optional status filter\n    search: Optional search term for campaign name\n    page: Page number (1-indexed)\n    page_size: Items per page (max 100)\n\nReturns:\n    Paginated list of campaigns","operationId":"list_campaigns_api_v1_campaigns__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CampaignStatus"},{"type":"null"}],"title":"Status"}},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search by campaign name","title":"Search"},"description":"Search by campaign name"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Page Size"},"description":"Items per page"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignListResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/aggregate-stats":{"get":{"tags":["campaigns"],"summary":"Get Aggregate Stats","description":"Get aggregate stats across all user campaigns.","operationId":"get_aggregate_stats_api_v1_campaigns_aggregate_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AggregateStatsResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/campaigns/{campaign_id}":{"get":{"tags":["campaigns"],"summary":"Get Campaign","description":"Get a specific campaign by ID.\n\nArgs:\n    campaign_id: Campaign ID\n    current_user: Authenticated user information\n    service: Campaign service instance\n\nReturns:\n    Campaign response with total leads count","operationId":"get_campaign_api_v1_campaigns__campaign_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["campaigns"],"summary":"Update Campaign","description":"Update a campaign.\n\nOnly certain fields can be updated, and some fields cannot be changed\nafter the campaign is launched.\n\nArgs:\n    campaign_id: Campaign ID\n    request: Update request\n    current_user: Authenticated user information\n    service: Campaign service instance\n\nReturns:\n    Updated campaign response","operationId":"update_campaign_api_v1_campaigns__campaign_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["campaigns"],"summary":"Delete Campaign","description":"Delete a campaign.\n\nDeletes the campaign and all associated leads and jobs (cascade delete).\n\nArgs:\n    campaign_id: Campaign ID\n    current_user: Authenticated user information\n    service: Campaign service instance","operationId":"delete_campaign_api_v1_campaigns__campaign_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/launch-preflight":{"post":{"tags":["campaigns"],"summary":"Launch Preflight","description":"Check launch readiness without side effects.\n\nReturns warnings and summary so the user can review before confirming launch.","operationId":"launch_preflight_api_v1_campaigns__campaign_id__launch_preflight_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreflightResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/launch":{"post":{"tags":["campaigns"],"summary":"Launch Campaign","description":"Launch a campaign.\n\nReturns campaign data with any warnings and a summary of launch results.","operationId":"launch_campaign_api_v1_campaigns__campaign_id__launch_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LaunchResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/launch-warnings":{"get":{"tags":["campaigns"],"summary":"Get Launch Warnings","description":"Retrieve persisted launch warnings for a campaign.","operationId":"get_launch_warnings_api_v1_campaigns__campaign_id__launch_warnings_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LaunchWarningHistoryResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/pause":{"post":{"tags":["campaigns"],"summary":"Pause Campaign","description":"Pause an active campaign.\n\nPaused campaigns will not send any more emails until resumed.\nThe dispatcher will skip leads from paused campaigns.\n\nArgs:\n    campaign_id: Campaign ID\n    current_user: Authenticated user information\n    service: Campaign service instance\n\nReturns:\n    Updated campaign response","operationId":"pause_campaign_api_v1_campaigns__campaign_id__pause_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/resume":{"post":{"tags":["campaigns"],"summary":"Resume Campaign","description":"Resume a paused campaign.\n\nArgs:\n    campaign_id: Campaign ID\n    current_user: Authenticated user information\n    service: Campaign service instance\n\nReturns:\n    Updated campaign response","operationId":"resume_campaign_api_v1_campaigns__campaign_id__resume_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/click-stats":{"get":{"tags":["campaigns"],"summary":"Get Campaign Click Stats","description":"Get click tracking stats for a campaign.","operationId":"get_campaign_click_stats_api_v1_campaigns__campaign_id__click_stats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignClickStatsResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/stats":{"get":{"tags":["campaigns"],"summary":"Get Campaign Stats","description":"Get comprehensive stats for a single campaign.","operationId":"get_campaign_stats_api_v1_campaigns__campaign_id__stats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignStatsResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/stats/step-performance":{"get":{"tags":["campaigns"],"summary":"Get Step Performance","description":"Get per-step performance breakdown for a campaign.","operationId":"get_step_performance_api_v1_campaigns__campaign_id__stats_step_performance_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StepPerformanceResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/leads/{campaign_lead_id}/events":{"get":{"tags":["campaigns"],"summary":"Get Lead Events","description":"Get email event timeline for a specific campaign lead.","operationId":"get_lead_events_api_v1_campaigns__campaign_id__leads__campaign_lead_id__events_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"campaign_lead_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Lead Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Lead Events Api V1 Campaigns  Campaign Id  Leads  Campaign Lead Id  Events Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/leads":{"get":{"tags":["campaigns"],"summary":"List Campaign Leads","description":"List leads for a campaign with their current status.\n\nIncludes lead data from the dataset for display purposes.\n\nArgs:\n    campaign_id: Campaign ID\n    current_user: Authenticated user information\n    service: Campaign service instance\n    status_filter: Optional status filter\n    page: Page number (1-indexed)\n    page_size: Items per page (max 200)\n\nReturns:\n    Paginated list of campaign leads with lead data","operationId":"list_campaign_leads_api_v1_campaigns__campaign_id__leads_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CampaignLeadStatus"},{"type":"null"}],"title":"Status"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Items per page","default":50,"title":"Page Size"},"description":"Items per page"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignLeadListResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"},"404":{"description":"Campaign not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/leads/{campaign_lead_id}/approve":{"post":{"tags":["playground"],"summary":"Approve Lead Email","description":"Freeze a per-step approved email on this campaign_lead.\n\nWrites into `campaign_leads.metadata.approved_emails[step_index]`. The\nsend-time short-circuit (PR A2) reads this exact blob and skips LangGraph.","operationId":"approve_lead_email_api_v1_campaigns__campaign_id__leads__campaign_lead_id__approve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"campaign_lead_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Lead Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveLeadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveLeadResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Campaign or lead not found"},"409":{"description":"Concurrent edit conflict"},"422":{"description":"Validation failure"}}}},"/api/v1/campaigns/{campaign_id}/leads/{campaign_lead_id}/unapprove":{"post":{"tags":["playground"],"summary":"Unapprove Lead Email","description":"Clear the approved blob for one step on this lead.","operationId":"unapprove_lead_email_api_v1_campaigns__campaign_id__leads__campaign_lead_id__unapprove_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"campaign_lead_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Lead Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnapproveLeadRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveLeadResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Campaign or lead not found"},"409":{"description":"Concurrent edit conflict"},"422":{"description":"Validation failure"}}}},"/api/v1/campaigns/{campaign_id}/leads/{campaign_lead_id}/reset":{"post":{"tags":["playground"],"summary":"Reset Lead Approvals","description":"Reset approvals for this lead. Omitting step_indices clears every step.","operationId":"reset_lead_approvals_api_v1_campaigns__campaign_id__leads__campaign_lead_id__reset_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"campaign_lead_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Lead Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetLeadApprovalsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApproveLeadResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Campaign or lead not found"},"409":{"description":"Concurrent edit conflict"},"422":{"description":"Validation failure"}}}},"/api/v1/campaigns/{campaign_id}/playground/generate":{"post":{"tags":["playground"],"summary":"Playground Generate","description":"Enqueue an ARQ ``playground_generation`` task per target lead.","operationId":"playground_generate_api_v1_campaigns__campaign_id__playground_generate_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaygroundGenerateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaygroundGenerateResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Campaign or lead not found"},"409":{"description":"Concurrent edit conflict"},"422":{"description":"Validation failure"}}}},"/api/v1/campaigns/{campaign_id}/playground/cancel":{"post":{"tags":["playground"],"summary":"Playground Cancel","description":"DB-authoritative cancel — flip generation_job.status to 'cancelled'.","operationId":"playground_cancel_api_v1_campaigns__campaign_id__playground_cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaygroundCancelRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaygroundCancelResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Campaign or lead not found"},"409":{"description":"Concurrent edit conflict"},"422":{"description":"Validation failure"}}}},"/api/v1/campaigns/{campaign_id}/playground/status":{"get":{"tags":["playground"],"summary":"Playground Status","description":"Aggregate generation_job state per lead for the optional batch_id.","operationId":"playground_status_api_v1_campaigns__campaign_id__playground_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"batch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter to a specific batch (optional).","title":"Batch Id"},"description":"Filter to a specific batch (optional)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaygroundBatchStatus"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Campaign or lead not found"},"409":{"description":"Concurrent edit conflict"},"422":{"description":"Validation failure"}}}},"/api/v1/campaigns/{campaign_id}/playground/drafts":{"get":{"tags":["playground"],"summary":"Playground Drafts","description":"Return full draft subject+body for every lead in the batch.\n\nTenant-scope enforced via ``service.get_batch_drafts`` which calls\n``_load_campaign_owned(campaign_id, user_id)`` before any row read.\nA user who passes another user's batch_id gets a 404 because the\n``campaign_id`` is ownership-checked first — the batch filter is only\napplied WITHIN an authorized campaign scope.\n\nIntended usage from the UI: fetched once when the batch reaches\nterminal-all (overall pending+running == 0), and on explicit \"refresh\ndrafts\" actions. NOT called on the 2s poll loop — the status endpoint\nreturns ``has_draft`` + ``subject_preview`` for that surface.","operationId":"playground_drafts_api_v1_campaigns__campaign_id__playground_drafts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"batch_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","description":"Batch ID produced by POST /playground/generate.","title":"Batch Id"},"description":"Batch ID produced by POST /playground/generate."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaygroundDraftsResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"Campaign or lead not found"},"409":{"description":"Concurrent edit conflict"},"422":{"description":"Validation failure"}}}},"/api/v1/capabilities":{"get":{"tags":["capabilities"],"summary":"Get Capabilities","description":"Return current capability flags. Called on frontend boot + SPA refocus.","operationId":"get_capabilities_api_v1_capabilities_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CapabilitiesResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/templates/":{"post":{"tags":["templates"],"summary":"Create Template","description":"Create a new email template.\n\nTemplates can be used across multiple campaigns for sending template-based\nemails. Variables in the template (e.g., {{first_name}}) will be replaced\nwith lead data at send time.\n\nArgs:\n    request: Template creation request with name and content\n    current_user: Authenticated user information\n    service: Campaign service instance\n\nReturns:\n    Created template response","operationId":"create_template_api_v1_templates__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"404":{"description":"Template not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["templates"],"summary":"List Templates","description":"List all templates for the authenticated user.\n\nArgs:\n    current_user: Authenticated user information\n    service: Campaign service instance\n    page: Page number (1-indexed)\n    page_size: Items per page (max 100)\n\nReturns:\n    Paginated list of templates","operationId":"list_templates_api_v1_templates__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Page number","default":1,"title":"Page"},"description":"Page number"},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Items per page","default":20,"title":"Page Size"},"description":"Items per page"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateListResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"404":{"description":"Template not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/templates/{template_id}":{"get":{"tags":["templates"],"summary":"Get Template","description":"Get a specific template by ID.\n\nArgs:\n    template_id: Template ID\n    current_user: Authenticated user information\n    service: Campaign service instance\n\nReturns:\n    Template response","operationId":"get_template_api_v1_templates__template_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"404":{"description":"Template not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["templates"],"summary":"Update Template","description":"Update a template.\n\nArgs:\n    template_id: Template ID\n    request: Update request\n    current_user: Authenticated user information\n    service: Campaign service instance\n\nReturns:\n    Updated template response","operationId":"update_template_api_v1_templates__template_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateUpdateRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"404":{"description":"Template not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["templates"],"summary":"Delete Template","description":"Delete a template.\n\nNote: Deleting a template that is in use by a campaign will set the\ntemplate_id to NULL in the campaign's step configuration.\n\nArgs:\n    template_id: Template ID\n    current_user: Authenticated user information\n    service: Campaign service instance","operationId":"delete_template_api_v1_templates__template_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"404":{"description":"Template not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/bavimail":{"get":{"tags":["webhooks"],"summary":"Health Check","operationId":"health_check_api_v1_webhooks_bavimail_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["webhooks"],"summary":"Webhook Handler","operationId":"webhook_handler_api_v1_webhooks_bavimail_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/bavimail/domains":{"get":{"tags":["bavimail-proxy"],"summary":"List Domains","operationId":"list_domains_api_v1_bavimail_domains_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Response List Domains Api V1 Bavimail Domains Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["bavimail-proxy"],"summary":"Add Domain","operationId":"add_domain_api_v1_bavimail_domains_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddDomainRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Add Domain Api V1 Bavimail Domains Post"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/bavimail/domains/{domain_id}":{"get":{"tags":["bavimail-proxy"],"summary":"Get Domain","operationId":"get_domain_api_v1_bavimail_domains__domain_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Domain Api V1 Bavimail Domains  Domain Id  Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["bavimail-proxy"],"summary":"Update Domain","operationId":"update_domain_api_v1_bavimail_domains__domain_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDomainRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Domain Api V1 Bavimail Domains  Domain Id  Put"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["bavimail-proxy"],"summary":"Delete Domain","operationId":"delete_domain_api_v1_bavimail_domains__domain_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Domain Api V1 Bavimail Domains  Domain Id  Delete"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/domains/{domain_id}/setup":{"get":{"tags":["bavimail-proxy"],"summary":"Get Domain Setup","operationId":"get_domain_setup_api_v1_bavimail_domains__domain_id__setup_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Domain Setup Api V1 Bavimail Domains  Domain Id  Setup Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/domains/{domain_id}/dns-status":{"get":{"tags":["bavimail-proxy"],"summary":"Check Dns Status","operationId":"check_dns_status_api_v1_bavimail_domains__domain_id__dns_status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Check Dns Status Api V1 Bavimail Domains  Domain Id  Dns Status Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/domains/{domain_id}/verify":{"post":{"tags":["bavimail-proxy"],"summary":"Verify Domain","operationId":"verify_domain_api_v1_bavimail_domains__domain_id__verify_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"domain_id","in":"path","required":true,"schema":{"type":"string","title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Verify Domain Api V1 Bavimail Domains  Domain Id  Verify Post"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/aliases":{"get":{"tags":["bavimail-proxy"],"summary":"List Aliases","operationId":"list_aliases_api_v1_bavimail_aliases_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"domain_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Aliases Api V1 Bavimail Aliases Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["bavimail-proxy"],"summary":"Create Alias","operationId":"create_alias_api_v1_bavimail_aliases_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAliasRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Create Alias Api V1 Bavimail Aliases Post"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/aliases/{alias_id}":{"get":{"tags":["bavimail-proxy"],"summary":"Get Alias","operationId":"get_alias_api_v1_bavimail_aliases__alias_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alias_id","in":"path","required":true,"schema":{"type":"string","title":"Alias Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Alias Api V1 Bavimail Aliases  Alias Id  Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["bavimail-proxy"],"summary":"Update Alias","operationId":"update_alias_api_v1_bavimail_aliases__alias_id__put","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alias_id","in":"path","required":true,"schema":{"type":"string","title":"Alias Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAliasRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Update Alias Api V1 Bavimail Aliases  Alias Id  Put"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["bavimail-proxy"],"summary":"Delete Alias","operationId":"delete_alias_api_v1_bavimail_aliases__alias_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alias_id","in":"path","required":true,"schema":{"type":"string","title":"Alias Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Alias Api V1 Bavimail Aliases  Alias Id  Delete"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/emails":{"post":{"tags":["bavimail-proxy"],"summary":"Send Email","operationId":"send_email_api_v1_bavimail_emails_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"X-Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Send Email Api V1 Bavimail Emails Post"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["bavimail-proxy"],"summary":"List Emails","operationId":"list_emails_api_v1_bavimail_emails_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alias_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alias Id"}},{"name":"idempotency_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency Key"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Emails Api V1 Bavimail Emails Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/emails/{email_id}":{"get":{"tags":["bavimail-proxy"],"summary":"Get Email","operationId":"get_email_api_v1_bavimail_emails__email_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Email Api V1 Bavimail Emails  Email Id  Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/emails/{email_id}/cancel":{"post":{"tags":["bavimail-proxy"],"summary":"Cancel Email","operationId":"cancel_email_api_v1_bavimail_emails__email_id__cancel_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Cancel Email Api V1 Bavimail Emails  Email Id  Cancel Post"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/emails/{email_id}/links":{"get":{"tags":["bavimail-proxy"],"summary":"Get Email Links","operationId":"get_email_links_api_v1_bavimail_emails__email_id__links_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Email Links Api V1 Bavimail Emails  Email Id  Links Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/emails/{email_id}/clicks":{"get":{"tags":["bavimail-proxy"],"summary":"Get Email Clicks","operationId":"get_email_clicks_api_v1_bavimail_emails__email_id__clicks_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"link_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Link Id"}},{"name":"include_bots","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Bots"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Get Email Clicks Api V1 Bavimail Emails  Email Id  Clicks Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/inbound-emails":{"get":{"tags":["bavimail-proxy"],"summary":"List Inbound Emails","operationId":"list_inbound_emails_api_v1_bavimail_inbound_emails_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alias_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alias Id"}},{"name":"include_warmup","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Warmup"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Inbound Emails Api V1 Bavimail Inbound Emails Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/inbound-emails/{email_id}":{"get":{"tags":["bavimail-proxy"],"summary":"Get Inbound Email","operationId":"get_inbound_email_api_v1_bavimail_inbound_emails__email_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Inbound Email Api V1 Bavimail Inbound Emails  Email Id  Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["bavimail-proxy"],"summary":"Delete Inbound Email","operationId":"delete_inbound_email_api_v1_bavimail_inbound_emails__email_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Inbound Email Api V1 Bavimail Inbound Emails  Email Id  Delete"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/inbound-emails/{email_id}/raw":{"get":{"tags":["bavimail-proxy"],"summary":"Get Inbound Email Raw","operationId":"get_inbound_email_raw_api_v1_bavimail_inbound_emails__email_id__raw_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/inbound-emails/{email_id}/attachments/{index}":{"get":{"tags":["bavimail-proxy"],"summary":"Download Inbound Attachment","operationId":"download_inbound_attachment_api_v1_bavimail_inbound_emails__email_id__attachments__index__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"email_id","in":"path","required":true,"schema":{"type":"string","title":"Email Id"}},{"name":"index","in":"path","required":true,"schema":{"type":"integer","title":"Index"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/conversations":{"get":{"tags":["bavimail-proxy"],"summary":"List Conversations","operationId":"list_conversations_api_v1_bavimail_conversations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alias_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alias Id"}},{"name":"domain_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Domain Id"}},{"name":"include_warmup","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Warmup"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Conversations Api V1 Bavimail Conversations Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/conversations/{conversation_id}":{"get":{"tags":["bavimail-proxy"],"summary":"Get Conversation","operationId":"get_conversation_api_v1_bavimail_conversations__conversation_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","title":"Conversation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Conversation Api V1 Bavimail Conversations  Conversation Id  Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - No BaviMail API key found"},"502":{"description":"Bad Gateway - BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/bavimail/webhooks/re-register":{"post":{"tags":["bavimail-self-service"],"summary":"Re-register BaviMail webhook for the calling tenant","description":"Force a fresh `ensure_webhook` round-trip for the calling user. Idempotent: if BaviMail already has an active+verified webhook, returns it as `already_active` without recreating. If a previously registered webhook is dead (consecutive_failures>=5, disabled_at set, or is_active=false), it is deleted and recreated. The endpoint is scoped strictly to `current_user.id`; operators with admin support tooling use a separate path. Rate-limited to 10 requests/minute per authenticated user (JWT `sub` claim, with credential/IP fallback for unparsable or unauthenticated callers).","operationId":"re_register_webhook_api_v1_bavimail_webhooks_re_register_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReRegisterResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/campaigns/{campaign_id}/personalize":{"post":{"tags":["campaign-personalization"],"summary":"Personalize Campaign Email","description":"Generate personalized email content for a campaign lead.\n\nThis endpoint is called by the Worker Lambda (via internal API key) or\ndirectly by authenticated users (via JWT).","operationId":"personalize_campaign_email_api_v1_campaigns__campaign_id__personalize_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"X-Internal-Api-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Internal-Api-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"404":{"description":"Campaign or lead not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/campaigns/{campaign_id}/template-preview":{"post":{"tags":["campaign-personalization"],"summary":"Preview Template Substitution","description":"Preview template variable substitution without personalization.\n\nThis endpoint renders a template with actual lead data but WITHOUT\nAI personalization. Useful for previewing what {{variable}} substitutions\nwill look like before launching a campaign.\n\nArgs:\n    campaign_id: Campaign ID\n    step_index: Step index to preview\n    variant_label: Variant label to preview\n    lead_row_index: Row index of lead in dataset to use for preview\n    current_user: Authenticated user\n    campaign_service: Campaign service instance\n\nReturns:\n    Preview of subject and body with variables substituted","operationId":"preview_template_substitution_api_v1_campaigns__campaign_id__template_preview_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"step_index","in":"query","required":true,"schema":{"type":"integer","minimum":0,"description":"Step index to preview","title":"Step Index"},"description":"Step index to preview"},{"name":"variant_label","in":"query","required":true,"schema":{"type":"string","description":"Variant label to preview","title":"Variant Label"},"description":"Variant label to preview"},{"name":"lead_row_index","in":"query","required":true,"schema":{"type":"integer","minimum":0,"description":"Lead row index in dataset","title":"Lead Row Index"},"description":"Lead row index in dataset"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Preview Template Substitution Api V1 Campaigns  Campaign Id  Template Preview Post"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"404":{"description":"Campaign or lead not found"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/suppression/":{"post":{"tags":["suppression"],"summary":"Add Suppression","description":"Add an email to the suppression list.","operationId":"add_suppression_api_v1_suppression__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionEntry"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["suppression"],"summary":"List Suppression","description":"List suppression entries for the current user.","operationId":"list_suppression_api_v1_suppression__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuppressionListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/suppression/{entry_id}":{"delete":{"tags":["suppression"],"summary":"Delete Suppression","description":"Remove an email from the suppression list.","operationId":"delete_suppression_api_v1_suppression__entry_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"entry_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Entry Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email-verification/validate":{"post":{"tags":["email-verification"],"summary":"Validate Email","description":"Validate a single email address and return risk assessment.","operationId":"validate_email_api_v1_email_verification_validate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateEmailRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Validate Email Api V1 Email Verification Validate Post"}}}},"401":{"description":"Unauthorized"},"402":{"description":"Insufficient credits"},"403":{"description":"Forbidden - No BaviMail API key"},"502":{"description":"BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-verification/dataset/{dataset_id}":{"post":{"tags":["email-verification"],"summary":"Verify Dataset Emails","description":"Verify all emails in a dataset and return per-row risk results.","operationId":"verify_dataset_emails_api_v1_email_verification_dataset__dataset_id__post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Verify Dataset Emails Api V1 Email Verification Dataset  Dataset Id  Post"}}}},"401":{"description":"Unauthorized"},"402":{"description":"Insufficient credits"},"403":{"description":"Forbidden - No BaviMail API key"},"502":{"description":"BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email-verification/dataset/{dataset_id}/prune":{"post":{"tags":["email-verification"],"summary":"Prune Dataset By Risk","description":"Delete rows above a risk threshold and re-index remaining rows.","operationId":"prune_dataset_by_risk_api_v1_email_verification_dataset__dataset_id__prune_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PruneRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Prune Dataset By Risk Api V1 Email Verification Dataset  Dataset Id  Prune Post"}}}},"401":{"description":"Unauthorized"},"402":{"description":"Insufficient credits"},"403":{"description":"Forbidden - No BaviMail API key"},"502":{"description":"BaviMail API error"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/preferences":{"get":{"tags":["notifications"],"summary":"Get Preferences","description":"Get notification preferences for the current user.","operationId":"get_preferences_api_v1_notifications_preferences_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["notifications"],"summary":"Update Preferences","description":"Upsert notification preferences for the current user.","operationId":"update_preferences_api_v1_notifications_preferences_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/notifications/test":{"post":{"tags":["notifications"],"summary":"Send Test Notification","description":"Send a test notification to verify delivery.","operationId":"send_test_notification_api_v1_notifications_test_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/notifications/alerts":{"get":{"tags":["notifications"],"summary":"Get Alerts","description":"Get user alerts. Default: unread only.","operationId":"get_alerts_api_v1_notifications_alerts_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"unread","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Unread"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/notifications/alerts/{alert_id}/read":{"patch":{"tags":["notifications"],"summary":"Mark Alert Read","description":"Mark an alert as read.","operationId":"mark_alert_read_api_v1_notifications_alerts__alert_id__read_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","title":"Alert Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/feedback":{"post":{"tags":["feedback"],"summary":"Submit Feedback","description":"Submit user feedback with optional screenshot and attachments.","operationId":"submit_feedback_api_v1_feedback_post","responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connected-accounts/auth-link":{"post":{"tags":["connected-accounts"],"summary":"Create Auth Link","description":"Generate a hosted auth URL to connect a LinkedIn account.","operationId":"create_auth_link_api_v1_connected_accounts_auth_link_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLinkRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthLinkResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connected-accounts/connect":{"post":{"tags":["connected-accounts"],"summary":"Connect Account","description":"Connect a LinkedIn account via username/password.\n\nP0: Password is never logged — only username is referenced in logs.","operationId":"connect_account_api_v1_connected_accounts_connect_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectAccountRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectAccountResult"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connected-accounts/connect-cookie":{"post":{"tags":["connected-accounts"],"summary":"Connect Account Cookie","description":"Connect a LinkedIn account via browser cookie (li_at).\n\nSECURITY: li_at cookie is never logged or stored. It is sent directly\nto Unipile and discarded.","operationId":"connect_account_cookie_api_v1_connected_accounts_connect_cookie_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectCookieRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectAccountResult"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connected-accounts/checkpoint":{"post":{"tags":["connected-accounts"],"summary":"Solve Checkpoint Endpoint","description":"Solve a 2FA/OTP checkpoint to complete account connection.","operationId":"solve_checkpoint_endpoint_api_v1_connected_accounts_checkpoint_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckpointRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckpointResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connected-accounts/claim":{"post":{"tags":["connected-accounts"],"summary":"Claim Connected Account","description":"Free a LinkedIn slug previously connected by another user.\n\nThe frontend calls this after receiving a 409 ``account_owned_by_another_user``\nfrom /connect or /connect-cookie. That earlier 409 carries a signed\n``claim_token`` AND deletes the requesting user's freshly minted\nUnipile account upstream so no orphan accumulates if the user never\nfollows through. Presenting the token here:\n\n1. Verifies HMAC + expiry + requesting-user binding (fail-closed).\n2. Enforces single-use jti via INSERT into ``consumed_claim_tokens``;\n   a replay returns 410 Gone.\n3. Runs the DB function ``claim_connected_account`` which (inside one\n   transaction) disconnects the previous owner's row, pauses their\n   campaigns, and queues a user_alert.\n4. Best-effort: deletes the previous owner's Unipile account upstream.\n\nThe function does NOT INSERT a new row for the requesting user.\nResponse carries ``next_action=\"reconnect\"``; the frontend redirects\nthe user back to /connect (or /connect-cookie) to register their own\nUnipile session, which now succeeds because the slug is no longer\nheld by any connected row.","operationId":"claim_connected_account_api_v1_connected_accounts_claim_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connected-accounts/connect-status/{checkpoint_token}":{"get":{"tags":["connected-accounts"],"summary":"Check Connect Status","description":"Poll whether an IN_APP_VALIDATION account is ready.\n\nUsed by the frontend when the checkpoint type is IN_APP_VALIDATION\n(user approves in the LinkedIn mobile app, no code to enter).","operationId":"check_connect_status_api_v1_connected_accounts_connect_status__checkpoint_token__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"checkpoint_token","in":"path","required":true,"schema":{"type":"string","title":"Checkpoint Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectStatusResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/connected-accounts":{"get":{"tags":["connected-accounts"],"summary":"List Connected Accounts","description":"List all connected accounts for the current user.","operationId":"list_connected_accounts_api_v1_connected_accounts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectedAccountListResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connected-accounts/{account_id}":{"get":{"tags":["connected-accounts"],"summary":"Get Connected Account","description":"Get a single connected account by ID.","operationId":"get_connected_account_api_v1_connected_accounts__account_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectedAccountResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/connected-accounts/{account_id}/health":{"get":{"tags":["connected-accounts"],"summary":"Get Account Health","description":"Get health indicators for a connected LinkedIn account.","operationId":"get_account_health_api_v1_connected_accounts__account_id__health_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountHealthResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/connected-accounts/{account_id}/disable":{"post":{"tags":["connected-accounts"],"summary":"Disable Connected Account","description":"Soft-disable a connected account (sets status to 'disconnected').","operationId":"disable_connected_account_api_v1_connected_accounts__account_id__disable_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/connected-accounts/{account_id}/limits":{"patch":{"tags":["connected-accounts"],"summary":"Update Account Limits","description":"Update daily limits for a connected account.","operationId":"update_account_limits_api_v1_connected_accounts__account_id__limits_patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateLimitsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/connected-accounts/{account_id}/resume":{"post":{"tags":["connected-accounts"],"summary":"Resume Rate Limited Account","description":"Resume a rate-limited LinkedIn account. Reactivates frozen leads.\n\nStep-aware: step 1 leads → active, step 2+ leads → connected.","operationId":"resume_rate_limited_account_api_v1_connected_accounts__account_id__resume_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/search":{"post":{"tags":["linkedin-playground"],"summary":"Search Linkedin","operationId":"search_linkedin_api_v1_linkedin_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInActionResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/linkedin/search/save":{"post":{"tags":["linkedin-playground"],"summary":"Save Search Results","description":"Save LinkedIn search results as a lead dataset.","operationId":"save_search_results_api_v1_linkedin_search_save_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInSearchSaveRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInSearchSaveResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/linkedin/profile":{"post":{"tags":["linkedin-playground"],"summary":"Get Profile","operationId":"get_profile_api_v1_linkedin_profile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInProfileRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInActionResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/linkedin/invite":{"post":{"tags":["linkedin-playground"],"summary":"Send Invite","operationId":"send_invite_api_v1_linkedin_invite_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-idempotency-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInInviteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInActionResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/message":{"post":{"tags":["linkedin-playground"],"summary":"Send Message","operationId":"send_message_api_v1_linkedin_message_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"x-idempotency-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInMessageRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInActionResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/chats":{"get":{"tags":["linkedin-playground"],"summary":"List Chats","operationId":"list_chats_api_v1_linkedin_chats_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"account_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInActionResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/chats/{chat_id}/messages":{"get":{"tags":["linkedin-playground"],"summary":"List Chat Messages","operationId":"list_chat_messages_api_v1_linkedin_chats__chat_id__messages_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","title":"Chat Id"}},{"name":"account_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInActionResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/actions":{"get":{"tags":["linkedin-playground"],"summary":"List Actions","description":"Return persistent action history and today's usage counts.","operationId":"list_actions_api_v1_linkedin_actions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"account_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInActionResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/posts/schedule":{"post":{"tags":["linkedin-content"],"summary":"Schedule Post","operationId":"schedule_post_api_v1_linkedin_posts_schedule_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_schedule_post_api_v1_linkedin_posts_schedule_post"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInPostResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/linkedin/posts/sync":{"post":{"tags":["linkedin-content"],"summary":"Sync Posts","operationId":"sync_posts_api_v1_linkedin_posts_sync_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"connected_account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connected Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Sync Posts Api V1 Linkedin Posts Sync Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/posts/rate-limit":{"get":{"tags":["linkedin-content"],"summary":"Get Rate Limit","operationId":"get_rate_limit_api_v1_linkedin_posts_rate_limit_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"connected_account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connected Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/posts/":{"get":{"tags":["linkedin-content"],"summary":"List Posts","operationId":"list_posts_api_v1_linkedin_posts__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"connected_account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connected Account Id"}},{"name":"after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"After"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInPostListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["linkedin-content"],"summary":"Create Post","operationId":"create_post_api_v1_linkedin_posts__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_create_post_api_v1_linkedin_posts__post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInPostResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/posts/{post_id}":{"delete":{"tags":["linkedin-content"],"summary":"Cancel Post","operationId":"cancel_post_api_v1_linkedin_posts__post_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Cancel Post Api V1 Linkedin Posts  Post Id  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/unipile":{"post":{"tags":["webhooks"],"summary":"Handle Unipile Webhook","description":"Receive and process Unipile webhook events.","operationId":"handle_unipile_webhook_api_v1_webhooks_unipile_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/agent/chat":{"post":{"tags":["agent"],"summary":"Agent Chat","description":"SSE streaming endpoint for the unified Bavi agent.\n\nWrite path:\n1. Write user message to conversation_messages BEFORE streaming\n2. Stream agent response via SSE\n3. Write assistant response to conversation_messages on finish","operationId":"agent_chat_api_v1_agent_chat_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/api__routers__agent_chat__ChatRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/agent/conversations":{"get":{"tags":["agent"],"summary":"List Conversations","description":"List user's non-archived conversations, newest first.","operationId":"list_conversations_api_v1_agent_conversations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["agent"],"summary":"Create Conversation","description":"Create a new conversation.","operationId":"create_conversation_api_v1_agent_conversations_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversationRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/agent/conversations/{thread_id}":{"get":{"tags":["agent"],"summary":"Get Conversation","description":"Get a conversation with its messages.","operationId":"get_conversation_api_v1_agent_conversations__thread_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","title":"Thread Id"}},{"name":"before_cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Before Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["agent"],"summary":"Archive Conversation","description":"Archive (soft-delete) a conversation.","operationId":"archive_conversation_api_v1_agent_conversations__thread_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","title":"Thread Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/conversations/{thread_id}/interrupt":{"get":{"tags":["agent"],"summary":"Get Pending Interrupt","description":"Check if a conversation has a pending interrupt (for browser reopen).","operationId":"get_pending_interrupt_api_v1_agent_conversations__thread_id__interrupt_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"thread_id","in":"path","required":true,"schema":{"type":"string","title":"Thread Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/stripe/create-checkout-session":{"post":{"tags":["stripe"],"summary":"Create Checkout Session","description":"Create a Stripe Checkout session for the requested tier.","operationId":"create_checkout_session_api_v1_stripe_create_checkout_session_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/stripe/create-portal-session":{"post":{"tags":["stripe"],"summary":"Create Portal Session","description":"Create a Stripe Billing Portal session for subscription management.","operationId":"create_portal_session_api_v1_stripe_create_portal_session_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/stripe/subscription-status":{"get":{"tags":["stripe"],"summary":"Get Subscription Status","description":"Return current subscription info for the authenticated user.","operationId":"get_subscription_status_api_v1_stripe_subscription_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/stripe/purchase-credits":{"post":{"tags":["stripe"],"summary":"Purchase Credits","description":"Create a Stripe Checkout session for a one-time credit top-up purchase.","operationId":"purchase_credits_api_v1_stripe_purchase_credits_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreditPurchaseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-finder/health":{"get":{"tags":["email-finder"],"summary":"Health Check","description":"Email finder health check — verifies database connectivity.","operationId":"health_check_api_v1_email_finder_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/email-finder/stats":{"get":{"tags":["email-finder"],"summary":"Get Stats","description":"Get email finder database statistics.","operationId":"get_stats_api_v1_email_finder_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-finder/search":{"post":{"tags":["email-finder"],"summary":"Search Person","description":"Search for a B2B contact by name + company/domain.\n\nReturns a profile from the database if found, or predicted email patterns\nwith confidence scores if not found. Costs 0 credits (monthly lookup limit only).","operationId":"search_person_api_v1_email_finder_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-finder/company/{domain}":{"get":{"tags":["email-finder"],"summary":"Get Company","description":"Get company profile + email patterns by domain.","operationId":"get_company_api_v1_email_finder_company__domain__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"domain","in":"path","required":true,"schema":{"type":"string","title":"Domain"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email-finder/find":{"post":{"tags":["email-finder"],"summary":"Find Email","description":"Find someone's email by trying patterns via sequential SMTP verification.\n\nGenerates 8 email pattern candidates, tries each via SMTP RCPT TO in\nprobability order (stop on first valid), then verifies the winner via BaviMail.\n\nCosts 3 credits. Async — returns job_id for polling.\nFree tier users get 403.","operationId":"find_email_api_v1_email_finder_find_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FindRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-finder/verify":{"post":{"tags":["email-finder"],"summary":"Verify Email","description":"Verify an email address via SMTP + BaviMail.\n\nChecks cache first (free). If not cached, consumes 1 credit and\nenqueues a verification job. Poll /verify/{job_id} for results.\n\nFree tier users get 403 — verification requires a paid plan.","operationId":"verify_email_api_v1_email_finder_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-finder/verify/{job_id}":{"get":{"tags":["email-finder"],"summary":"Get Verification Status","description":"Poll for find or verify job status.","operationId":"get_verification_status_api_v1_email_finder_verify__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/email-finder/bulk":{"post":{"tags":["email-finder"],"summary":"Bulk Search","description":"Bulk find: 3 credits/row, full SMTP+BaviMail verification.\n\nEquivalent to running /find for each row in parallel via ARQ workers. Rows\nmust have `name` and either `domain` or `company`. Company-only rows are\nresolved via _resolve_company_domain before charging; unresolved rows are\nskipped with no charge and reported in `skipped_unresolved`.","operationId":"bulk_search_api_v1_email_finder_bulk_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/email-finder/bulk/{job_id}/status":{"get":{"tags":["email-finder"],"summary":"Get Bulk Status","description":"Aggregated bulk status. `?include_rows=false` returns counts only.","operationId":"get_bulk_status_api_v1_email_finder_bulk__job_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","title":"Job Id"}},{"name":"include_rows","in":"query","required":false,"schema":{"type":"boolean","default":true,"title":"Include Rows"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/lead-finder/batch":{"post":{"tags":["lead-finder"],"summary":"Submit Batch","description":"Submit a batch of names to find LinkedIn URLs.\n\nCreates a processing session + dataset, reserves credits (3 per name),\ndispatches ARQ jobs for each name.","operationId":"submit_batch_api_v1_lead_finder_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BatchLeadFinderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/lead-finder/batch/{session_id}/status":{"get":{"tags":["lead-finder"],"summary":"Get Batch Status","description":"Poll batch lead finder progress. Ownership-guarded (L4).\n\nReads directly from Supabase (not SessionService Redis cache) because\nworker updates counters via direct Supabase writes that don't invalidate cache.","operationId":"get_batch_status_api_v1_lead_finder_batch__session_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/webhooks/stripe":{"post":{"tags":["webhooks","webhooks"],"summary":"Stripe Webhook","description":"Stripe webhook endpoint — signature-verified, idempotent via event dedup.","operationId":"stripe_webhook_api_v1_webhooks_stripe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AccountHealthResponse":{"properties":{"connections_today":{"type":"integer","title":"Connections Today","default":0},"messages_today":{"type":"integer","title":"Messages Today","default":0},"searches_today":{"type":"integer","title":"Searches Today","default":0},"daily_connection_limit":{"type":"integer","title":"Daily Connection Limit","default":25},"daily_message_limit":{"type":"integer","title":"Daily Message Limit","default":100},"daily_search_limit":{"type":"integer","title":"Daily Search Limit","default":50},"warmup_days_remaining":{"type":"integer","title":"Warmup Days Remaining","default":0},"warmup_total":{"type":"integer","title":"Warmup Total","default":14},"last_activity":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Activity"},"warning":{"type":"boolean","title":"Warning","default":false},"acceptance_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Acceptance Rate"},"acceptance_rate_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Acceptance Rate Updated At"},"acceptance_rate_penalty_active":{"type":"boolean","title":"Acceptance Rate Penalty Active","default":false},"effective_daily_limit":{"type":"integer","title":"Effective Daily Limit","default":25}},"type":"object","title":"AccountHealthResponse","description":"Health indicators for a connected LinkedIn account."},"AddDomainRequest":{"properties":{"domain":{"type":"string","title":"Domain"},"provider_key":{"type":"string","title":"Provider Key"}},"type":"object","required":["domain","provider_key"],"title":"AddDomainRequest"},"AddLeadsRequest":{"properties":{"leads":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Leads","description":"List of lead data dictionaries"}},"type":"object","required":["leads"],"title":"AddLeadsRequest","description":"Request model for adding leads to a session."},"AggregateStatsResponse":{"properties":{"active_campaigns":{"type":"integer","title":"Active Campaigns","default":0},"total_campaigns":{"type":"integer","title":"Total Campaigns","default":0},"total_sent":{"type":"integer","title":"Total Sent","default":0},"total_delivered":{"type":"integer","title":"Total Delivered","default":0},"total_opened":{"type":"integer","title":"Total Opened","default":0},"total_replied":{"type":"integer","title":"Total Replied","default":0},"total_bounced":{"type":"integer","title":"Total Bounced","default":0},"avg_open_rate":{"type":"string","title":"Avg Open Rate","default":"0.0"},"avg_reply_rate":{"type":"string","title":"Avg Reply Rate","default":"0.0"}},"type":"object","title":"AggregateStatsResponse","description":"Response model for aggregate stats across all user campaigns."},"ApiKeyCreatedResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","title":"Key","description":"Full API key (shown only once)"},"name":{"type":"string","title":"Name"},"key_prefix":{"type":"string","title":"Key Prefix","description":"First 17 chars for identification"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","key","name","key_prefix","created_at"],"title":"ApiKeyCreatedResponse","description":"Response after creating an API key. Raw key is shown only once."},"ApiKeyListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"key_prefix":{"type":"string","title":"Key Prefix"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"last_used_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Used At"}},"type":"object","required":["id","name","key_prefix","created_at"],"title":"ApiKeyListItem","description":"Single API key in a list response. No raw key, no scopes."},"ApiKeyListResponse":{"properties":{"keys":{"items":{"$ref":"#/components/schemas/ApiKeyListItem"},"type":"array","title":"Keys"},"count":{"type":"integer","title":"Count"},"tier_limit":{"type":"integer","title":"Tier Limit"}},"type":"object","required":["keys","count","tier_limit"],"title":"ApiKeyListResponse","description":"List of API keys for the authenticated user."},"ApplyRequest":{"properties":{"referral_code":{"type":"string","maxLength":20,"minLength":3,"title":"Referral Code"}},"type":"object","required":["referral_code"],"title":"ApplyRequest"},"ApplyResponse":{"properties":{"applied":{"type":"boolean","title":"Applied"}},"type":"object","required":["applied"],"title":"ApplyResponse"},"ApproveLeadRequest":{"properties":{"step_index":{"type":"integer","maximum":32.0,"minimum":1.0,"title":"Step Index","description":"Step number being approved (1-indexed, matches steps_config)."},"variant_label":{"type":"string","maxLength":10,"minLength":1,"title":"Variant Label","description":"Variant label being approved; must match the lead's assigned variant for this step."},"subject":{"type":"string","maxLength":998,"minLength":1,"title":"Subject","description":"Approved subject line (frozen)."},"body":{"type":"string","maxLength":50000,"minLength":1,"title":"Body","description":"Approved body (frozen)."},"custom_prompt":{"anyOf":[{"type":"string","maxLength":32000},{"type":"null"}],"title":"Custom Prompt","description":"If provided, overrides the resolved prompt hierarchy for this approval."},"prompt_snapshot":{"anyOf":[{"type":"string","maxLength":32000},{"type":"null"}],"title":"Prompt Snapshot","description":"Exact prompt text used to generate the draft. If omitted, server resolves it."},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"LLM model identifier used for the draft (e.g., 'gemini-2.0-flash')."},"generation_latency_ms":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Generation Latency Ms","description":"Optional: generation latency for observability."},"research_sources":{"title":"Research Sources","description":"Optional: research-cache source contents used to produce the draft. Hashed into research_cache_fingerprint."},"expected_step_config_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expected Step Config Fingerprint","description":"Optional: fingerprint the client computed at draft time. If it differs from the server-computed fingerprint, approval fails with 422 — the step variant/sender/template was swapped after drafting."}},"type":"object","required":["step_index","variant_label","subject","body"],"title":"ApproveLeadRequest","description":"POST /campaigns/{id}/leads/{lead_id}/approve body."},"ApproveLeadResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"campaign_lead_id":{"type":"string","format":"uuid","title":"Campaign Lead Id"},"step_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Step Index"},"approved_steps":{"items":{"type":"integer"},"type":"array","title":"Approved Steps","description":"All step indices currently approved for this lead after the operation."},"approved_entry":{"anyOf":[{"$ref":"#/components/schemas/ApprovedEmailEntry"},{"type":"null"}]},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["campaign_id","campaign_lead_id","updated_at"],"title":"ApproveLeadResponse","description":"POST approve/unapprove/reset response."},"ApprovedEmailEntry":{"properties":{"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"prompt_snapshot":{"type":"string","title":"Prompt Snapshot"},"prompt_version_hash":{"type":"string","title":"Prompt Version Hash"},"research_cache_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Research Cache Fingerprint"},"lead_identity_fingerprint":{"type":"string","title":"Lead Identity Fingerprint"},"step_index":{"type":"integer","title":"Step Index"},"variant_label":{"type":"string","title":"Variant Label"},"sender_profile_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Profile Id"},"template_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Id"},"step_config_fingerprint":{"type":"string","title":"Step Config Fingerprint"},"approved_at":{"type":"string","format":"date-time","title":"Approved At"},"approved_by":{"type":"string","title":"Approved By"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"generation_latency_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Generation Latency Ms"}},"type":"object","required":["subject","body","prompt_snapshot","prompt_version_hash","lead_identity_fingerprint","step_index","variant_label","step_config_fingerprint","approved_at","approved_by"],"title":"ApprovedEmailEntry","description":"One entry in campaign_leads.metadata.approved_emails."},"AuthLinkRequest":{"properties":{"provider":{"$ref":"#/components/schemas/ConnectedAccountProvider","description":"Provider to connect","default":"linkedin"},"return_path":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Return Path","description":"Relative path to redirect after auth (e.g. '/onboarding?step=connect'). Must start with '/'. If omitted, defaults to '/dashboard/connected-accounts'."}},"type":"object","title":"AuthLinkRequest","description":"Request to generate a hosted auth link for account connection."},"AuthLinkResponse":{"properties":{"url":{"type":"string","title":"Url","description":"Redirect URL for account connection"},"provider":{"type":"string","title":"Provider"}},"type":"object","required":["url","provider"],"title":"AuthLinkResponse","description":"Response containing the hosted auth URL."},"BatchLeadFinderRequest":{"properties":{"names":{"items":{"$ref":"#/components/schemas/LeadFinderName"},"type":"array","maxItems":50,"minItems":1,"title":"Names"},"dataset_name":{"type":"string","maxLength":200,"title":"Dataset Name","default":""}},"type":"object","required":["names"],"title":"BatchLeadFinderRequest"},"BatchPreviewLead":{"properties":{"lead_data":{"additionalProperties":true,"type":"object","title":"Lead Data","description":"Lead fields (company, role, linkedin_url, ...)."},"dataset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dataset Id","description":"Optional dataset id for per-lead research cache."},"row_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Row Index","description":"Row index within dataset; required when dataset_id is set."},"force_refresh_research":{"type":"boolean","title":"Force Refresh Research","description":"Bypass the research cache for this lead.","default":false}},"type":"object","required":["lead_data"],"title":"BatchPreviewLead","description":"One lead within a batch preview request."},"BatchPreviewRequest":{"properties":{"client_run_id":{"type":"string","title":"Client Run Id","description":"Client-generated UUIDv4; backend echoes it as batch_id in every event."},"leads":{"items":{"$ref":"#/components/schemas/BatchPreviewLead"},"type":"array","minItems":1,"title":"Leads"},"sender_profile_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Profile Id","description":"Saved sender profile id; takes precedence over sender_data."},"sender_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Sender Data","description":"Inline sender profile data; ignored if sender_profile_id is set."},"active_prompt_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Prompt Name","description":"Name of a named prompt stored on sender_data.prompts[]. Silent fallback to custom_prompt → default if not found."},"custom_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Prompt","description":"Optional prompt override for this batch run (100-5000 chars)."}},"type":"object","required":["client_run_id","leads"],"title":"BatchPreviewRequest","description":"Batch preview request body. Streams results as SSE."},"BavlioRequest":{"properties":{"lead_data":{"$ref":"#/components/schemas/DynamicLeadData","description":"Lead information with dynamic fields"},"sender_data":{"$ref":"#/components/schemas/DynamicSenderData","description":"Sender information with dynamic fields"}},"type":"object","required":["lead_data","sender_data"],"title":"BavlioRequest","description":"Direct JSON request combining lead and sender data."},"BavlioResponse":{"properties":{"personalised_email":{"type":"string","title":"Personalised Email","description":"The generated personalized email content"},"subject_line":{"type":"string","title":"Subject Line","description":"Suggested email subject line","default":""},"metadata":{"$ref":"#/components/schemas/CommonalityMetadata","description":"Metadata about the commonality discovery and generation process"}},"type":"object","required":["personalised_email","metadata"],"title":"BavlioResponse","description":"Response model for personalization endpoint as specified in PRD."},"Body_create_post_api_v1_linkedin_posts__post":{"properties":{"text":{"type":"string","maxLength":3000,"minLength":1,"title":"Text"},"connected_account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connected Account Id"},"image":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Image"}},"type":"object","required":["text"],"title":"Body_create_post_api_v1_linkedin_posts__post"},"Body_preview_excel_sheets_api_v1_upload_excel_preview_post":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"Excel file to preview"}},"type":"object","required":["file"],"title":"Body_preview_excel_sheets_api_v1_upload_excel_preview_post"},"Body_preview_file_api_v1_upload_preview_post":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"CSV or Excel file to preview"}},"type":"object","required":["file"],"title":"Body_preview_file_api_v1_upload_preview_post"},"Body_schedule_post_api_v1_linkedin_posts_schedule_post":{"properties":{"text":{"type":"string","maxLength":3000,"minLength":1,"title":"Text"},"scheduled_at":{"type":"string","title":"Scheduled At"},"connected_account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connected Account Id"},"image":{"anyOf":[{"type":"string","format":"binary"},{"type":"null"}],"title":"Image"}},"type":"object","required":["text","scheduled_at"],"title":"Body_schedule_post_api_v1_linkedin_posts_schedule_post"},"Body_upload_csv_with_profiles_api_v1_sessions__session_id__upload_csv_post":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"CSV file to upload"},"csv_config":{"type":"string","title":"Csv Config","description":"JSON string with enhanced CSV configuration"},"has_header":{"type":"boolean","title":"Has Header","description":"Whether the CSV has a header row","default":true},"update_sender_data":{"type":"boolean","title":"Update Sender Data","description":"Whether to update session sender data","default":true}},"type":"object","required":["file","csv_config"],"title":"Body_upload_csv_with_profiles_api_v1_sessions__session_id__upload_csv_post"},"Body_upload_excel_with_profiles_api_v1_sessions__session_id__upload_excel_post":{"properties":{"file":{"type":"string","format":"binary","title":"File","description":"Excel file to upload"},"sheet_config":{"type":"string","title":"Sheet Config","description":"JSON string with enhanced sheet configuration"},"has_header":{"type":"boolean","title":"Has Header","description":"Whether the sheets have header rows","default":true},"update_sender_data":{"type":"boolean","title":"Update Sender Data","description":"Whether to update session sender data","default":true}},"type":"object","required":["file","sheet_config"],"title":"Body_upload_excel_with_profiles_api_v1_sessions__session_id__upload_excel_post"},"BulkDeleteRequest":{"properties":{"extraction_ids":{"items":{"type":"string"},"type":"array","minItems":1,"title":"Extraction Ids","description":"List of extraction IDs to delete"}},"type":"object","required":["extraction_ids"],"title":"BulkDeleteRequest","description":"Request model for bulk deleting extractions."},"BulkDeleteResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether the operation was successful"},"deleted_count":{"type":"integer","title":"Deleted Count","description":"Number of extractions successfully deleted"},"failed_ids":{"items":{"type":"string"},"type":"array","title":"Failed Ids","description":"IDs that failed to delete"},"message":{"type":"string","title":"Message","description":"Summary message"}},"type":"object","required":["success","deleted_count","message"],"title":"BulkDeleteResponse","description":"Response model for bulk delete operation."},"BulkPersonalizationRequest":{"properties":{"requests":{"items":{"$ref":"#/components/schemas/BavlioRequest"},"type":"array","maxItems":100,"minItems":1,"title":"Requests","description":"List of personalization requests"}},"type":"object","required":["requests"],"title":"BulkPersonalizationRequest","description":"Request model for bulk personalization with validation."},"BulkSearchRequest":{"properties":{"rows":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Rows","description":"List of {name, company, domain} dicts"}},"type":"object","required":["rows"],"title":"BulkSearchRequest"},"CSVInfo":{"properties":{"row_count":{"type":"integer","title":"Row Count","description":"Total number of rows in the CSV file"},"column_count":{"type":"integer","title":"Column Count","description":"Number of columns in the CSV file"},"columns":{"items":{"type":"string"},"type":"array","title":"Columns","description":"List of column names/headers"},"sample_data":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sample Data","description":"First 5 rows of data for preview"}},"type":"object","required":["row_count","column_count","columns","sample_data"],"title":"CSVInfo","description":"CSV file preview information."},"CampaignChannel":{"type":"string","enum":["email","linkedin"],"title":"CampaignChannel","description":"Per-step channel selector (for mixed campaigns)."},"CampaignClickStatsResponse":{"properties":{"total_clicks":{"type":"integer","title":"Total Clicks","default":0},"clicked_count":{"type":"integer","title":"Clicked Count","default":0},"total_opens":{"type":"integer","title":"Total Opens","default":0},"opened_count":{"type":"integer","title":"Opened Count","default":0},"total_sent":{"type":"integer","title":"Total Sent","default":0},"click_rate":{"type":"number","title":"Click Rate","default":0.0},"open_rate":{"type":"number","title":"Open Rate","default":0.0}},"type":"object","title":"CampaignClickStatsResponse","description":"Response model for campaign click tracking stats."},"CampaignCreateRequest":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"Campaign name"},"description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Description","description":"Campaign description"},"type":{"$ref":"#/components/schemas/CampaignType","description":"Campaign type (email, linkedin, or mixed)","default":"email"},"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id","description":"Dataset containing leads"},"alias_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Alias Ids","description":"Bavimail alias IDs for sending (required for email campaigns)"},"connected_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connected Account Id","description":"Connected account ID (required for linkedin campaigns)"},"steps":{"items":{"$ref":"#/components/schemas/CampaignStepConfig-Input"},"type":"array","maxItems":10,"minItems":1,"title":"Steps","description":"Campaign steps configuration"},"launch_type":{"$ref":"#/components/schemas/CampaignLaunchType","description":"Launch type (immediate or scheduled)","default":"immediate"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date","description":"Scheduled start date (required if launch_type=scheduled)"},"daily_limit":{"type":"integer","maximum":10000.0,"minimum":1.0,"title":"Daily Limit","description":"Max actions per day","default":500},"sending_window_start":{"type":"string","format":"time","title":"Sending Window Start","description":"Daily sending window start (UTC)","default":"09:00:00"},"sending_window_end":{"type":"string","format":"time","title":"Sending Window End","description":"Daily sending window end (UTC)","default":"17:00:00"},"min_interval_seconds":{"type":"integer","maximum":3600.0,"minimum":60.0,"title":"Min Interval Seconds","description":"Minimum seconds between actions","default":300},"timezone":{"type":"string","title":"Timezone","description":"Timezone for sending window interpretation","default":"UTC"},"send_days":{"items":{"type":"string"},"type":"array","title":"Send Days","description":"Days of week to send (3-letter lowercase abbreviations)"},"system_prompt":{"anyOf":[{"type":"string","maxLength":5000,"minLength":100},{"type":"null"}],"title":"System Prompt","description":"Campaign-level personalization prompt override. When set, the email pipeline resolver uses this in preference to sender_data.custom_prompt. NULL = fall through to sender-level custom_prompt or DEFAULT."},"unreviewed_launch_policy":{"$ref":"#/components/schemas/UnreviewedLaunchPolicy","description":"Policy applied at scheduled launch time when the campaign uses AI personalization and the user never reviewed drafts in the playground. launch_default = regenerate at send; hold = pause + notify; cancel = revert to draft + notify.","default":"launch_default"}},"type":"object","required":["name","dataset_id","steps"],"title":"CampaignCreateRequest","description":"Request model for creating a campaign."},"CampaignLaunchType":{"type":"string","enum":["immediate","scheduled"],"title":"CampaignLaunchType","description":"Campaign launch type values."},"CampaignLeadListResponse":{"properties":{"leads":{"items":{"$ref":"#/components/schemas/CampaignLeadResponse"},"type":"array","title":"Leads","description":"List of leads"},"total":{"type":"integer","title":"Total","description":"Total number of leads"},"page":{"type":"integer","title":"Page","description":"Current page number"},"page_size":{"type":"integer","title":"Page Size","description":"Items per page"}},"type":"object","required":["leads","total","page","page_size"],"title":"CampaignLeadListResponse","description":"Response model for campaign lead list."},"CampaignLeadResponse":{"properties":{"campaign_lead_id":{"type":"string","format":"uuid","title":"Campaign Lead Id","description":"Unique lead identifier"},"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id","description":"Associated campaign ID"},"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id","description":"Source dataset ID"},"row_index":{"type":"integer","title":"Row Index","description":"Row index in dataset"},"status":{"$ref":"#/components/schemas/CampaignLeadStatus","description":"Current lead status"},"current_step":{"type":"integer","title":"Current Step","description":"Current step number"},"next_action_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Action At","description":"Next scheduled action"},"assigned_alias_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assigned Alias Id","description":"Assigned sending alias"},"variant_map":{"additionalProperties":{"type":"string"},"type":"object","title":"Variant Map","description":"Step to variant mapping"},"lead_data":{"additionalProperties":true,"type":"object","title":"Lead Data","description":"Lead data from dataset"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation timestamp"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","description":"Last update timestamp"}},"type":"object","required":["campaign_lead_id","campaign_id","dataset_id","row_index","status","current_step","variant_map","lead_data","created_at","updated_at"],"title":"CampaignLeadResponse","description":"Response model for campaign lead with associated lead data."},"CampaignLeadStatus":{"type":"string","enum":["pending","active","processing","completed","replied","bounced","unsubscribed","failed","paused","invalid","waiting_acceptance","connected","connection_ignored","rate_limited"],"title":"CampaignLeadStatus","description":"Campaign lead status values."},"CampaignListResponse":{"properties":{"campaigns":{"items":{"$ref":"#/components/schemas/CampaignResponse"},"type":"array","title":"Campaigns","description":"List of campaigns"},"total":{"type":"integer","title":"Total","description":"Total number of campaigns"},"page":{"type":"integer","title":"Page","description":"Current page number"},"page_size":{"type":"integer","title":"Page Size","description":"Items per page"}},"type":"object","required":["campaigns","total","page","page_size"],"title":"CampaignListResponse","description":"Response model for campaign list."},"CampaignResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id","description":"Unique campaign identifier"},"user_id":{"type":"string","format":"uuid","title":"User Id","description":"Owner user ID"},"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id","description":"Associated dataset ID"},"name":{"type":"string","title":"Name","description":"Campaign name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Campaign description"},"type":{"type":"string","title":"Type","description":"Campaign type (email, linkedin, mixed)"},"status":{"$ref":"#/components/schemas/CampaignStatus","description":"Current campaign status"},"launch_type":{"$ref":"#/components/schemas/CampaignLaunchType","description":"Launch type"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date","description":"Scheduled start date"},"daily_limit":{"type":"integer","title":"Daily Limit","description":"Max actions per day"},"sending_window_start":{"type":"string","format":"time","title":"Sending Window Start","description":"Daily sending window start"},"sending_window_end":{"type":"string","format":"time","title":"Sending Window End","description":"Daily sending window end"},"min_interval_seconds":{"type":"integer","title":"Min Interval Seconds","description":"Min seconds between actions"},"timezone":{"type":"string","title":"Timezone","description":"Timezone for sending window"},"steps_config":{"items":{"$ref":"#/components/schemas/CampaignStepConfig-Output"},"type":"array","title":"Steps Config","description":"Steps configuration"},"alias_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Alias Ids","description":"Bavimail alias IDs"},"connected_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connected Account Id","description":"Connected account for LinkedIn"},"send_days":{"items":{"type":"string"},"type":"array","title":"Send Days","description":"Days of week to send"},"total_leads":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Leads","description":"Total leads in campaign"},"processed_leads":{"type":"integer","title":"Processed Leads","description":"Leads not in pending/active status","default":0},"launch_job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Launch Job Id","description":"ARQ job ID for background launch"},"launch_requested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Launch Requested At","description":"When launch was requested"},"launch_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Launch Error","description":"Error message if launch failed"},"system_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Prompt","description":"Campaign-level personalization prompt override (migration 108)."},"unreviewed_launch_policy":{"$ref":"#/components/schemas/UnreviewedLaunchPolicy","description":"Policy for scheduled launch without playground review (migration 108).","default":"launch_default"},"paused_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Paused Reason","description":"Reason the campaign is paused, e.g. 'pending_personalization_review' (migration 108)."},"playground_discovery_dismissed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Playground Discovery Dismissed At","description":"When the owner dismissed the playground discovery banner (migration 108)."},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation timestamp"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","description":"Last update timestamp"}},"type":"object","required":["campaign_id","user_id","dataset_id","name","type","status","launch_type","daily_limit","sending_window_start","sending_window_end","min_interval_seconds","timezone","steps_config","send_days","created_at","updated_at"],"title":"CampaignResponse","description":"Response model for campaign."},"CampaignStatsResponse":{"properties":{"total_leads":{"type":"integer","title":"Total Leads","default":0},"total_steps":{"type":"integer","title":"Total Steps","default":0},"campaign_status":{"type":"string","title":"Campaign Status","default":""},"replied":{"type":"integer","title":"Replied","default":0},"bounced":{"type":"integer","title":"Bounced","default":0},"unsubscribed":{"type":"integer","title":"Unsubscribed","default":0},"emails_sent":{"type":"integer","title":"Emails Sent","default":0},"deduped_emails_sent":{"type":"integer","title":"Deduped Emails Sent","default":0},"emails_delivered":{"type":"integer","title":"Emails Delivered","default":0},"emails_bounced":{"type":"integer","title":"Emails Bounced","default":0},"emails_complained":{"type":"integer","title":"Emails Complained","default":0},"total_clicks":{"type":"integer","title":"Total Clicks","default":0},"clicked_count":{"type":"integer","title":"Clicked Count","default":0},"total_opens":{"type":"integer","title":"Total Opens","default":0},"opened_count":{"type":"integer","title":"Opened Count","default":0},"open_rate":{"type":"string","title":"Open Rate","default":"0.0"},"click_rate":{"type":"string","title":"Click Rate","default":"0.0"},"reply_rate":{"type":"string","title":"Reply Rate","default":"0.0"},"bounce_rate":{"type":"string","title":"Bounce Rate","default":"0.0"},"delivery_rate":{"type":"string","title":"Delivery Rate","default":"0.0"},"processed_leads":{"type":"integer","title":"Processed Leads","default":0},"progress_percentage":{"type":"integer","title":"Progress Percentage","default":0},"linkedin_requests_sent":{"type":"integer","title":"Linkedin Requests Sent","default":0},"linkedin_accepted":{"type":"integer","title":"Linkedin Accepted","default":0},"linkedin_acceptance_rate":{"type":"string","title":"Linkedin Acceptance Rate","default":"0.0"},"linkedin_replied":{"type":"integer","title":"Linkedin Replied","default":0}},"type":"object","title":"CampaignStatsResponse","description":"Response model for single campaign stats (detail page)."},"CampaignStatus":{"type":"string","enum":["draft","launching","scheduled","active","draining","paused","completed","failed"],"title":"CampaignStatus","description":"Campaign status values."},"CampaignStepConfig-Input":{"properties":{"step":{"type":"integer","minimum":1.0,"title":"Step","description":"Step number (1-indexed)"},"delay_days":{"type":"integer","minimum":0.0,"title":"Delay Days","description":"Days to wait after previous step (0 for immediate)."},"channel":{"$ref":"#/components/schemas/CampaignChannel","description":"Channel for this step","default":"email"},"variants":{"anyOf":[{"items":{"$ref":"#/components/schemas/CampaignStepVariant"},"type":"array","maxItems":4},{"type":"null"}],"title":"Variants","description":"Variants for A/B testing (required for email steps)"},"ai_personalization_enabled":{"type":"boolean","title":"Ai Personalization Enabled","description":"When False, the step is treated as non-personalized by both the Lambda dispatcher (no hold/cancel policy branching) and the playground service (no leads returned for generation). Defaults True for backward compat with legacy campaigns missing this key.","default":true},"track_clicks":{"type":"boolean","title":"Track Clicks","description":"Enable click tracking for this step","default":false},"action_type":{"anyOf":[{"$ref":"#/components/schemas/LinkedInActionType"},{"type":"null"}],"description":"LinkedIn action type (required for linkedin steps)"},"message_template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message Template","description":"LinkedIn message template with {{variable}} placeholders"}},"type":"object","required":["step","delay_days"],"title":"CampaignStepConfig","description":"Configuration for a single step in the campaign sequence.\n\nEach step represents one action (email or LinkedIn) in the sequence."},"CampaignStepConfig-Output":{"properties":{"step":{"type":"integer","minimum":1.0,"title":"Step","description":"Step number (1-indexed)"},"delay_days":{"type":"integer","minimum":0.0,"title":"Delay Days","description":"Days to wait after previous step (0 for immediate)."},"channel":{"$ref":"#/components/schemas/CampaignChannel","description":"Channel for this step","default":"email"},"variants":{"anyOf":[{"items":{"$ref":"#/components/schemas/CampaignStepVariant"},"type":"array","maxItems":4},{"type":"null"}],"title":"Variants","description":"Variants for A/B testing (required for email steps)"},"ai_personalization_enabled":{"type":"boolean","title":"Ai Personalization Enabled","description":"When False, the step is treated as non-personalized by both the Lambda dispatcher (no hold/cancel policy branching) and the playground service (no leads returned for generation). Defaults True for backward compat with legacy campaigns missing this key.","default":true},"track_clicks":{"type":"boolean","title":"Track Clicks","description":"Enable click tracking for this step","default":false},"action_type":{"anyOf":[{"$ref":"#/components/schemas/LinkedInActionType"},{"type":"null"}],"description":"LinkedIn action type (required for linkedin steps)"},"message_template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message Template","description":"LinkedIn message template with {{variable}} placeholders"}},"type":"object","required":["step","delay_days"],"title":"CampaignStepConfig","description":"Configuration for a single step in the campaign sequence.\n\nEach step represents one action (email or LinkedIn) in the sequence."},"CampaignStepVariant":{"properties":{"label":{"type":"string","maxLength":10,"minLength":1,"title":"Label","description":"Variant label (e.g., 'A', 'B')"},"weight":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Weight","description":"Weight for random selection (0-100)"},"type":{"$ref":"#/components/schemas/VariantSourceType","description":"Content source type"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id","description":"Template ID (required if type=TEMPLATE)"},"sender_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Sender Profile Id","description":"Sender profile ID (required if type=PERSONALIZATION)"}},"type":"object","required":["label","weight","type"],"title":"CampaignStepVariant","description":"Configuration for a single variant within a campaign step.\n\nA variant represents one possible path for a lead at this step,\nselected based on weighted randomization during campaign launch."},"CampaignType":{"type":"string","enum":["email","linkedin","mixed"],"title":"CampaignType","description":"Campaign type — determines the execution channel."},"CampaignUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Description"},"step_updates":{"anyOf":[{"items":{"$ref":"#/components/schemas/StepTemplateUpdate"},"type":"array"},{"type":"null"}],"title":"Step Updates"},"daily_limit":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Daily Limit"},"sending_window_start":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Sending Window Start"},"sending_window_end":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Sending Window End"},"min_interval_seconds":{"anyOf":[{"type":"integer","maximum":3600.0,"minimum":60.0},{"type":"null"}],"title":"Min Interval Seconds"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"send_days":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Send Days"},"launch_type":{"anyOf":[{"$ref":"#/components/schemas/CampaignLaunchType"},{"type":"null"}]},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"},"system_prompt":{"anyOf":[{"type":"string","maxLength":5000,"minLength":100},{"type":"null"}],"title":"System Prompt","description":"Campaign-level personalization prompt override. Send explicit `null` to clear the existing value (sets the column to NULL); omit the field entirely to leave it unchanged. Empty string is rejected by the 100-char min-length guard — use `null` to clear."},"unreviewed_launch_policy":{"anyOf":[{"$ref":"#/components/schemas/UnreviewedLaunchPolicy"},{"type":"null"}],"description":"Policy applied when scheduled launch fires without playground review."},"playground_discovery_dismissed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Playground Discovery Dismissed At","description":"ISO timestamp of when the user dismissed the playground discovery banner on the campaign detail page. Send explicit `null` to clear the dismissal (banner re-appears); omit to leave unchanged. Narrow-PATCH surface — AC16 requires that a dismissal write must not clobber system_prompt or unreviewed_launch_policy on the same row, which the `model_fields_set` PATCH semantics enforce."}},"type":"object","title":"CampaignUpdateRequest","description":"Request model for updating a campaign."},"CapabilitiesResponse":{"properties":{"playground_freeze":{"type":"boolean","title":"Playground Freeze"},"unreviewed_launch_policy":{"type":"boolean","title":"Unreviewed Launch Policy"}},"type":"object","required":["playground_freeze","unreviewed_launch_policy"],"title":"CapabilitiesResponse","description":"Runtime capability flags for the frontend."},"ChatMessage":{"properties":{"id":{"type":"string","title":"Id"},"role":{"type":"string","title":"Role","description":"Message sender: 'user' or 'assistant'"},"content":{"type":"string","title":"Content","description":"Message content"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Additional metadata like field name, validation rules"}},"type":"object","required":["role","content"],"title":"ChatMessage","description":"Represents a single message in the chat conversation."},"ChatResponse":{"properties":{"session_id":{"type":"string","title":"Session Id"},"message":{"$ref":"#/components/schemas/ChatMessage"},"is_complete":{"type":"boolean","title":"Is Complete","description":"Whether profile collection is complete","default":false},"collected_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Collected Data","description":"All collected profile data so far"},"next_field":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Field","description":"The field we're expecting next"},"suggestions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Suggestions","description":"Suggested responses or examples"}},"type":"object","required":["session_id","message"],"title":"ChatResponse","description":"Response model for chat interactions."},"CheckoutRequest":{"properties":{"tier":{"type":"string","title":"Tier"},"billing_period":{"type":"string","title":"Billing Period","default":"monthly"},"success_url":{"type":"string","title":"Success Url"},"cancel_url":{"type":"string","title":"Cancel Url"}},"type":"object","required":["tier","success_url","cancel_url"],"title":"CheckoutRequest"},"CheckpointRequest":{"properties":{"checkpoint_token":{"type":"string","title":"Checkpoint Token"},"code":{"type":"string","title":"Code"}},"type":"object","required":["checkpoint_token","code"],"title":"CheckpointRequest","description":"Request to solve a 2FA/OTP checkpoint."},"CheckpointResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"account":{"anyOf":[{"$ref":"#/components/schemas/ConnectedAccountResponse"},{"type":"null"}]}},"type":"object","required":["success"],"title":"CheckpointResponse","description":"Response from solving a checkpoint."},"ClaimRequest":{"properties":{"claim_token":{"type":"string","maxLength":4096,"minLength":10,"title":"Claim Token"}},"type":"object","required":["claim_token"],"title":"ClaimRequest","description":"Request body for ``POST /api/v1/connected-accounts/claim``."},"ClaimResponse":{"properties":{"success":{"type":"boolean","title":"Success","default":true},"previous_owner_user_id":{"type":"string","format":"uuid","title":"Previous Owner User Id","description":"User ID of the previous owner (for client-side audit logging only)."},"linkedin_slug":{"type":"string","title":"Linkedin Slug","description":"The canonical slug that was freed. The frontend uses this to prompt the user to re-run /connect and complete onboarding."},"next_action":{"type":"string","title":"Next Action","description":"Always 'reconnect'. The frontend should redirect the user back to the connect flow so they can register their own Unipile session.","default":"reconnect"}},"type":"object","required":["previous_owner_user_id","linkedin_slug"],"title":"ClaimResponse","description":"Response from a successful ownership transfer.\n\nThe claim flow only DISCONNECTS the previous owner's row to free\nthe canonical slug; the requesting user re-runs ``/connect`` to\nregister their own Unipile session, which then succeeds because\nthe slug is no longer held."},"CodeResponse":{"properties":{"referral_code":{"type":"string","title":"Referral Code"}},"type":"object","required":["referral_code"],"title":"CodeResponse"},"CommonalityMetadata":{"properties":{"commonality_found":{"type":"string","title":"Commonality Found"},"confidence_score":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence Score"},"research_sources":{"items":{"type":"string"},"type":"array","title":"Research Sources"},"generation_time_ms":{"type":"integer","title":"Generation Time Ms"},"model_used":{"type":"string","title":"Model Used"},"prompt_source":{"type":"string","title":"Prompt Source","description":"Which level of the resolver chain produced the system prompt (e.g., 'campaign_system_prompt', 'sender_profile_named', 'default'). Lets Gate 0 / ops confirm the correct prompt won.","default":""}},"type":"object","required":["commonality_found","confidence_score","research_sources","generation_time_ms","model_used"],"title":"CommonalityMetadata","description":"Metadata about the discovered commonality."},"ConnectAccountRequest":{"properties":{"username":{"type":"string","maxLength":256,"minLength":1,"title":"Username"},"password":{"type":"string","maxLength":256,"minLength":1,"title":"Password"},"provider":{"$ref":"#/components/schemas/ConnectedAccountProvider","default":"linkedin"},"country":{"anyOf":[{"type":"string","maxLength":2,"minLength":2,"pattern":"^[A-Z]{2}$"},{"type":"null"}],"title":"Country","description":"ISO 3166-1 alpha-2 country code (e.g. 'US', 'PL'). If omitted, Unipile auto-assigns proxy near user's IP."}},"type":"object","required":["username","password"],"title":"ConnectAccountRequest","description":"Request to connect a LinkedIn account via username/password."},"ConnectAccountResult":{"properties":{"success":{"type":"boolean","title":"Success"},"account":{"anyOf":[{"$ref":"#/components/schemas/ConnectedAccountResponse"},{"type":"null"}]},"checkpoint_required":{"type":"boolean","title":"Checkpoint Required","default":false},"checkpoint_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checkpoint Type"},"checkpoint_token":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checkpoint Token"}},"type":"object","required":["success"],"title":"ConnectAccountResult","description":"Response from the connect flow — either success or checkpoint needed."},"ConnectCookieRequest":{"properties":{"li_at":{"type":"string","maxLength":1024,"minLength":10,"title":"Li At","description":"LinkedIn li_at access token cookie"},"user_agent":{"type":"string","maxLength":1024,"minLength":5,"title":"User Agent","description":"Browser user agent where cookie was obtained"},"provider":{"$ref":"#/components/schemas/ConnectedAccountProvider","default":"linkedin"},"country":{"anyOf":[{"type":"string","maxLength":2,"minLength":2,"pattern":"^[A-Z]{2}$"},{"type":"null"}],"title":"Country","description":"ISO 3166-1 alpha-2 country code (e.g. 'US', 'PL'). If omitted, Unipile auto-assigns proxy near user's IP."}},"type":"object","required":["li_at","user_agent"],"title":"ConnectCookieRequest","description":"Request to connect a LinkedIn account via browser cookie."},"ConnectStatusResponse":{"properties":{"ready":{"type":"boolean","title":"Ready"},"account":{"anyOf":[{"$ref":"#/components/schemas/ConnectedAccountResponse"},{"type":"null"}]}},"type":"object","required":["ready"],"title":"ConnectStatusResponse","description":"Response from polling connect status (for IN_APP_VALIDATION)."},"ConnectedAccountListResponse":{"properties":{"accounts":{"items":{"$ref":"#/components/schemas/ConnectedAccountResponse"},"type":"array","title":"Accounts"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["accounts","total"],"title":"ConnectedAccountListResponse","description":"Response model for listing connected accounts."},"ConnectedAccountOption":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"display_name":{"type":"string","title":"Display Name"}},"type":"object","required":["id","display_name"],"title":"ConnectedAccountOption"},"ConnectedAccountProvider":{"type":"string","enum":["linkedin"],"title":"ConnectedAccountProvider"},"ConnectedAccountResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"provider":{"type":"string","title":"Provider"},"provider_account_id":{"type":"string","title":"Provider Account Id"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"profile_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Profile Url"},"status":{"$ref":"#/components/schemas/ConnectedAccountStatus"},"is_default":{"type":"boolean","title":"Is Default","default":false},"daily_connection_limit":{"type":"integer","title":"Daily Connection Limit","default":25},"daily_message_limit":{"type":"integer","title":"Daily Message Limit","default":100},"warmup_days":{"type":"integer","title":"Warmup Days","default":14},"connection_country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connection Country"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","provider","provider_account_id","status","created_at","updated_at"],"title":"ConnectedAccountResponse","description":"Response model for a connected account."},"ConnectedAccountStatus":{"type":"string","enum":["connected","disconnected","error","reconnecting","rate_limited"],"title":"ConnectedAccountStatus"},"CreateAliasRequest":{"properties":{"domain_id":{"type":"string","title":"Domain Id"},"alias":{"type":"string","title":"Alias"},"signature_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signature Html"}},"type":"object","required":["domain_id","alias"],"title":"CreateAliasRequest"},"CreateApiKeyRequest":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"User-defined label for the key"}},"type":"object","required":["name"],"title":"CreateApiKeyRequest","description":"Request to create a new API key."},"CreateConversationRequest":{"properties":{"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"}},"type":"object","title":"CreateConversationRequest"},"CreateSessionRequest":{"properties":{"session_type":{"type":"string","enum":["enrichment","personalization"],"title":"Session Type","description":"Type of session: enrichment or personalization"},"sender_data":{"additionalProperties":true,"type":"object","title":"Sender Data","description":"Initial sender data for the session"}},"type":"object","required":["session_type"],"title":"CreateSessionRequest","description":"Request model for creating a new processing session."},"CreditBalanceResponse":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id","description":"User ID"},"total_credits":{"type":"integer","minimum":0.0,"title":"Total Credits","description":"Total credits available"},"used_credits":{"type":"integer","minimum":0.0,"title":"Used Credits","description":"Credits used"},"available_credits":{"type":"integer","minimum":0.0,"title":"Available Credits","description":"Credits available for use"},"tier":{"type":"string","title":"Tier","description":"User's current tier","default":"free"}},"type":"object","required":["user_id","total_credits","used_credits","available_credits"],"title":"CreditBalanceResponse","description":"User credit balance response model."},"CreditEstimateRequest":{"properties":{"operation_type":{"type":"string","title":"Operation Type","description":"Type of operation"},"operation_count":{"type":"integer","minimum":1.0,"title":"Operation Count","description":"Number of operations","default":1},"file_size_mb":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"File Size Mb","description":"File size in MB"},"user_tier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Tier","description":"User tier for pricing calculation"}},"type":"object","required":["operation_type"],"title":"CreditEstimateRequest","description":"Credit cost estimation request model."},"CreditEstimateResponse":{"properties":{"credits_required":{"type":"integer","minimum":0.0,"title":"Credits Required","description":"Credits required for operation"},"operation_type":{"type":"string","title":"Operation Type","description":"Type of operation"},"operation_count":{"type":"integer","title":"Operation Count","description":"Number of operations"},"pricing_mode":{"type":"string","title":"Pricing Mode","description":"Current pricing mode"},"unit_cost":{"type":"integer","title":"Unit Cost","description":"Cost per unit"},"tier_discount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Tier Discount","description":"Tier discount applied"},"breakdown":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Breakdown","description":"Cost breakdown by component"}},"type":"object","required":["credits_required","operation_type","operation_count","pricing_mode","unit_cost"],"title":"CreditEstimateResponse","description":"Credit cost estimation response model."},"CreditPurchaseRequest":{"properties":{"pack_id":{"type":"string","title":"Pack Id"},"success_url":{"type":"string","title":"Success Url"},"cancel_url":{"type":"string","title":"Cancel Url"}},"type":"object","required":["pack_id","success_url","cancel_url"],"title":"CreditPurchaseRequest"},"DatasetSummary":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"source_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Type"},"row_count":{"type":"integer","title":"Row Count","default":0},"created_at":{"type":"string","title":"Created At"},"archived_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Archived At"}},"type":"object","required":["dataset_id","created_at"],"title":"DatasetSummary"},"DatasetWithLatestSession":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id","description":"Unique dataset identifier"},"source_type":{"type":"string","title":"Source Type","description":"Source of the dataset (upload, api, linkedin_search, etc)"},"row_count":{"type":"integer","title":"Row Count","description":"Total number of rows in dataset"},"created_at":{"type":"string","title":"Created At","description":"ISO timestamp of dataset creation"},"updated_at":{"type":"string","title":"Updated At","description":"ISO timestamp of last dataset update"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id","description":"Latest session ID"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"Status of latest session"},"pipeline_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pipeline Type","description":"Pipeline type (enrichment/personalization/extraction)"},"leads_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Leads Count","description":"Total leads in session"},"processed_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Processed Count","description":"Number of processed leads"},"failed_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Failed Count","description":"Number of failed leads"},"progress_percentage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Progress Percentage","description":"Processing progress (0-100)"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename","description":"Original filename for display"},"session_created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Created At","description":"When session was created"},"session_updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Updated At","description":"Last session update"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At","description":"When session completed"}},"type":"object","required":["dataset_id","source_type","row_count","created_at","updated_at"],"title":"DatasetWithLatestSession"},"DynamicLeadData":{"properties":{"data":{"additionalProperties":true,"type":"object","title":"Data","description":"Raw lead data with variable columns (up to 40+)"}},"type":"object","required":["data"],"title":"DynamicLeadData","description":"Flexible lead data model for handling variable columns."},"DynamicSenderData":{"properties":{"data":{"additionalProperties":true,"type":"object","title":"Data","description":"Raw sender data with variable columns"}},"type":"object","required":["data"],"title":"DynamicSenderData","description":"Flexible sender data model for handling variable columns."},"EnrichmentChatMessage":{"properties":{"id":{"type":"string","title":"Id"},"role":{"type":"string","title":"Role","description":"Message sender: 'user' or 'assistant'"},"content":{"type":"string","title":"Content","description":"Message content"},"timestamp":{"type":"string","format":"date-time","title":"Timestamp"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Additional metadata like action type, file info, etc."}},"type":"object","required":["role","content"],"title":"EnrichmentChatMessage","description":"Represents a single message in the enrichment chat conversation."},"EnrichmentChatRequest":{"properties":{"session_id":{"type":"string","minLength":1,"title":"Session Id","description":"Unique session identifier"},"message":{"type":"string","maxLength":10000,"minLength":1,"title":"Message","description":"User's message"},"context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Context","description":"Current conversation context including uploaded file info"}},"type":"object","required":["session_id","message"],"title":"EnrichmentChatRequest","description":"Request model for enrichment chat interactions with enhanced validation."},"EnrichmentChatResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session identifier"},"message":{"$ref":"#/components/schemas/EnrichmentChatMessage","description":"Assistant's response message"},"action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action","description":"Action to trigger in frontend (e.g., 'requestUpload', 'startProcessing')"},"suggested_fields":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Suggested Fields","description":"Suggested fields to enrich based on user query"},"processing_status":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Processing Status","description":"Status of ongoing enrichment processing"},"credits_estimated":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Estimated","description":"Estimated credits required for suggested operations"},"rate_limit_remaining":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rate Limit Remaining","description":"Remaining rate limit for user"},"response_time_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Response Time Ms","description":"Response time in milliseconds"}},"type":"object","required":["session_id","message"],"title":"EnrichmentChatResponse","description":"Enhanced response model for enrichment chat interactions."},"EnrichmentJobStatus":{"properties":{"job_id":{"type":"string","title":"Job Id","description":"Job identifier"},"status":{"type":"string","pattern":"^(queued|started|processing|finished|failed|cancelled)$","title":"Status","description":"Current job status"},"progress":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Progress","description":"Progress percentage (0-100)"},"total":{"type":"integer","minimum":0.0,"title":"Total","description":"Total items to process"},"processed":{"type":"integer","minimum":0.0,"title":"Processed","description":"Successfully processed items"},"failed":{"type":"integer","minimum":0.0,"title":"Failed","description":"Failed items"},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Started At","description":"Job start timestamp"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At","description":"Job completion timestamp"},"estimated_remaining_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Remaining Minutes","description":"Estimated time remaining in minutes"},"credits_used":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Used","description":"Credits consumed so far"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result","description":"Job result data if completed"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Error message if failed"}},"type":"object","required":["job_id","status","progress","total","processed","failed"],"title":"EnrichmentJobStatus","description":"Response model for enrichment job status."},"ExcelPreviewResponse":{"properties":{"filename":{"type":"string","title":"Filename","description":"Name of the uploaded Excel file"},"sheets":{"additionalProperties":{"$ref":"#/components/schemas/ExcelSheetInfo"},"type":"object","title":"Sheets","description":"Information about each sheet in the file"},"total_sheets":{"type":"integer","title":"Total Sheets","description":"Total number of sheets in the file"},"message":{"type":"string","title":"Message","description":"Success message"}},"type":"object","required":["filename","sheets","total_sheets","message"],"title":"ExcelPreviewResponse","description":"Response model for Excel sheet preview."},"ExcelSheetInfo":{"properties":{"row_count":{"type":"integer","title":"Row Count","description":"Total number of rows in the sheet"},"column_count":{"type":"integer","title":"Column Count","description":"Number of columns in the sheet"},"columns":{"items":{"type":"string"},"type":"array","title":"Columns","description":"List of column names/headers"},"sample_data":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sample Data","description":"First 5 rows of data for preview"}},"type":"object","required":["row_count","column_count","columns","sample_data"],"title":"ExcelSheetInfo","description":"Information about a single Excel sheet."},"ExtractionListResponse":{"properties":{"extractions":{"items":{"$ref":"#/components/schemas/UserExtraction"},"type":"array","title":"Extractions","description":"List of available extractions"},"total_count":{"type":"integer","title":"Total Count","description":"Total number of extractions for the user"}},"type":"object","required":["extractions","total_count"],"title":"ExtractionListResponse","description":"Response model for listing user extractions."},"FindRequest":{"properties":{"name":{"type":"string","maxLength":200,"minLength":2,"title":"Name","description":"Full name to find email for"},"domain":{"anyOf":[{"type":"string","maxLength":253,"pattern":"^[a-zA-Z0-9]([a-zA-Z0-9\\-]*[a-zA-Z0-9])?(\\.[a-zA-Z0-9]([a-zA-Z0-9\\-]*[a-zA-Z0-9])?)*\\.[a-zA-Z]{2,}$"},{"type":"null"}],"title":"Domain","description":"Company domain"},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company","description":"Company name (used for domain resolution if domain omitted)"}},"type":"object","required":["name"],"title":"FindRequest"},"GenerationRow":{"properties":{"generation_id":{"type":"string","title":"Generation Id"},"lead_index":{"type":"integer","title":"Lead Index"},"lead_snapshot":{"additionalProperties":true,"type":"object","title":"Lead Snapshot"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"status":{"type":"string","enum":["generated","skipped","failed"],"title":"Status"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"generated_at":{"type":"string","title":"Generated At"}},"type":"object","required":["generation_id","lead_index","lead_snapshot","status","generated_at"],"title":"GenerationRow"},"GoogleSheetsImportRequest":{"properties":{"sheet_url":{"type":"string","title":"Sheet Url","description":"Google Sheets URL"},"sheet_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sheet Name","description":"Specific sheet name to import"},"use_oauth":{"type":"boolean","title":"Use Oauth","description":"Use OAuth authentication (default) or service account","default":true}},"type":"object","required":["sheet_url"],"title":"GoogleSheetsImportRequest","description":"Request model for Google Sheets import with OAuth."},"GrantSheetAccessRequest":{"properties":{"sheet_id":{"type":"string","title":"Sheet Id","description":"Google Sheet ID"},"sheet_name":{"type":"string","title":"Sheet Name","description":"Name of the Google Sheet"},"sheet_url":{"type":"string","title":"Sheet Url","description":"Full URL of the Google Sheet"}},"type":"object","required":["sheet_id","sheet_name","sheet_url"],"title":"GrantSheetAccessRequest","description":"Request model for granting access to a Google Sheet."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"JobStatusResponse":{"properties":{"job_id":{"type":"string","title":"Job Id","description":"Job identifier"},"job_type":{"type":"string","title":"Job Type","description":"Type of job"},"status":{"type":"string","title":"Status","description":"Current job status"},"progress":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Progress","description":"Job progress percentage"},"progress_detail":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Progress Detail","description":"Detailed progress info (percentage, processed, failed, total) when available"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result","description":"Job result if completed"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error","description":"Error message if failed"},"created_at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Created At","description":"Job creation timestamp"},"completed_at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Completed At","description":"Job completion timestamp"}},"type":"object","required":["job_id","job_type","status"],"title":"JobStatusResponse","description":"Response model for job status check."},"LaunchResponse":{"properties":{"campaign":{"$ref":"#/components/schemas/CampaignResponse"},"warnings":{"items":{"$ref":"#/components/schemas/LaunchWarning"},"type":"array","title":"Warnings","default":[]},"summary":{"$ref":"#/components/schemas/LaunchSummary"}},"type":"object","required":["campaign","summary"],"title":"LaunchResponse","description":"Response for campaign launch (includes warnings)."},"LaunchSummary":{"properties":{"total_rows":{"type":"integer","title":"Total Rows"},"launchable_rows":{"type":"integer","title":"Launchable Rows"},"warning_count":{"type":"integer","title":"Warning Count"}},"type":"object","required":["total_rows","launchable_rows","warning_count"],"title":"LaunchSummary","description":"Summary counts for a launch or preflight check."},"LaunchWarning":{"properties":{"code":{"$ref":"#/components/schemas/LaunchWarningCode"},"message":{"type":"string","title":"Message"},"row_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Row Index"},"provider_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Id"},"field":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Field"}},"type":"object","required":["code","message"],"title":"LaunchWarning","description":"A single warning generated during campaign launch validation."},"LaunchWarningCode":{"type":"string","enum":["missing_linkedin_url","provider_resolution_failed","duplicate_same_campaign_input","duplicate_active_outreach","connected_account_disconnected","daily_send_limit_exceeded","already_connected","previously_contacted","autumn_quota_exceeded","autumn_preflight_unavailable","autumn_customer_unmapped","autumn_db_unavailable","autumn_auth_failed","autumn_malformed_response","autumn_di_misconfigured"],"title":"LaunchWarningCode","description":"Warning codes returned during campaign launch validation."},"LaunchWarningHistoryResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"warnings":{"items":{"$ref":"#/components/schemas/LaunchWarning"},"type":"array","title":"Warnings","default":[]},"summary":{"anyOf":[{"$ref":"#/components/schemas/LaunchSummary"},{"type":"null"}]},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["campaign_id"],"title":"LaunchWarningHistoryResponse","description":"Response for stored launch warnings."},"LeadFinderName":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"company":{"type":"string","maxLength":200,"title":"Company","default":""},"location":{"type":"string","maxLength":100,"title":"Location","default":""}},"type":"object","required":["name"],"title":"LeadFinderName"},"LinkedInActionResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Data"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["success"],"title":"LinkedInActionResponse"},"LinkedInActionType":{"type":"string","enum":["connection_request","message","follow_up"],"title":"LinkedInActionType","description":"LinkedIn step action types."},"LinkedInInviteRequest":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"provider_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Id"},"identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identifier"},"message":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Message"}},"type":"object","required":["account_id"],"title":"LinkedInInviteRequest"},"LinkedInMessageRequest":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"provider_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Id"},"identifier":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Identifier"},"chat_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chat Id"},"text":{"type":"string","maxLength":8000,"minLength":1,"title":"Text"}},"type":"object","required":["account_id","text"],"title":"LinkedInMessageRequest"},"LinkedInPostListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/LinkedInPostResponse"},"type":"array","title":"Items"},"accounts":{"items":{"$ref":"#/components/schemas/ConnectedAccountOption"},"type":"array","title":"Accounts","default":[]},"next_after":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next After"},"total_count":{"type":"integer","title":"Total Count","default":0}},"type":"object","required":["items"],"title":"LinkedInPostListResponse"},"LinkedInPostResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"connected_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connected Account Id"},"unipile_post_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Unipile Post Id"},"social_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Social Id"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text"},"share_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Share Url"},"attachments":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Attachments","default":[]},"status":{"type":"string","title":"Status"},"is_repost":{"type":"boolean","title":"Is Repost","default":false},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"author_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Id"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"retry_count":{"type":"integer","title":"Retry Count","default":0},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"impressions":{"type":"integer","title":"Impressions","default":0},"reactions":{"type":"integer","title":"Reactions","default":0},"comments":{"type":"integer","title":"Comments","default":0},"reposts":{"type":"integer","title":"Reposts","default":0},"metrics_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Metrics Updated At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","user_id","status","created_at","updated_at"],"title":"LinkedInPostResponse"},"LinkedInProfileRequest":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"identifier":{"type":"string","maxLength":500,"minLength":1,"title":"Identifier"}},"type":"object","required":["account_id","identifier"],"title":"LinkedInProfileRequest"},"LinkedInSearchRequest":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query"},"category":{"type":"string","const":"people","title":"Category","default":"people"}},"type":"object","required":["account_id","query"],"title":"LinkedInSearchRequest"},"LinkedInSearchSaveRequest":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"results":{"items":{"additionalProperties":true,"type":"object"},"type":"array","maxItems":25,"title":"Results"},"dataset_name":{"type":"string","maxLength":200,"minLength":1,"title":"Dataset Name"},"search_query":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Search Query"}},"type":"object","required":["account_id","results","dataset_name"],"title":"LinkedInSearchSaveRequest"},"LinkedInSearchSaveResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"dataset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Dataset Id"},"leads_saved":{"type":"integer","title":"Leads Saved","default":0},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["success"],"title":"LinkedInSearchSaveResponse"},"NamedPromptCreate":{"properties":{"name":{"type":"string","title":"Name","description":"Prompt name (will be canonicalized to lowercase)"},"text":{"type":"string","title":"Text","description":"Prompt body (100-5000 chars)"}},"type":"object","required":["name","text"],"title":"NamedPromptCreate"},"NamedPromptList":{"properties":{"prompts":{"items":{"$ref":"#/components/schemas/NamedPromptOut"},"type":"array","title":"Prompts"},"cap":{"type":"integer","title":"Cap","default":100}},"type":"object","required":["prompts"],"title":"NamedPromptList"},"NamedPromptOut":{"properties":{"name":{"type":"string","title":"Name"},"text":{"type":"string","title":"Text"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["name","text"],"title":"NamedPromptOut"},"NamedPromptUpdate":{"properties":{"new_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"New Name","description":"Rename: new canonical name"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"Update text body"}},"type":"object","title":"NamedPromptUpdate"},"NotificationPreferencesRequest":{"properties":{"email_enabled":{"type":"boolean","title":"Email Enabled","default":true},"personal_email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Personal Email"},"whatsapp_enabled":{"type":"boolean","title":"Whatsapp Enabled","default":false},"whatsapp_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Whatsapp Number"},"notify_on_reply":{"type":"boolean","title":"Notify On Reply","default":true},"notify_on_bounce":{"type":"boolean","title":"Notify On Bounce","default":false},"notify_on_complaint":{"type":"boolean","title":"Notify On Complaint","default":false}},"type":"object","title":"NotificationPreferencesRequest"},"NotificationPreferencesResponse":{"properties":{"email_enabled":{"type":"boolean","title":"Email Enabled"},"personal_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Personal Email"},"whatsapp_enabled":{"type":"boolean","title":"Whatsapp Enabled"},"whatsapp_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Whatsapp Number"},"notify_on_reply":{"type":"boolean","title":"Notify On Reply"},"notify_on_bounce":{"type":"boolean","title":"Notify On Bounce"},"notify_on_complaint":{"type":"boolean","title":"Notify On Complaint"}},"type":"object","required":["email_enabled","whatsapp_enabled","notify_on_reply","notify_on_bounce","notify_on_complaint"],"title":"NotificationPreferencesResponse"},"PersonalizationEffectivePromptResponse":{"properties":{"prompt":{"type":"string","title":"Prompt"},"source":{"type":"string","title":"Source"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","required":["prompt","source"],"title":"PersonalizationEffectivePromptResponse"},"PersonalizationJobResponse":{"properties":{"job_id":{"type":"string","title":"Job Id","description":"Unique job identifier"},"status":{"type":"string","pattern":"^(queued|processing|completed|failed)$","title":"Status","description":"Job status"},"message":{"type":"string","title":"Message","description":"Status message"},"estimated_time_seconds":{"type":"integer","minimum":1.0,"title":"Estimated Time Seconds","description":"Estimated processing time in seconds"},"credits_required":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Required","description":"Credits required for this operation"},"priority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priority","description":"Job priority level","default":"normal"}},"type":"object","required":["job_id","status","message","estimated_time_seconds"],"title":"PersonalizationJobResponse","description":"Enhanced response model for personalization job requests."},"PersonalizationPreviewCommonality":{"properties":{"text":{"type":"string","title":"Text"},"confidence_score":{"type":"number","title":"Confidence Score"},"rarity_score":{"type":"number","title":"Rarity Score"},"relevance_score":{"type":"number","title":"Relevance Score"},"supporting_evidence":{"items":{"type":"string"},"type":"array","title":"Supporting Evidence"}},"type":"object","required":["text","confidence_score","rarity_score","relevance_score","supporting_evidence"],"title":"PersonalizationPreviewCommonality"},"PersonalizationPreviewRequest":{"properties":{"lead_data":{"additionalProperties":true,"type":"object","title":"Lead Data","description":"The lead fields to personalize against (company, role, linkedin_url, etc.)"},"sender_profile_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Profile Id","description":"ID of a saved sender profile. If omitted, sender_data must be provided."},"sender_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Sender Data","description":"Inline sender profile data. Ignored if sender_profile_id is provided."},"custom_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Custom Prompt","description":"Optional prompt override. Must be 100-5000 characters if provided."},"research_context":{"anyOf":[{"type":"string","maxLength":20000},{"type":"null"}],"title":"Research Context","description":"Optional pre-fetched research context (overrides enrichment). Max 20000 chars."},"dataset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dataset Id","description":"Optional dataset id for research cache persistence. Paired with row_index."},"row_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Row Index","description":"Row index within the dataset. Required when dataset_id is set."},"force_refresh_research":{"type":"boolean","title":"Force Refresh Research","description":"Bypass the research cache and fetch fresh (e.g. user hit 'Refresh research').","default":false}},"type":"object","required":["lead_data"],"title":"PersonalizationPreviewRequest","description":"Input for the sync personalization preview."},"PersonalizationPreviewResearchSource":{"properties":{"name":{"type":"string","title":"Name"},"status":{"type":"string","title":"Status"},"summary":{"type":"string","title":"Summary","default":""},"meta":{"additionalProperties":true,"type":"object","title":"Meta"},"from_cache":{"type":"boolean","title":"From Cache","default":false}},"type":"object","required":["name","status"],"title":"PersonalizationPreviewResearchSource"},"PersonalizationPreviewResponse":{"properties":{"subject":{"type":"string","title":"Subject"},"email_body":{"type":"string","title":"Email Body"},"commonality":{"$ref":"#/components/schemas/PersonalizationPreviewCommonality"},"prompt_source":{"type":"string","title":"Prompt Source","description":"Which prompt was used: 'default', 'sender_profile_custom', or 'custom_override'."},"model_used":{"type":"string","title":"Model Used"},"latency_ms":{"type":"integer","title":"Latency Ms"},"research_sources":{"items":{"$ref":"#/components/schemas/PersonalizationPreviewResearchSource"},"type":"array","title":"Research Sources","description":"Which enrichment sources ran and whether they succeeded."},"research_chars":{"type":"integer","title":"Research Chars","default":0},"research_latency_ms":{"type":"integer","title":"Research Latency Ms","default":0},"research_from_cache":{"type":"boolean","title":"Research From Cache","default":false},"research_cached_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Research Cached At"},"research_meta":{"additionalProperties":true,"type":"object","title":"Research Meta","description":"Aggregate research metadata. Currently exposes `zero_research_reason` (one of the ZERO_RESEARCH_REASON_* enum values) when the joined research_chars was below the useful threshold. Used by ops sweep scripts to derive a per-cohort distribution of why some leads return empty research."}},"type":"object","required":["subject","email_body","commonality","prompt_source","model_used","latency_ms"],"title":"PersonalizationPreviewResponse"},"PersonalizationRequest":{"properties":{"campaign_lead_id":{"type":"string","format":"uuid","title":"Campaign Lead Id","description":"The campaign lead ID"},"job_id":{"type":"string","format":"uuid","title":"Job Id","description":"The outbound job ID"},"step_index":{"type":"integer","minimum":0.0,"title":"Step Index","description":"The step index in the campaign"},"variant_label":{"type":"string","title":"Variant Label","description":"The variant label for A/B testing"},"sender_profile_id":{"type":"string","format":"uuid","title":"Sender Profile Id","description":"The sender profile ID to use"}},"type":"object","required":["campaign_lead_id","job_id","step_index","variant_label","sender_profile_id"],"title":"PersonalizationRequest","description":"Request to personalize email content for a campaign lead."},"PersonalizationResponse":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id","description":"The outbound job ID"},"campaign_lead_id":{"type":"string","format":"uuid","title":"Campaign Lead Id","description":"The campaign lead ID"},"personalized_subject":{"type":"string","title":"Personalized Subject","description":"Personalized email subject"},"personalized_body":{"type":"string","title":"Personalized Body","description":"Personalized email body (HTML)"},"sender_email":{"type":"string","title":"Sender Email","description":"Sender email from profile"},"recipient_email":{"type":"string","title":"Recipient Email","description":"Recipient email address"},"credits_consumed":{"type":"integer","title":"Credits Consumed","description":"Credits consumed for personalization"}},"type":"object","required":["job_id","campaign_lead_id","personalized_subject","personalized_body","sender_email","recipient_email","credits_consumed"],"title":"PersonalizationResponse","description":"Response containing personalized email content."},"PersonalizationSavePromptRequest":{"properties":{"sender_profile_id":{"type":"string","title":"Sender Profile Id"},"prompt":{"type":"string","maxLength":5000,"minLength":100,"title":"Prompt"},"save_as_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Save As Name","description":"Named prompt slot to upsert into. Defaults to 'saved' so repeated playground saves update the same slot rather than accumulating entries. Collision with a reserved name returns 422.","default":"saved"}},"type":"object","required":["sender_profile_id","prompt"],"title":"PersonalizationSavePromptRequest"},"PersonalizationStatusResponse":{"properties":{"job_id":{"type":"string","title":"Job Id","description":"Job identifier"},"status":{"type":"string","title":"Status","description":"Current job status"},"progress_percentage":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Progress Percentage","description":"Progress percentage (0-100)"},"processed_leads":{"type":"integer","minimum":0.0,"title":"Processed Leads","description":"Number of processed leads"},"failed_leads":{"type":"integer","minimum":0.0,"title":"Failed Leads","description":"Number of failed leads"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message","description":"Error message if failed"},"started_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Started At","description":"Job start timestamp"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At","description":"Job completion timestamp"},"credits_used":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Used","description":"Credits consumed"}},"type":"object","required":["job_id","status","progress_percentage","processed_leads","failed_leads"],"title":"PersonalizationStatusResponse","description":"Response model for personalization job status."},"PlaygroundBatchStatus":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"batch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Batch Id"},"overall":{"additionalProperties":{"type":"integer"},"type":"object","title":"Overall"},"per_lead":{"items":{"$ref":"#/components/schemas/PlaygroundGenerationJobState"},"type":"array","title":"Per Lead"}},"type":"object","required":["campaign_id","overall"],"title":"PlaygroundBatchStatus","description":"Overall + per-lead batch progress. Returned by GET /playground/status."},"PlaygroundCancelRequest":{"properties":{"batch_id":{"type":"string","format":"uuid","title":"Batch Id","description":"Batch id to cancel; only leads with this batch_id are affected."}},"type":"object","required":["batch_id"],"title":"PlaygroundCancelRequest","description":"POST /campaigns/{id}/playground/cancel body."},"PlaygroundCancelResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"batch_id":{"type":"string","format":"uuid","title":"Batch Id"},"cancelled_count":{"type":"integer","title":"Cancelled Count"}},"type":"object","required":["campaign_id","batch_id","cancelled_count"],"title":"PlaygroundCancelResponse"},"PlaygroundDraft":{"properties":{"campaign_lead_id":{"type":"string","format":"uuid","title":"Campaign Lead Id"},"subject":{"type":"string","maxLength":500,"minLength":1,"title":"Subject"},"body":{"type":"string","maxLength":50000,"minLength":1,"title":"Body"},"generated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Generated At"},"prompt_version_hash":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Version Hash"}},"type":"object","required":["campaign_lead_id","subject","body"],"title":"PlaygroundDraft","description":"Full generated draft body for a single lead. Returned in a list from\n`GET /campaigns/:id/playground/drafts`. Bounds match the A1 approve\nlimits so an approved body fits through the same validators."},"PlaygroundDraftsResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"batch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Batch Id"},"drafts":{"items":{"$ref":"#/components/schemas/PlaygroundDraft"},"type":"array","title":"Drafts"}},"type":"object","required":["campaign_id"],"title":"PlaygroundDraftsResponse","description":"Response model for `GET /campaigns/:id/playground/drafts?batch_id=...`.\n\nOne-shot fetch — frontend calls this when the batch reaches terminal-all\nOR on explicit \"refresh drafts\" user action. Response size can legitimately\nbe large (50 leads × 50KB body = 2.5MB) because it is user-initiated, not\na polling endpoint."},"PlaygroundGenerateRequest":{"properties":{"step_index":{"type":"integer","maximum":32.0,"minimum":1.0,"title":"Step Index","description":"Campaign step to generate drafts for."},"n_leads":{"type":"integer","maximum":200.0,"minimum":1.0,"title":"N Leads","description":"Number of PERSONALIZATION-assigned leads to enqueue.","default":50},"custom_prompt":{"anyOf":[{"type":"string","maxLength":32000},{"type":"null"}],"title":"Custom Prompt","description":"Optional override prompt; else server resolves via campaign.system_prompt -> sender.custom_prompt -> DEFAULT."}},"type":"object","required":["step_index"],"title":"PlaygroundGenerateRequest","description":"POST /campaigns/{id}/playground/generate body.\n\nEnqueues one ARQ task per target lead. Each call creates a fresh\n``batch_id`` server-side — V1 does not coalesce spam-clicks; the client\nshould debounce the button. The canonical idempotency tuple\n``(campaign_id, campaign_lead_id, prompt_version_hash, batch_id)`` keeps\nduplicate workers no-op via the DB-authoritative cancel/batch check."},"PlaygroundGenerateResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"step_index":{"type":"integer","title":"Step Index"},"batch_id":{"type":"string","format":"uuid","title":"Batch Id"},"enqueued_lead_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Enqueued Lead Ids"},"prompt_version_hash":{"type":"string","title":"Prompt Version Hash"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["campaign_id","step_index","batch_id","enqueued_lead_ids","prompt_version_hash","total"],"title":"PlaygroundGenerateResponse","description":"Response from the batch-enqueue endpoint."},"PlaygroundGenerationJobState":{"properties":{"campaign_lead_id":{"type":"string","format":"uuid","title":"Campaign Lead Id"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"batch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Batch Id"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"has_draft":{"type":"boolean","title":"Has Draft","default":false},"subject_preview":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Subject Preview","description":"First 80 chars of the generated subject (server-truncated)."}},"type":"object","required":["campaign_lead_id"],"title":"PlaygroundGenerationJobState","description":"Per-lead generation state snapshot for the polling endpoint.\n\nR2 (RAC-11) adds `has_draft` + `subject_preview` so the polling client\ncan render a per-row \"ready to review\" indicator + a short subject\nteaser without pulling the full body on every poll. Full bodies are\nfetched once from the dedicated `GET /playground/drafts` endpoint.\n\nPolling-payload scale assertion: at 50 leads × any subject_preview\nlength capped at 80 chars, a status response stays under ~200KB even\nwith error strings populated."},"PreflightResponse":{"properties":{"can_launch":{"type":"boolean","title":"Can Launch"},"warnings":{"items":{"$ref":"#/components/schemas/LaunchWarning"},"type":"array","title":"Warnings","default":[]},"summary":{"$ref":"#/components/schemas/LaunchSummary"}},"type":"object","required":["can_launch","summary"],"title":"PreflightResponse","description":"Response for launch preflight check (no side effects)."},"ProcessExtractionRequest":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session ID to process the extraction into"},"sheet_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Sheet Config","description":"Optional configuration for multi-sheet processing"}},"type":"object","required":["session_id"],"title":"ProcessExtractionRequest","description":"Request model for processing an extraction into a session."},"ProcessExtractionResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session ID where data was processed"},"status":{"type":"string","title":"Status","description":"Processing status"},"leads_queued":{"type":"integer","title":"Leads Queued","description":"Number of leads queued for processing"},"file_info":{"additionalProperties":true,"type":"object","title":"File Info","description":"Information about the processed file"},"message":{"type":"string","title":"Message","description":"Success message"}},"type":"object","required":["session_id","status","leads_queued","file_info","message"],"title":"ProcessExtractionResponse","description":"Response model for extraction processing."},"ProcessFileRequest":{"properties":{"session_id":{"type":"string","minLength":1,"title":"Session Id","description":"Processing session ID"},"linkedin_urls":{"items":{"type":"string"},"type":"array","maxItems":1000,"minItems":1,"title":"Linkedin Urls","description":"List of LinkedIn URLs to enrich"},"source_column":{"type":"string","minLength":1,"title":"Source Column","description":"Name of the source column"}},"type":"object","required":["session_id","linkedin_urls","source_column"],"title":"ProcessFileRequest","description":"Request model for file enrichment processing."},"ProcessFileResponse":{"properties":{"job_id":{"type":"string","title":"Job Id","description":"Background job ID"},"session_id":{"type":"string","title":"Session Id","description":"Processing session ID"},"status":{"type":"string","pattern":"^(queued|processing|completed|failed)$","title":"Status","description":"Processing status"},"message":{"type":"string","title":"Message","description":"Status message"},"urls_to_process":{"type":"integer","minimum":0.0,"title":"Urls To Process","description":"Number of URLs to process"},"estimated_duration_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Duration Minutes","description":"Estimated processing duration in minutes"},"credits_required":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits Required","description":"Credits required for this operation"},"priority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priority","description":"Job priority level","default":"normal"}},"type":"object","required":["job_id","session_id","status","message","urls_to_process"],"title":"ProcessFileResponse","description":"Response model for file enrichment processing."},"ProcessingStartResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session identifier"},"status":{"type":"string","title":"Status","description":"Processing status"},"leads_to_process":{"type":"integer","title":"Leads To Process","description":"Number of leads to process"},"message":{"type":"string","title":"Message","description":"Status message"}},"type":"object","required":["session_id","status","leads_to_process","message"],"title":"ProcessingStartResponse","description":"Response model for starting processing."},"PruneRequest":{"properties":{"max_risk_level":{"type":"string","title":"Max Risk Level"}},"type":"object","required":["max_risk_level"],"title":"PruneRequest"},"RateLimitResponse":{"properties":{"daily_limit":{"type":"integer","title":"Daily Limit","default":100},"effective_outreach_limit":{"type":"integer","title":"Effective Outreach Limit","default":25},"outreach_used":{"type":"integer","title":"Outreach Used","default":0},"content_used":{"type":"integer","title":"Content Used","default":0},"remaining":{"type":"integer","title":"Remaining","default":100}},"type":"object","title":"RateLimitResponse"},"ReRegisterResponse":{"properties":{"webhook_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Webhook Id"},"url":{"type":"string","title":"Url"},"status":{"type":"string","title":"Status"}},"type":"object","required":["webhook_id","url","status"],"title":"ReRegisterResponse","description":"Response model for the self-service re-register endpoint."},"ReferralUseSummary":{"properties":{"status":{"type":"string","title":"Status"},"converted_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Converted At"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["status","created_at"],"title":"ReferralUseSummary"},"RenameRequest":{"properties":{"title":{"type":"string","maxLength":200,"minLength":1,"title":"Title","description":"New title for the extraction"}},"type":"object","required":["title"],"title":"RenameRequest","description":"Request model for renaming an extraction."},"ResetLeadApprovalsRequest":{"properties":{"step_indices":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Step Indices","description":"If omitted or empty, all approved steps are cleared."}},"type":"object","title":"ResetLeadApprovalsRequest","description":"POST /campaigns/{id}/leads/{lead_id}/reset body.\n\n`step_indices=None` OR `step_indices=[]` clears every approved step. A\nnon-empty list selectively clears those step indices."},"RunDetail":{"properties":{"run_id":{"type":"string","title":"Run Id"},"prompt_source":{"type":"string","enum":["named","custom_prompt"],"title":"Prompt Source"},"prompt_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Name"},"n_leads":{"type":"integer","title":"N Leads"},"n_completed":{"type":"integer","title":"N Completed"},"n_failed":{"type":"integer","title":"N Failed"},"status":{"type":"string","enum":["in_progress","completed","failed","stale"],"title":"Status"},"started_at":{"type":"string","title":"Started At"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"model_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model Version"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"}},"type":"object","required":["run_id","prompt_source","n_leads","n_completed","n_failed","status","started_at"],"title":"RunDetail"},"RunDetailResponse":{"properties":{"run":{"$ref":"#/components/schemas/RunDetail"},"generations":{"items":{"$ref":"#/components/schemas/GenerationRow"},"type":"array","title":"Generations"},"total_generations":{"type":"integer","title":"Total Generations"},"has_more":{"type":"boolean","title":"Has More"}},"type":"object","required":["run","generations","total_generations","has_more"],"title":"RunDetailResponse"},"RunLeadsResponse":{"properties":{"generations":{"items":{"$ref":"#/components/schemas/GenerationRow"},"type":"array","title":"Generations"},"total_generations":{"type":"integer","title":"Total Generations"},"offset":{"type":"integer","title":"Offset"},"limit":{"type":"integer","title":"Limit"},"has_more":{"type":"boolean","title":"Has More"}},"type":"object","required":["generations","total_generations","offset","limit","has_more"],"title":"RunLeadsResponse"},"RunListResponse":{"properties":{"runs":{"items":{"$ref":"#/components/schemas/RunSummary"},"type":"array","title":"Runs"},"has_more":{"type":"boolean","title":"Has More","default":false}},"type":"object","required":["runs"],"title":"RunListResponse"},"RunSummary":{"properties":{"run_id":{"type":"string","title":"Run Id"},"prompt_source":{"type":"string","enum":["named","custom_prompt"],"title":"Prompt Source"},"prompt_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Name"},"n_leads":{"type":"integer","title":"N Leads"},"n_completed":{"type":"integer","title":"N Completed"},"n_failed":{"type":"integer","title":"N Failed"},"status":{"type":"string","enum":["in_progress","completed","failed","stale"],"title":"Status"},"started_at":{"type":"string","title":"Started At"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["run_id","prompt_source","n_leads","n_completed","n_failed","status","started_at"],"title":"RunSummary"},"SearchRequest":{"properties":{"name":{"type":"string","maxLength":200,"minLength":2,"title":"Name","description":"Full name to search for"},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company","description":"Company name (optional if domain provided)"},"domain":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Domain","description":"Company domain (optional if company provided)"}},"type":"object","required":["name"],"title":"SearchRequest"},"SearchResponse":{"properties":{"found":{"type":"boolean","title":"Found"},"person":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Person"},"prediction":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Prediction"},"verification":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Verification"},"confidence_breakdown":{"additionalProperties":true,"type":"object","title":"Confidence Breakdown","default":{}},"source":{"type":"string","title":"Source","default":"none"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"type":"object","required":["found"],"title":"SearchResponse"},"SendEmailRequest":{"properties":{"alias_id":{"type":"string","title":"Alias Id"},"to_email":{"type":"string","title":"To Email"},"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"track_opens":{"type":"boolean","title":"Track Opens","default":true},"track_clicks":{"type":"boolean","title":"Track Clicks","default":false},"click_tracking_patterns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Click Tracking Patterns"},"send_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Send At"},"send_at_timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Send At Timezone"},"conversation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Conversation Id"},"in_reply_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"In Reply To"},"attachments":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Attachments"}},"type":"object","required":["alias_id","to_email","subject","body"],"title":"SendEmailRequest"},"SenderDataUploadResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session identifier"},"sources_updated":{"type":"integer","title":"Sources Updated","description":"Number of sender data sources updated"},"merge_strategy":{"type":"string","title":"Merge Strategy","description":"Merge strategy used"},"message":{"type":"string","title":"Message","description":"Success message"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id","description":"Background job ID if processing was queued"},"estimated_completion_time":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Estimated Completion Time","description":"Estimated completion timestamp"},"processing_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Processing Status","description":"Status of background processing job"}},"type":"object","required":["session_id","sources_updated","merge_strategy","message"],"title":"SenderDataUploadResponse","description":"Response model for sender data upload."},"SenderProfile":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"Unique profile identifier"},"user_id":{"type":"string","title":"User Id","description":"User ID who owns this profile"},"profile_name":{"type":"string","maxLength":100,"minLength":1,"title":"Profile Name","description":"User-friendly name for this profile (e.g., 'Sales Team Profile', 'Personal Brand')"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description","description":"Optional description of when/how to use this profile"},"sender_data":{"$ref":"#/components/schemas/DynamicSenderData","description":"The actual sender data with arbitrary fields"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At","description":"Profile creation timestamp"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At","description":"Last update timestamp"},"usage_count":{"type":"integer","title":"Usage Count","description":"Number of times this profile has been used","default":0},"is_default":{"type":"boolean","title":"Is Default","description":"Whether this is the default profile","default":false}},"type":"object","required":["user_id","profile_name","sender_data"],"title":"SenderProfile","description":"Sender profile model for storing reusable sender configurations.\n\nThis model stores a named profile containing DynamicSenderData, which can\nhave ANY arbitrary fields. There is no predefined schema for the sender data.\n\nExamples of valid sender data:\n- {\"full_name\": \"John\", \"company\": \"TechCorp\", \"role\": \"Sales\"}\n- {\"sender_name\": \"Jane\", \"brand\": \"AI Solutions\", \"linkedin\": \"jane-doe\"}\n- {\"name\": \"Bob\", \"agency\": \"Marketing Pro\", \"phone\": \"+1234\", \"timezone\": \"EST\"}\n- Any other combination of fields the user needs"},"SenderProfileCreate":{"properties":{"profile_name":{"type":"string","maxLength":100,"minLength":1,"title":"Profile Name","description":"User-friendly name for this profile"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description","description":"Optional description of when/how to use this profile"},"sender_data":{"additionalProperties":true,"type":"object","title":"Sender Data","description":"The sender data as a dictionary with any fields"},"is_default":{"type":"boolean","title":"Is Default","description":"Whether this should be the default profile","default":false}},"type":"object","required":["profile_name","sender_data"],"title":"SenderProfileCreate","description":"Request model for creating a sender profile."},"SenderProfileUpdate":{"properties":{"profile_name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Profile Name","description":"New name for the profile"},"description":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Description","description":"New description"},"sender_data":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Sender Data","description":"New sender data (replaces existing data completely)"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default","description":"Whether this should be the default profile"}},"type":"object","title":"SenderProfileUpdate","description":"Request model for updating a sender profile."},"SessionResultsResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session identifier"},"total_results":{"type":"integer","title":"Total Results","description":"Total number of results"},"results":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Results","description":"Processing results"},"columns":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Columns","description":"Column order from dataset schema (for display ordering)"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Dataset metadata for display (name, label, source)"}},"type":"object","required":["session_id","total_results","results"],"title":"SessionResultsResponse","description":"Response model for session results."},"SessionStatusResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session identifier"},"status":{"type":"string","title":"Status","description":"Current status"},"created_at":{"type":"number","title":"Created At","description":"Creation timestamp"},"leads_count":{"type":"integer","title":"Leads Count","description":"Total leads in session"},"processed_count":{"type":"integer","title":"Processed Count","description":"Number of processed leads"},"failed_count":{"type":"integer","title":"Failed Count","description":"Number of failed leads"},"progress_percentage":{"type":"number","title":"Progress Percentage","description":"Processing progress as percentage"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata","description":"Session metadata"},"active_jobs":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Active Jobs","description":"Active background jobs"},"job_history":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Job History","description":"Recent job history"}},"type":"object","required":["session_id","status","created_at","leads_count","processed_count","failed_count","progress_percentage","metadata"],"title":"SessionStatusResponse","description":"Response model for session status."},"SessionUploadResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session identifier for the upload"},"dataset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dataset Id","description":"Created dataset ID"},"status":{"type":"string","title":"Status","description":"Upload status"},"leads_queued":{"type":"integer","title":"Leads Queued","description":"Number of leads queued for processing"},"sender_data_sources":{"type":"integer","title":"Sender Data Sources","description":"Number of sender data sources identified"},"file_info":{"additionalProperties":true,"type":"object","title":"File Info","description":"Information about the uploaded file"},"quota_info":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Quota Info","description":"Quota status information"},"message":{"type":"string","title":"Message","description":"Success message"},"job_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Job Id","description":"Background job ID if processing was queued"},"estimated_completion_time":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Estimated Completion Time","description":"Estimated completion timestamp"},"processing_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Processing Status","description":"Status of background processing job"}},"type":"object","required":["session_id","status","leads_queued","sender_data_sources","file_info","message"],"title":"SessionUploadResponse","description":"Enhanced response model for session-based upload with quota information."},"SheetAccessVerifyRequest":{"properties":{"sheet_url":{"type":"string","title":"Sheet Url","description":"Google Sheets URL to verify"}},"type":"object","required":["sheet_url"],"title":"SheetAccessVerifyRequest","description":"Request model for verifying Google Sheets access."},"StatsResponse":{"properties":{"total_earned":{"type":"number","title":"Total Earned"},"active_referrals":{"type":"integer","title":"Active Referrals"},"referral_uses":{"items":{"$ref":"#/components/schemas/ReferralUseSummary"},"type":"array","title":"Referral Uses"}},"type":"object","required":["total_earned","active_referrals","referral_uses"],"title":"StatsResponse"},"StepPerformanceDataPoint":{"properties":{"step":{"type":"integer","title":"Step"},"sent":{"type":"integer","title":"Sent","default":0},"opened":{"type":"integer","title":"Opened","default":0},"clicked":{"type":"integer","title":"Clicked","default":0},"replied":{"type":"integer","title":"Replied","default":0},"open_rate":{"type":"number","title":"Open Rate","default":0.0},"click_rate":{"type":"number","title":"Click Rate","default":0.0},"reply_rate":{"type":"number","title":"Reply Rate","default":0.0}},"type":"object","required":["step"],"title":"StepPerformanceDataPoint","description":"Performance metrics for a single campaign step."},"StepPerformanceResponse":{"properties":{"steps":{"items":{"$ref":"#/components/schemas/StepPerformanceDataPoint"},"type":"array","title":"Steps","default":[]}},"type":"object","title":"StepPerformanceResponse","description":"Response model for step performance stats."},"StepTemplateUpdate":{"properties":{"step":{"type":"integer","minimum":1.0,"title":"Step"},"message_template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message Template"}},"type":"object","required":["step"],"title":"StepTemplateUpdate","description":"Update a single step's message template."},"SuppressionCreateRequest":{"properties":{"email":{"type":"string","title":"Email"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["email"],"title":"SuppressionCreateRequest"},"SuppressionEntry":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["id","email","created_at"],"title":"SuppressionEntry"},"SuppressionListResponse":{"properties":{"entries":{"items":{"$ref":"#/components/schemas/SuppressionEntry"},"type":"array","title":"Entries"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["entries","total"],"title":"SuppressionListResponse"},"TemplateContent":{"properties":{"subject":{"type":"string","maxLength":500,"minLength":1,"title":"Subject","description":"Email subject line"},"body":{"type":"string","minLength":1,"title":"Body","description":"Email body (HTML supported)"}},"type":"object","required":["subject","body"],"title":"TemplateContent","description":"Template email content structure."},"TemplateCreateRequest":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name","description":"Template name for identification"},"content":{"$ref":"#/components/schemas/TemplateContent","description":"Email content with subject and body"}},"type":"object","required":["name","content"],"title":"TemplateCreateRequest","description":"Request model for creating an email template."},"TemplateListResponse":{"properties":{"templates":{"items":{"$ref":"#/components/schemas/TemplateResponse"},"type":"array","title":"Templates","description":"List of templates"},"total":{"type":"integer","title":"Total","description":"Total number of templates"}},"type":"object","required":["templates","total"],"title":"TemplateListResponse","description":"Response model for template list."},"TemplateResponse":{"properties":{"template_id":{"type":"string","format":"uuid","title":"Template Id","description":"Unique template identifier"},"user_id":{"type":"string","format":"uuid","title":"User Id","description":"Owner user ID"},"name":{"type":"string","title":"Name","description":"Template name"},"content":{"$ref":"#/components/schemas/TemplateContent","description":"Email content"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Creation timestamp"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","description":"Last update timestamp"}},"type":"object","required":["template_id","user_id","name","content","created_at","updated_at"],"title":"TemplateResponse","description":"Response model for email template."},"TemplateUpdateRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name","description":"Template name"},"content":{"anyOf":[{"$ref":"#/components/schemas/TemplateContent"},{"type":"null"}],"description":"Email content"}},"type":"object","title":"TemplateUpdateRequest","description":"Request model for updating an email template."},"UnapproveLeadRequest":{"properties":{"step_index":{"type":"integer","maximum":32.0,"minimum":1.0,"title":"Step Index","description":"Step number to un-approve."}},"type":"object","required":["step_index"],"title":"UnapproveLeadRequest","description":"POST /campaigns/{id}/leads/{lead_id}/unapprove body."},"UnifiedPreviewResponse":{"properties":{"filename":{"type":"string","title":"Filename","description":"Name of the uploaded file"},"file_type":{"type":"string","enum":["csv","excel"],"title":"File Type","description":"Type of file uploaded"},"csv_info":{"anyOf":[{"$ref":"#/components/schemas/CSVInfo"},{"type":"null"}],"description":"CSV file information (only populated for CSV files)"},"sheets":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Sheets","description":"Information about each sheet in the Excel file (only populated for Excel files)"},"total_sheets":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Sheets","description":"Total number of sheets in the Excel file (only populated for Excel files)"},"message":{"type":"string","title":"Message","description":"Success or informational message"}},"type":"object","required":["filename","file_type","message"],"title":"UnifiedPreviewResponse","description":"Unified preview response for CSV and Excel files.\n\nThis model supports both CSV and Excel file previews through a single endpoint.\nThe file_type field determines which optional fields are populated."},"UnreviewedLaunchPolicy":{"type":"string","enum":["launch_default","hold","cancel"],"title":"UnreviewedLaunchPolicy","description":"Policy applied when a scheduled AI-personalized campaign fires without review.\n\nMirrors the CHECK constraint on `campaigns.unreviewed_launch_policy` from\nmigration 108. If you add a value here, update the migration too."},"UpdateAliasRequest":{"properties":{"alias":{"type":"string","title":"Alias"},"signature_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signature Html"}},"type":"object","required":["alias"],"title":"UpdateAliasRequest"},"UpdateDatasetRequest":{"properties":{"dataset_name":{"type":"string","maxLength":255,"minLength":1,"title":"Dataset Name","description":"New display name for the dataset"}},"type":"object","required":["dataset_name"],"title":"UpdateDatasetRequest","description":"Request body for updating dataset metadata."},"UpdateDatasetResponse":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id","description":"Dataset ID that was updated"},"dataset_name":{"type":"string","title":"Dataset Name","description":"New dataset name"},"updated_at":{"type":"string","title":"Updated At","description":"ISO timestamp of update"}},"type":"object","required":["dataset_id","dataset_name","updated_at"],"title":"UpdateDatasetResponse","description":"Response after updating dataset."},"UpdateDomainRequest":{"properties":{"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"provider_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Config"},"strip_tracking_on_read":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Strip Tracking On Read"}},"type":"object","title":"UpdateDomainRequest"},"UpdateLimitsRequest":{"properties":{"daily_connection_limit":{"anyOf":[{"type":"integer","maximum":200.0,"minimum":1.0},{"type":"null"}],"title":"Daily Connection Limit"},"daily_message_limit":{"anyOf":[{"type":"integer","maximum":500.0,"minimum":1.0},{"type":"null"}],"title":"Daily Message Limit"},"warmup_days":{"anyOf":[{"type":"integer","maximum":30.0,"minimum":0.0},{"type":"null"}],"title":"Warmup Days"}},"type":"object","title":"UpdateLimitsRequest","description":"Request to update connected account daily limits."},"UpdateSenderDataRequest":{"properties":{"sender_data":{"additionalProperties":true,"type":"object","title":"Sender Data","description":"Additional sender data"},"merge_strategy":{"type":"string","title":"Merge Strategy","description":"How to merge data (update/replace)","default":"update"}},"type":"object","required":["sender_data"],"title":"UpdateSenderDataRequest","description":"Request model for updating sender data."},"UserExtraction":{"properties":{"id":{"type":"string","title":"Id","description":"Unique extraction identifier"},"user_id":{"type":"string","title":"User Id","description":"User ID who owns this extraction"},"filename":{"type":"string","title":"Filename","description":"Original filename of the extracted data"},"title":{"type":"string","title":"Title","description":"Display title for the extraction"},"source":{"type":"string","title":"Source","description":"Source of the extraction (e.g., 'PitchBook', 'LinkedIn')"},"record_count":{"type":"integer","title":"Record Count","description":"Number of records in the extraction"},"file_size":{"type":"integer","title":"File Size","description":"Size of the file in bytes"},"is_excel":{"type":"boolean","title":"Is Excel","description":"Whether this is an Excel file"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When the extraction was created"},"extraction_date":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Extraction Date","description":"Original extraction date info"}},"type":"object","required":["id","user_id","filename","title","source","record_count","file_size","is_excel","created_at"],"title":"UserExtraction","description":"User extraction model for listing available extracted files."},"ValidateEmailRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"ValidateEmailRequest"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VariantSourceType":{"type":"string","enum":["TEMPLATE","PERSONALIZATION"],"title":"VariantSourceType","description":"Step variant source type."},"VerifyRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email","description":"Email address to verify"},"force":{"type":"boolean","title":"Force","description":"Force re-verification even if cached","default":false}},"type":"object","required":["email"],"title":"VerifyRequest"},"api__routers__agent_chat__ChatRequest":{"properties":{"thread_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Thread Id","description":"Existing thread ID to resume"},"message":{"type":"string","maxLength":10000,"title":"Message","default":""},"page_context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Page Context"},"resume":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Resume","description":"Resume payload for interrupt confirmation (e.g. {confirmed: true})"}},"type":"object","title":"ChatRequest"},"api__routers__datasets__list__DatasetListResponse":{"properties":{"datasets":{"items":{"$ref":"#/components/schemas/DatasetWithLatestSession"},"type":"array","title":"Datasets","description":"List of datasets"},"total_count":{"type":"integer","title":"Total Count","description":"Total number of datasets matching criteria"},"page":{"type":"integer","title":"Page","description":"Current page number"},"page_size":{"type":"integer","title":"Page Size","description":"Number of items per page"}},"type":"object","required":["datasets","total_count","page","page_size"],"title":"DatasetListResponse"},"api__routers__generation_history__DatasetListResponse":{"properties":{"datasets":{"items":{"$ref":"#/components/schemas/DatasetSummary"},"type":"array","title":"Datasets"},"has_more":{"type":"boolean","title":"Has More","default":false}},"type":"object","required":["datasets"],"title":"DatasetListResponse"},"api__routers__sender_profile_chat__ChatRequest":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Unique session identifier"},"message":{"type":"string","title":"Message","description":"User's message"},"context":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Context","description":"Current conversation context and collected data"}},"type":"object","required":["session_id","message"],"title":"ChatRequest","description":"Request model for chat interactions."},"api__routers__sessions__management__CreateSessionResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Unique session identifier"},"status":{"type":"string","title":"Status","description":"Current session status"},"created_at":{"type":"number","title":"Created At","description":"Session creation timestamp"}},"type":"object","required":["session_id","status","created_at"],"title":"CreateSessionResponse","description":"Response model for session creation."},"api__routers__user_extractions__CreateSessionResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Created session ID"},"dataset_id":{"type":"string","title":"Dataset Id","description":"Created dataset ID"},"leads_count":{"type":"integer","title":"Leads Count","description":"Number of leads loaded"},"status":{"type":"string","title":"Status","description":"Session status"}},"type":"object","required":["session_id","dataset_id","leads_count","status"],"title":"CreateSessionResponse","description":"Response model for creating a session from an extraction."}},"securitySchemes":{"HTTPBearer":{"type":"http","scheme":"bearer"}}},"tags":[{"name":"API Keys","description":"Create, list, and revoke API keys for programmatic access. JWT authentication required."},{"name":"credits","description":"Credit balance, cost estimates, and transaction history."},{"name":"campaigns","description":"Create, manage, launch, and monitor email campaigns."},{"name":"campaign-personalization","description":"AI-powered email subject and body personalization for campaigns."},{"name":"email-finder","description":"Find and verify email addresses for prospects."},{"name":"email-verification","description":"Validate email addresses and prune invalid entries from datasets."},{"name":"sender-profiles","description":"Manage sender identity profiles for outreach."},{"name":"sender-profile-chat","description":"Interactive chat for building sender profiles."},{"name":"templates","description":"Email template CRUD."},{"name":"suppression","description":"Do-not-contact suppression list management."},{"name":"datasets","description":"Lead dataset listing, download, and updates."},{"name":"user-extractions","description":"Uploaded lead file management and processing."},{"name":"enrichment-chat","description":"Interactive chat for data enrichment sessions."},{"name":"enrichment-processing","description":"Batch lead enrichment processing."},{"name":"File Upload (CSV/Excel)","description":"Upload and preview CSV/Excel lead files."},{"name":"connected-accounts","description":"LinkedIn account connections via Unipile."},{"name":"linkedin-content","description":"LinkedIn post creation, scheduling, and management."},{"name":"linkedin-playground","description":"Direct LinkedIn actions (profile lookup, messaging, engagement)."},{"name":"bavimail-proxy","description":"BaviMail domain, alias, and email management."},{"name":"agent","description":"Bavi AI agent chat with SSE streaming."},{"name":"notifications","description":"Notification preferences and delivery."},{"name":"referral","description":"Referral code management and stats."},{"name":"feedback","description":"User feedback submission."},{"name":"authentication","description":"JWT token verification and user info."},{"name":"Google OAuth","description":"Google OAuth login flow and access tokens."},{"name":"Google Sheets OAuth","description":"Google Sheets import and access management."},{"name":"stripe","description":"Stripe checkout, billing portal, and subscription status. JWT only."},{"name":"users","description":"User quota and usage information."},{"name":"Health","description":"Health checks and system status."},{"name":"Personalization","description":"Core lead personalization engine."},{"name":"Session Management","description":"Enrichment session lifecycle."},{"name":"Session Processing","description":"Session data processing."},{"name":"webhooks","description":"Inbound webhook handlers (Stripe, BaviMail, Unipile)."}]}