{"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","x-guidance":{"product":"Bavlio Data API","protocols":["x402"],"description":"Pay-per-call B2B data endpoints for AI agents. USDC on Base mainnet via x402 v2. See /openapi.json for pricing. Landing page + marketing details: https://bavlio.com/developers","network":"eip155:8453","docs_url":"https://docs.bavlio.com"},"x-payment-merchant-address":"0xcca4725e0e931982830bff523b141e1a7a58d3e7"},"paths":{"/api/x402/v1/email/verify":{"post":{"tags":["x402"],"summary":"Verify deliverability via SMTP RCPT probe (x402-paid, $0.005 USDC)","description":"SYNC inline SMTP verify. No ARQ. No user context. Idempotent.\n\nThe x402 payment middleware runs BEFORE this handler (PaymentMiddlewareASGI\nintercepts on path match). Settlement happens AFTER handler return iff\n``status < 400``. An adapter timeout / upstream error returns 4xx/5xx and\nskips settlement per the lib invariant.","operationId":"email_verify_api_x402_v1_email_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailVerifyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailVerifyResponse"}}}},"422":{"description":"Non-definitive verdict (catch-all domain or inconclusive probe): NOT charged (no x402 settlement). A definitive valid/invalid settles (200).","content":{"application/json":{"example":{"detail":{"error":"ERR_EMAIL_VERIFY_NOT_DEFINITIVE","result":"catch_all","is_catch_all":true}}}}}},"x-payment-info":{"protocols":[{"x402":{}}],"price":{"mode":"fixed","amount":5000,"currency":"USDC","atomic_units":true},"pricing_breakdown":"0.005 USDC per call on base-mainnet","network":"base-mainnet","timeout_seconds":10,"description":"Deliverability check via SMTP RCPT probe (Reacher backend).","pay_to":"0xcca4725e0e931982830bff523b141e1a7a58d3e7"},"x-agent-examples":[{"scenario":"Agent drafting a cold email needs to pre-verify deliverability","input":{"email":"prospect@acme.com"},"expected_outcome":"200 with result=valid|invalid + backend (charged for a definitive verdict)"},{"scenario":"Prospecting pipeline dedupes bounces before an outreach wave","input":{"email":"dan@startup.io"},"expected_outcome":"200 with result=valid on deliverable addresses (charged)"},{"scenario":"Catch-all or inconclusive domain — not charged","input":{"email":"anyone@catchall.io"},"expected_outcome":"422 ERR_EMAIL_VERIFY_NOT_DEFINITIVE (catch_all/unknown), NO settlement"}]}},"/api/x402/v1/email/validate":{"post":{"tags":["x402"],"summary":"Email deliverability check, SMTP-backed (x402-paid, $0.003 USDC)","description":"SMTP-backed inline validate. No ARQ. No user context. Idempotent.\n\nPrefilter hard-rejects (bad syntax / reserved / placeholder / system) settle a\nstable ``risk_level == \"invalid\"`` payload rather than raising — the agent\nasked a question and got a definitive answer. Otherwise the SMTP verdict is\nmapped into the unchanged DTO; a non-answer (SMTP unavailable) returns 503 so\nx402 skips settlement.","operationId":"email_validate_api_x402_v1_email_validate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailValidateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailValidateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-payment-info":{"protocols":[{"x402":{}}],"price":{"mode":"fixed","amount":3000,"currency":"USDC","atomic_units":true},"pricing_breakdown":"0.003 USDC per call on base-mainnet","network":"base-mainnet","timeout_seconds":10,"description":"Deliverability check: prefilter (syntax/reserved/placeholder/role) + SMTP RCPT probe, mapped to valid_format/has_mx/is_disposable/is_role/risk_level. No user key required.","pay_to":"0xcca4725e0e931982830bff523b141e1a7a58d3e7"},"x-agent-examples":[{"scenario":"Fast pre-flight check before committing to a paid SMTP verify","input":{"email":"maybe@acme.com"},"expected_outcome":"200 with has_mx + risk_level=safe|risky|invalid"},{"scenario":"Agent filtering free-mail / disposable addresses from a lead list","input":{"email":"user@guerrillamail.com"},"expected_outcome":"200 with is_disposable=true"},{"scenario":"Role-account detector for campaign hygiene","input":{"email":"info@company.com"},"expected_outcome":"200 with is_role=true"}]}},"/api/x402/v1/email/find":{"post":{"tags":["x402"],"summary":"Find working email via sequential SMTP pattern probing (x402-paid, $0.010 USDC)","description":"SYNC inline SMTP find. No ARQ. No user context. Idempotent per candidate list.\n\nCaller either pre-computes candidates or passes first/last/domain and we\ngenerate them. Returns the first pattern that SMTP-validates, or\n``found=false`` if none did.","operationId":"email_find_api_x402_v1_email_find_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailFindRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmailFindResponse"}}}},"422":{"description":"Catch-all / accept-all domain: best-guess only, NOT charged (no x402 settlement). The body carries the best-guess for verify-before-send.","content":{"application/json":{"example":{"detail":{"error":"ERR_EMAIL_FIND_CATCH_ALL","is_catch_all":true,"email":"dan@acme.com","pattern":"first"}}}}}},"x-payment-info":{"protocols":[{"x402":{}}],"price":{"mode":"fixed","amount":10000,"currency":"USDC","atomic_units":true},"pricing_breakdown":"0.010 USDC per call on base-mainnet","network":"base-mainnet","timeout_seconds":8,"description":"Find working email for a person at a domain via sequential SMTP pattern probing. Pass candidates OR first_name + last_name + domain.","pay_to":"0xcca4725e0e931982830bff523b141e1a7a58d3e7"},"x-agent-examples":[{"scenario":"Agent building a prospecting pipeline — find the email from first_name/last_name/domain","input":{"first_name":"Dan","last_name":"Roberts","domain":"acme.com"},"expected_outcome":"200 with found=true + email=dan@acme.com + pattern + backend, OR found=false on exhaustion"},{"scenario":"Agent has pre-computed candidates (e.g. from LinkedIn + pattern inference), narrow to the live one","input":{"candidates":[{"email":"d.roberts@acme.com","pattern":"f.last","confidence":0.6},{"email":"dan@acme.com","pattern":"first","confidence":0.4}],"domain":"acme.com"},"expected_outcome":"200 with found=true pointing at the RCPT-accepting candidate + pattern field matches"},{"scenario":"Bulk enrichment worker — accept soft-exhaustion (all backends tried, no match)","input":{"first_name":"Obscure","last_name":"Person","domain":"nomatch.com"},"expected_outcome":"200 with found=false (NOT 402/503 — this is paid info)"}]}},"/api/x402/v1/linkedin/find-url":{"post":{"tags":["x402"],"summary":"Find LinkedIn profile URL via public search engines (x402-paid, $0.008 USDC)","description":"SYNC inline search. No ARQ. No user context. Idempotent per query.","operationId":"linkedin_find_url_api_x402_v1_linkedin_find_url_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInFindUrlRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInFindUrlResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-payment-info":{"protocols":[{"x402":{}}],"price":{"mode":"fixed","amount":8000,"currency":"USDC","atomic_units":true},"pricing_breakdown":"0.008 USDC per call on base-mainnet","network":"base-mainnet","timeout_seconds":12,"description":"Find LinkedIn profile URL for a person via public search engines. No LinkedIn-proprietary data returned. First-party + resellable.","pay_to":"0xcca4725e0e931982830bff523b141e1a7a58d3e7"},"x-agent-examples":[{"scenario":"Agent enriching a lead with name + company context","input":{"name":"Dan Roberts","company":"Acme Corp"},"expected_outcome":"200 with status=found + linkedin_url=https://linkedin.com/in/... + profiles[].match_confidence"},{"scenario":"Agent has only a name (generic), low-confidence expected","input":{"name":"John Smith"},"expected_outcome":"200 with status=not_found when all candidate profiles score below the 0.3 confidence threshold"},{"scenario":"Agent narrows to a specific country via the location bias","input":{"name":"Jane Doe","company":"Tesla","location":"de"},"expected_outcome":"200 with status=found + Germany-biased profile match, or status=not_found"}]}},"/api/x402/v1/prospects/search":{"post":{"tags":["x402"],"summary":"Search prospect pool by tag overlap (x402-paid, $0.012 USDC)","description":"SYNC inline Supabase read. No ARQ. No user context. Idempotent.","operationId":"prospects_search_api_x402_v1_prospects_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProspectSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProspectSearchResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"x-payment-info":{"protocols":[{"x402":{}}],"price":{"mode":"fixed","amount":12000,"currency":"USDC","atomic_units":true},"pricing_breakdown":"0.012 USDC per call on base-mainnet","network":"base-mainnet","timeout_seconds":10,"description":"Search the shared prospect pool by tag overlap. Read-only; returns up to 100 first-party-discovered LinkedIn profiles (default limit 20, max 100).","pay_to":"0xcca4725e0e931982830bff523b141e1a7a58d3e7"},"x-agent-examples":[{"scenario":"Agent hunting for B2B prospects by role + industry tags","input":{"tags":["founder","ai"],"limit":50},"expected_outcome":"200 with count=N + results=[{linkedin_url, full_name, company, tags, ...}, ...] up to 50"},{"scenario":"Agent looking for prospects by job function intersection (no limit override; default 20)","input":{"tags":["engineering manager"]},"expected_outcome":"200 with count<=20 + results[] matching tag overlap"},{"scenario":"Agent gets count=0 when the tag combination has no match","input":{"tags":["niche rare title"]},"expected_outcome":"200 with count=0 + results=[] (NOT an error — this is paid info)"}]}},"/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).\n\nAlso provisions + maps the user's Autumn customer (Epic 1) so the Epic 3\nwebhook release gate (autumn_customer_id IS NULL = 0) can pass. The map is\nfail-open and runs before the SES send so a transient email failure does\nnot skip billing provisioning; create_customer is idempotent-by-id, so\nretrying the welcome email after a 502 re-maps harmlessly.","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/onboarding-status":{"get":{"tags":["users"],"summary":"Get Onboarding Status","description":"Return lightweight setup facts used by dashboard onboarding gates.","operationId":"get_onboarding_status_api_v1_users_onboarding_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Onboarding Status Api V1 Users Onboarding Status Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/complete-onboarding":{"post":{"tags":["users"],"summary":"Complete Onboarding Endpoint","description":"Complete onboarding outside the chat stream via the existing tool path.","operationId":"complete_onboarding_endpoint_api_v1_users_complete_onboarding_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CompleteOnboardingRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Complete Onboarding Endpoint Api V1 Users Complete Onboarding 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"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/users/usage":{"get":{"tags":["users"],"summary":"Get Usage Dashboard","description":"Get the user's current credit and lead usage summary.\n\nMonthly quota fields describe only the recurring monthly allocation. The\ntotal spendable balance and top-up balance are returned separately.\n\nArgs:\n    user_info: Authenticated user information from JWT\n    usage_service: Usage tracking service instance\n    credit_service: Credit balance service instance\n\nReturns:\n    Dictionary containing the current usage summary.","operationId":"get_usage_dashboard_api_v1_users_usage_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Usage Dashboard Api V1 Users Usage Get"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"403":{"description":"Forbidden - Insufficient permissions"}},"security":[{"HTTPBearer":[]}]}},"/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":{"$ref":"#/components/schemas/CreditTransactionListResponse"}}}},"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/promo/redeem":{"post":{"tags":["promo"],"summary":"Redeem a promo code via Autumn billing.attach with CAS lock","description":"Authenticated promo redemption. Rate-limited to 5 attempts/credential/hour AND 60 attempts/IP/hour. On Autumn 5xx the endpoint returns 503 with `manual_review_required=true` and pages operations -- it never silently drops a redemption.","operationId":"redeem_promo_api_promo_redeem_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Redeem Promo Api Promo Redeem Post"}}}}},"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/api__routers__sessions__management__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":"include_internal","in":"query","required":false,"schema":{"type":"boolean","description":"Include datasets created by internal QA tooling","default":false,"title":"Include Internal"},"description":"Include datasets created by internal QA tooling"},{"name":"source_category","in":"query","required":false,"schema":{"anyOf":[{"enum":["lead_finder","file_upload","api","manual","internal","other"],"type":"string"},{"type":"null"}],"description":"Canonical source category filter","title":"Source Category"},"description":"Canonical source category filter"},{"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}/subset":{"post":{"tags":["datasets","datasets"],"summary":"Create a dataset from selected rows","description":"Copy exact stable rows through the tenant-fenced atomic RPC.","operationId":"create_dataset_subset_api_v1_datasets__dataset_id__subset_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/CreateDatasetSubsetRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDatasetSubsetResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/datasets/{dataset_id}/row-usage/query":{"post":{"tags":["datasets","datasets"],"summary":"Query copied-row destinations","description":"Return direct copy destinations for the requested rows in one scoped dataset.","operationId":"get_dataset_row_usage_api_v1_datasets__dataset_id__row_usage_query_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/DatasetRowUsageRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetRowUsageResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/datasets/combine":{"post":{"tags":["datasets","datasets"],"summary":"Combine datasets into a new list","description":"Combine source lists through the tenant-fenced atomic RPC.","operationId":"combine_datasets_api_v1_datasets_combine_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CombineDatasetsRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CombineDatasetsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/datasets/{dataset_id}/rows/delete":{"post":{"tags":["datasets","datasets"],"summary":"Delete dataset rows","description":"Delete up to 200 exact persisted stable row IDs from a dataset","operationId":"delete_dataset_rows_api_v1_datasets__dataset_id__rows_delete_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/DeleteDatasetRowsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteDatasetRowsResponse"}}}},"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\nThe sender-profile creation limit is determined by the user's plan.\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 actor's org (B2b read cutover).\n\nRetrieves all sender profiles owned by the org (shared across members) with\noptional pagination. Profiles are sorted by creation date (newest first).\n\nArgs:\n    org_context: Resolved org scope for the actor\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 org","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/SenderProfileListItem"},"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 actor's org has access (B2b read\ncutover: sender_profiles are org-owned, shared across members).\n\nArgs:\n    profile_id: The ID of the profile to retrieve\n    org_context: Resolved org scope for the actor\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 actor's org has access (B2b read cutover).\n\nArgs:\n    profile_id: The ID of the profile to delete\n    org_context: Resolved org scope for the actor\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 (B2b read cutover).\n\nSearches through the actor's org profiles for those matching the search\nquery. Search is case-insensitive and matches partial names.\n\nArgs:\n    query: Search query string\n    org_context: Resolved org scope for the actor\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 actor's org (B2b read cutover).\n\nRetrieves the org's default profile if one exists.\n\nArgs:\n    org_context: Resolved org scope for the actor\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/prompts":{"get":{"tags":["workspace-prompts"],"summary":"List Workspace Prompts","operationId":"list_workspace_prompts_api_v1_prompts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspacePromptList"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["workspace-prompts"],"summary":"Create Workspace Prompt","operationId":"create_workspace_prompt_api_v1_prompts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspacePromptCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspacePromptOut"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/prompts/{prompt_id}":{"patch":{"tags":["workspace-prompts"],"summary":"Update Workspace Prompt","operationId":"update_workspace_prompt_api_v1_prompts__prompt_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string","title":"Prompt Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspacePromptUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspacePromptOut"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["workspace-prompts"],"summary":"Delete Workspace Prompt","operationId":"delete_workspace_prompt_api_v1_prompts__prompt_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string","title":"Prompt Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/prompts/{prompt_id}/attach":{"post":{"tags":["workspace-prompts"],"summary":"Attach Workspace Prompt","operationId":"attach_workspace_prompt_api_v1_prompts__prompt_id__attach_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string","title":"Prompt Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspacePromptAttachment"}}}},"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/prompts/{prompt_id}/detach":{"post":{"tags":["workspace-prompts"],"summary":"Detach Workspace Prompt","operationId":"detach_workspace_prompt_api_v1_prompts__prompt_id__detach_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string","title":"Prompt Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkspacePromptAttachment"}}}},"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized"},"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 attach a saved sender profile","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 or attach a saved sender profile","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":[]}],"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"}}},"get":{"tags":["campaigns"],"summary":"List Campaigns","description":"List all campaigns for the caller's org (shared across members).\n\nArgs:\n    org_context: Resolved org scope for the request (B1b-read)\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 the org's 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 (org-scoped).\n\nArgs:\n    campaign_id: Campaign ID\n    org_context: Resolved org scope for the request (B1b-read)\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. ORG-scoped (PR2d): any member of the owning\norg may edit the shared campaign.\n\nArgs:\n    campaign_id: Campaign ID\n    request: Update request\n    org_context: Resolved org scope for the request (actor + org)\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"}}],"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).\nORG-scoped (PR2d): any member of the owning org may delete the shared campaign.\n\nArgs:\n    campaign_id: Campaign ID\n    org_context: Resolved org scope for the request (actor + org)\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.\nORG-scoped (PR2d): any member of the owning org may preflight the campaign.","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.\nORG-scoped (PR2d): any member of the owning org may launch the campaign;\n``current_user`` is the actor (carried through for the BaviMail user_context).","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"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CampaignLaunchRequest"},{"type":"null"}],"title":"Request"}}}},"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.\n\nORG-scoped (PR2d): any member of the owning org may view the launch results.","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.\nORG-scoped (PR2d): any member of the owning org may pause the shared campaign.\n\nArgs:\n    campaign_id: Campaign ID\n    org_context: Resolved org scope for the request (actor + org)\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}/leads/add":{"post":{"tags":["campaigns"],"summary":"Add Campaign Leads","description":"Append selected lists and enroll their new rows through the launch pipeline.","operationId":"add_campaign_leads_api_v1_campaigns__campaign_id__leads_add_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/api__models__campaigns__AddLeadsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLeadsResponse"}}}},"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}/source-lists":{"get":{"tags":["campaigns"],"summary":"Get Campaign Source Lists","description":"Return lists previously added to this org-readable campaign.","operationId":"get_campaign_source_lists_api_v1_campaigns__campaign_id__source_lists_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/CampaignSourceListsResponse"}}}},"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\nORG-scoped (PR2d): any member of the owning org may resume the shared\ncampaign; ``current_user`` is the actor (carried through for user_context).\n\nArgs:\n    campaign_id: Campaign ID\n    current_user: Authenticated user information (actor)\n    org_context: Resolved org scope for the request\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 (org-scoped).","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 (org-scoped).","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 (org-scoped).","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 (org-scoped).","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}/activity":{"get":{"tags":["campaigns"],"summary":"Get Campaign Activity","description":"Campaign-wide activity feed (W2-A4b). `before`+`limit` page backward;\n`since` polls for new events — two distinct params, distinct semantics.","operationId":"get_campaign_activity_api_v1_campaigns__campaign_id__activity_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Backward 'load more': events strictly OLDER than this.","title":"Before"},"description":"Backward 'load more': events strictly OLDER than this."},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Forward polling: events strictly NEWER than this.","title":"Since"},"description":"Forward polling: events strictly NEWER than this."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by normalized event type(s).","title":"Event Type"},"description":"Filter by normalized event type(s)."},{"name":"step","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":1},{"type":"null"}],"description":"Filter to a sequence step (jobs only).","title":"Step"},"description":"Filter to a sequence step (jobs only)."},{"name":"lead_search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to a lead by email / identifier.","title":"Lead Search"},"description":"Filter to a lead by email / identifier."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignActivityResponse"}}}},"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}/draft-audience":{"get":{"tags":["campaigns"],"summary":"Get Campaign Draft Audience","description":"Return the selected dataset rows for a draft campaign without materializing leads.","operationId":"get_campaign_draft_audience_api_v1_campaigns__campaign_id__draft_audience_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"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":20,"title":"Page Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDraftAudienceResponse"}}}},"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}/merge-fields":{"get":{"tags":["campaigns"],"summary":"Get Campaign Merge Fields","description":"Return real merge fields from the campaign's selected dataset.","operationId":"get_campaign_merge_fields_api_v1_campaigns__campaign_id__merge_fields_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/CampaignMergeFieldsResponse"}}}},"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 (org-scoped).\n\nIncludes lead data from the dataset for display purposes.\n\nArgs:\n    campaign_id: Campaign ID\n    org_context: Resolved org scope for the request (B1b-read)\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}/messages":{"get":{"tags":["campaigns"],"summary":"Get Lead Messages","description":"Return per-step sent (or pending) email content for a campaign lead (org-scoped).\n\nSourced from `outbound_jobs.content` (capped at 200 rows/lead). Rows not yet\nsent (queued/scheduled/claimed/generating) are included with null\nsubject/body so the same UI drawer can preview upcoming steps. Ordered by\nstep asc.","operationId":"get_lead_messages_api_v1_campaigns__campaign_id__leads__campaign_lead_id__messages_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":{"$ref":"#/components/schemas/LeadMessagesResponse"}}}},"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}/leads/{campaign_lead_id}/timeline":{"get":{"tags":["campaigns"],"summary":"Get Lead Timeline","description":"Composed per-lead timeline (W2-A4a): outbound_jobs lifecycle +\nengagement_log + BaviMail email-events (cached, degrades). `degraded=true`\nmeans only local events are shown because BaviMail was unavailable.","operationId":"get_lead_timeline_api_v1_campaigns__campaign_id__leads__campaign_lead_id__timeline_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":{"$ref":"#/components/schemas/LeadTimelineResponse"}}}},"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/steps/draft":{"post":{"tags":["campaigns"],"summary":"Draft or critique copy for a campaign step","description":"Generate free editor-time copy using the org-scoped sender-profile service.","operationId":"draft_campaign_step_copy_api_v1_campaigns_steps_draft_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignStepCopyDraftRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignStepCopyDraftResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/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/draft":{"put":{"tags":["playground"],"summary":"Save Working Draft","description":"Auto-save an unapproved in-progress edit for one (lead, step).\n\nPersists into ``campaign_leads.metadata.working_drafts[step_index]`` via\nthe same CAS merge as approve. A working draft NEVER sends — approve stays\nthe only ship action. The frontend debounce-fires this while the reviewer\ntypes so edits survive a refresh without being approved.","operationId":"save_working_draft_api_v1_campaigns__campaign_id__playground_draft_put","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/SaveWorkingDraftRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveWorkingDraftResponse"}}}},"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/leads/{campaign_lead_id}/regenerate":{"post":{"tags":["playground"],"summary":"Playground Regenerate Lead","description":"Enqueue a one-lead playground generation batch for an existing lead.","operationId":"playground_regenerate_lead_api_v1_campaigns__campaign_id__playground_leads__campaign_lead_id__regenerate_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/PlaygroundRegenerateRequest"}}}},"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/prompt":{"get":{"tags":["playground"],"summary":"Playground Prompt","description":"Read-only resolved personalization prompt for a step.\n\nNever enqueues or writes — safe to call at any time, including while a\nbatch is running, so the playground can surface the prompt in use without\nbeing gated behind batch controls.","operationId":"playground_prompt_api_v1_campaigns__campaign_id__playground_prompt_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"step_index","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"Sequence step to resolve the prompt for.","default":1,"title":"Step Index"},"description":"Sequence step to resolve the prompt for."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaygroundStepPromptResponse"}}}},"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 caller's org (shared across members).\n\nArgs:\n    org_context: Resolved org scope for the request (B1b-read)\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/starter":{"get":{"tags":["templates"],"summary":"Get Starter Templates","description":"Return starter email templates that read as the CALLER's business.\n\nGenerated deterministically from the org's default sender profile so a\ncustomer sees copy selling their business to their ICP, never Bavlio's. When\nthe org has no usable sender profile, returns generic industry-neutral copy\nthat names no company.\n\nStrictly org-scoped: the sender profile is fetched via the org's default\naccessor, so one org can never see another's copy.","operationId":"get_starter_templates_api_v1_templates_starter_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StarterTemplatesResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing JWT token"},"404":{"description":"Template not found"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/templates/{template_id}":{"get":{"tags":["templates"],"summary":"Get Template","description":"Get a specific template by ID (org-scoped).\n\nArgs:\n    template_id: Template ID\n    org_context: Resolved org scope for the request (B1b-read)\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 (org-scoped).\n\nArgs:\n    template_id: Template ID\n    request: Update request\n    org_context: Resolved org scope for the request (B1b-read)\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 (org-scoped).\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    org_context: Resolved org scope for the request (B1b-read)\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/connect":{"post":{"tags":["bavimail-proxy"],"summary":"Connect a user-owned BaviMail API key","description":"Validates and stores the calling user's BaviMail API key. Rate-limited to 5 attempts/minute per authenticated credential in each API process.","operationId":"connect_bavimail_api_v1_bavimail_connect_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectBavimailRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BavimailConnectionResponse"}}}},"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":[]}]},"delete":{"tags":["bavimail-proxy"],"summary":"Disconnect BaviMail for the calling user","operationId":"disconnect_bavimail_api_v1_bavimail_connect_delete","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BavimailConnectionResponse"}}}},"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":[]}]}},"/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/attachments":{"post":{"tags":["bavimail-proxy"],"summary":"Upload Campaign Attachments","description":"Upload files into BaviMail attachment storage for use as campaign step\nattachments.\n\nThe size cap + MIME allowlist are enforced here on the REAL bytes (the\nauthoritative gate); `CampaignStepConfig` re-validates the stored refs as\ndefense-in-depth. Returns BaviMail attachment references in the exact shape\nof `CampaignStepAttachment` — the client persists these into the step's\n`attachments` array in `steps_config`, and the worker re-fetches the bytes by\n`attachment_id` at send time.","operationId":"upload_campaign_attachments_api_v1_bavimail_attachments_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_campaign_attachments_api_v1_bavimail_attachments_post"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Upload Campaign Attachments Api V1 Bavimail Attachments 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/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 content for a campaign lead.\n\nEmail (the default channel) is called by the Worker Lambda (via internal\nAPI key) or directly by authenticated users (via JWT). The LinkedIn AI\npersonalization channel is INTERNAL-AUTH ONLY (CB3) and returns a\nbody-only DM. The channel is resolved from the loaded STEP config (the\nrequest `channel` is advisory only) so a JWT caller cannot bypass the\nLinkedIn guard by omitting / spoofing `channel`.","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.\n\nInserts with ``scope`` matching the caller's owned scope (server-resolved).\n``user_id`` is retained as audit metadata.","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 within the caller's owned scope.\n\nA bavlio_owned caller sees every row inserted by any Bavlio-owned user\n(unified Bavlio + BaviMail suppression). A sapienex caller sees only\nsapienex rows. RLS at the DB layer enforces the same boundary.","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 within the caller's scope.\n\nCannot delete cross-scope rows: a sapienex caller cannot delete\nbavlio_owned rows and vice versa. RLS enforces the same boundary at the\nDB layer if a client tries to bypass this filter.","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/queue":{"get":{"tags":["review_queue"],"summary":"List Queue Items","description":"List the caller's review queue items, ordered by created_at desc.","operationId":"list_queue_items_api_v1_queue_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by queue item status","title":"Status"},"description":"Filter by queue item status"},{"name":"channel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by channel","title":"Channel"},"description":"Filter by channel"},{"name":"campaign_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by campaign","title":"Campaign Id"},"description":"Filter by campaign"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque pagination cursor","title":"Cursor"},"description":"Opaque pagination cursor"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/queue/stats":{"get":{"tags":["review_queue"],"summary":"Get Queue Stats","description":"Return per-status counts for the caller's queue items.\n\nUses one ``count=\"exact\", head=True`` request per status enum value.\nFour small head-only queries beat one full table scan; PostgREST\nonly returns the Content-Range header so payload is tiny. If queue\ncardinality per user ever exceeds ~50k pending rows we can replace\nthis with a SECURITY DEFINER RPC that does a single GROUP BY.","operationId":"get_queue_stats_api_v1_queue_stats_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueStatsResponse"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/queue/{item_id}":{"get":{"tags":["review_queue"],"summary":"Get Queue Item","description":"Return a single queue item plus the linked classification row.\n\nCross-tenant probes return **404** (not 403): an attacker must not\nbe able to distinguish \"this id does not exist\" from \"this id\nbelongs to someone else\" by status code alone.\n\nTwo sequential reads instead of a PostgREST embed because the\nshared ``AsyncTable.execute`` does not emit the ``select`` query\nparameter to the wire, so ``select=*,reply_classifications(*)``\nwould be silently dropped and the join would never round-trip. The\nsecond read is skipped entirely when ``classification_id`` is null,\nwhich is the common case for v1 non-classifier writers.\n\nThe classification read is filtered by BOTH ``id`` and ``user_id``\neven though the queue row already passed tenant scoping. Defense in\ndepth: if a bad FK or race ever wrote a cross-user classification_id\ninto a queue row, service-role bypasses RLS and would otherwise leak\nthe classification to the wrong tenant. Missing match returns\nclassification=null (same as a missing FK).","operationId":"get_queue_item_api_v1_queue__item_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Item Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueItemDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/queue/{item_id}/resolve":{"post":{"tags":["review_queue"],"summary":"Resolve Queue Item Endpoint","description":"Resolve a pending review queue item.\n\nAtomic 3-step inside ``cas_resolve_queue_item`` (migration 151):\n  1. CAS queue row pending -> resolved.\n  2. Conditional campaign_leads transition keyed on resolution_action.\n  3. Emit one engagement_log state_transition row.\n\nFor ``stop_and_suppress`` only: a second RPC call writes the\nsuppression row via ``cas_create_suppression``. The queue resolve\nitself does not roll back when the suppression write fails (the\nqueue state is already correct; operator can retry via the\nsuppression CRUD endpoint).\n\nReturns:\n    200 + ``QueueResolveResponse`` on success.\n    404 when the queue item is absent (or cross-tenant).\n    409 when the queue item was already in a terminal state\n        (resolved, auto_resolved, expired) or when the idempotency\n        key already reserved a duplicate-in-flight resolve.\n    422 when ``resolution_action_params`` is malformed (caught at\n        the pydantic layer for the pause_* branches).","operationId":"resolve_queue_item_endpoint_api_v1_queue__item_id__resolve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Item Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueResolveRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueueResolveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/engagement-log/prospect/{prospect_identifier}":{"get":{"tags":["engagement_log"],"summary":"List Prospect Events","description":"List engagement events for a prospect, newest-first.\n\nRequired filter is ``(prospect_identifier, prospect_identifier_type)``;\nthat pair is part of the supporting index ``idx_engagement_log_user_prospect``\n(migration 147) on ``(user_id, prospect_identifier_type,\nprospect_identifier, occurred_at DESC)`` so the seek to the first\npage is index-driven even when the user has millions of unrelated\nrows. The index does NOT include ``id``, so the ORDER BY tie-break\non ``id DESC`` falls through to a small in-page sort. That's fine\nin practice: rows sharing a single microsecond ``occurred_at`` are\nrare (only happens when a webhook handler fans out events inside\none transaction), and the tie-break scan is bounded by the page\nsize (``limit + 1``).","operationId":"list_prospect_events_api_v1_engagement_log_prospect__prospect_identifier__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"prospect_identifier","in":"path","required":true,"schema":{"type":"string","title":"Prospect Identifier"}},{"name":"type","in":"query","required":false,"schema":{"type":"string","description":"Prospect identifier type","default":"email","title":"Type"},"description":"Prospect identifier type"},{"name":"event_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by event_type","title":"Event Type"},"description":"Filter by event_type"},{"name":"channel","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by channel","title":"Channel"},"description":"Filter by channel"},{"name":"campaign_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Filter by campaign","title":"Campaign Id"},"description":"Filter by campaign"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque pagination cursor","title":"Cursor"},"description":"Opaque pagination cursor"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EngagementListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/engagement-log/{event_id}":{"get":{"tags":["engagement_log"],"summary":"Get Engagement Event","description":"Return a single engagement_log event.\n\nCross-tenant probes return **404** (not 403): an attacker must not\nbe able to distinguish \"this id does not exist\" from \"this id\nbelongs to someone else\" by status code alone. Service-role\nbypasses RLS so the ``.eq(\"user_id\", user_id)`` filter is the only\ntenant fence on this read path.","operationId":"get_engagement_event_api_v1_engagement_log__event_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"event_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Event Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EngagementEvent"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/unsubscribe":{"get":{"tags":["unsubscribe"],"summary":"Unsubscribe Get","description":"Confirmation page. Does NOT mutate state.","operationId":"unsubscribe_get_unsubscribe_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["unsubscribe"],"summary":"Unsubscribe Post","description":"One-click suppression. Idempotent.\n\nSuppresses the TOKEN-ENCODED email at TOKEN-ENCODED scope. Body\nparameters are deliberately ignored — never accept email or scope\nfrom anywhere except the HMAC-signed token. This blocks the\nsuppression-bombing attack where one valid token would otherwise\nlet an attacker suppress arbitrary emails.","operationId":"unsubscribe_post_unsubscribe_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/reengage/claim":{"get":{"tags":["reengage"],"summary":"Claim Reengagement Bonus","description":"Claim 250 bonus credits once, then redirect to the Bavlio app.","operationId":"claim_reengagement_bonus_reengage_claim_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"307":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/newsletter/subscribe":{"post":{"tags":["newsletter"],"summary":"Subscribe","description":"Idempotently subscribe an email without revealing prior list membership.","operationId":"subscribe_newsletter_subscribe_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterSubscribeRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewsletterSubscribeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/newsletter/unsubscribe":{"get":{"tags":["newsletter"],"summary":"Unsubscribe","description":"Unsubscribe by random token and always redirect to a friendly frontend state.","operationId":"unsubscribe_newsletter_unsubscribe_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"307":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/first-look":{"post":{"tags":["public"],"summary":"Create First Look","description":"Validate, deduplicate, record, and start one public first look.","operationId":"create_first_look_api_v1_public_first_look_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirstLookRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirstLookAccepted"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/public/first-look/{look_id}":{"get":{"tags":["public"],"summary":"Get First Look","description":"Return a public first look through an explicit no-contact projection.","operationId":"get_first_look_api_v1_public_first_look__look_id__get","parameters":[{"name":"look_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Look Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FirstLookResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/unsubscribe":{"get":{"tags":["unsubscribe"],"summary":"Unsubscribe Get","description":"Confirmation page. Does NOT mutate state.","operationId":"unsubscribe_get_api_v1_unsubscribe_get","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["unsubscribe"],"summary":"Unsubscribe Post","description":"One-click suppression. Idempotent.\n\nSuppresses the TOKEN-ENCODED email at TOKEN-ENCODED scope. Body\nparameters are deliberately ignored — never accept email or scope\nfrom anywhere except the HMAC-signed token. This blocks the\nsuppression-bombing attack where one valid token would otherwise\nlet an attacker suppress arbitrary emails.","operationId":"unsubscribe_post_api_v1_unsubscribe_post","parameters":[{"name":"token","in":"query","required":false,"schema":{"type":"string","default":"","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"text/html":{"schema":{"type":"string"}}}},"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/orgs/invites":{"post":{"tags":["orgs"],"summary":"Create Invite","description":"Invite a teammate to the caller's org by email (any member can invite).\n\n- Normalizes email to lowercase.\n- 409 if the email is ALREADY a member of this org.\n- If a pending invite already exists for (org, email), returns it idempotently\n  AND re-sends the invite email (re-clicking Invite re-notifies).\n- Generates a secure token, inserts a pending invite (expires now()+7d),\n  returns the invite incl. token + accept_url.\n- Best-effort sends the invitee a transactional email with the accept link via\n  BaviMail (from notifications@bavlio.com), SCHEDULED as a FastAPI background\n  task so it adds zero latency to this request. Email failures NEVER block\n  invite creation. When the transactional creds are unset, the enrichment\n  lookups + scheduling are skipped entirely (no wasted work).","operationId":"create_invite_api_v1_orgs_invites_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteCreateRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/orgs/members":{"get":{"tags":["orgs"],"summary":"List Members","description":"List the caller's org roster: members + pending invites (org-scoped).","operationId":"list_members_api_v1_orgs_members_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgMembersResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/orgs/invites/{invite_id}/revoke":{"post":{"tags":["orgs"],"summary":"Revoke Invite","description":"Revoke a pending invite (org-scoped). 404 if it isn't this org's pending invite.\n\nReturns a TOKEN-FREE response (FIX-2): any member can revoke under V1\nall-permissions, so echoing the accept token would be a token-harvest vector.","operationId":"revoke_invite_api_v1_orgs_invites__invite_id__revoke_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"invite_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invite Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RevocationResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/invites/{token}/accept":{"post":{"tags":["orgs"],"summary":"Accept Invite","description":"Accept an org invite by token (F2 — the membership-transfer transaction).\n\nThe accepter is the AUTHENTICATED user (NOT ``get_org_context``: they are joining\na DIFFERENT org than their current personal one, so resolving their *current* org\nis irrelevant here). The whole accept runs atomically in the ``accept_org_invite``\nRPC (one tx: assert pending+unexpired+email-match+org-less+resource-empty, revoke\nthe invitee's own outgoing pending invites, swap membership under the DEFERRABLE\none-membership constraint, retire the empty personal org, consume the invite). The\nRPC returns a typed status code (never raises for business outcomes); this maps it\nto HTTP. On success the resolver's org cache for the accepter is flushed so the\nnext request scopes to the NEW org (not the now-deleted personal org).","operationId":"accept_invite_api_v1_orgs_invites__token__accept_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"token","in":"path","required":true,"schema":{"type":"string","title":"Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptInviteResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/orgs/compliance":{"get":{"tags":["orgs"],"summary":"Get Org Compliance","description":"Return the caller's org CASL compliance identity + reseller flag (org-scoped).","operationId":"get_org_compliance_api_v1_orgs_compliance_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgComplianceResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["orgs"],"summary":"Update Org Compliance","description":"Update the caller's org CASL sender identity + mailing address (org-scoped).\n\nOnly ``compliance_legal_name`` + ``compliance_mailing_address`` are settable;\nboth are trimmed and a blank value clears the field (stored NULL). The UPDATE\ndict is built from ONLY those two model fields, so ``force_compliance`` can\nnever be set here regardless of what the client sends. Returns the\nround-tripped compliance record (``return=representation`` gives the full row).","operationId":"update_org_compliance_api_v1_orgs_compliance_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgComplianceUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgComplianceResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/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 caller's org (shared resource).","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 (scoped to the caller's org).","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 (org-scoped).","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 (org-scoped ownership).","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/company-context/documents":{"get":{"tags":["company-context"],"summary":"List Company Context Documents","description":"List live documents and chunk counts only for the caller's organization.","operationId":"list_company_context_documents_api_v1_company_context_documents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/api__routers__company_context__CompanyContextDocumentResponse"},"type":"array","title":"Response List Company Context Documents Api V1 Company Context Documents Get"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]},"post":{"tags":["company-context"],"summary":"Ingest Company Context Document","description":"Ingest and index one bounded plain-text document for the caller's org.","operationId":"ingest_company_context_document_api_v1_company_context_documents_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextIngestRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DocumentIngestResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/company-context/documents/upload":{"post":{"tags":["company-context"],"summary":"Upload Company Context Document","description":"Extract and index one bounded supported document upload.","operationId":"upload_company_context_document_api_v1_company_context_documents_upload_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_company_context_document_api_v1_company_context_documents_upload_post"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceDocumentIngestResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/company-context/documents/url":{"post":{"tags":["company-context"],"summary":"Ingest Company Context Url","description":"Fetch and index one public URL through the configured Firecrawl scraper.","operationId":"ingest_company_context_url_api_v1_company_context_documents_url_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UrlIngestRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceDocumentIngestResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/company-context/embeddings/retry":{"post":{"tags":["company-context"],"summary":"Retry Company Context Embeddings","description":"Retry stranded embeddings only for the caller's organization.","operationId":"retry_company_context_embeddings_api_v1_company_context_embeddings_retry_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EmbeddingRetryResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/company-context/facts":{"get":{"tags":["company-context"],"summary":"List Company Context Facts","description":"List active typed facts grouped by type for the caller's organization.","operationId":"list_company_context_facts_api_v1_company_context_facts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"items":{"$ref":"#/components/schemas/CompanyFactResponse"},"type":"array"},"type":"object","title":"Response List Company Context Facts Api V1 Company Context Facts Get"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/company-context/facts/{fact_id}":{"patch":{"tags":["company-context"],"summary":"Patch Company Context Fact","description":"Edit or reject one org-owned fact and record the human reviewer.","operationId":"patch_company_context_fact_api_v1_company_context_facts__fact_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"fact_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Fact Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyFactPatchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyFactResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-context/documents/{document_id}":{"delete":{"tags":["company-context"],"summary":"Delete Company Context Document","description":"Tombstone one org-owned document, then remove its chunks.","operationId":"delete_company_context_document_api_v1_company_context_documents__document_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Document Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/company-context/search":{"post":{"tags":["company-context"],"summary":"Search Company Context","description":"Return cosine-ranked live chunks from only the caller's organization.","operationId":"search_company_context_api_v1_company_context_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyContextSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CompanyContextSearchHitResponse"},"type":"array","title":"Response Search Company Context Api V1 Company Context Search Post"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/catalogue":{"get":{"tags":["connectors"],"summary":"Get Connector Catalogue","description":"Return one honest, searchable connector catalogue with per-org state.","operationId":"get_connector_catalogue_api_v1_connectors_catalogue_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Q"}},{"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/CatalogueResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/connectors/sessions":{"post":{"tags":["connectors"],"summary":"Create Connector Session","description":"Create an org-bound Nango session and build the direct provider OAuth URL.","operationId":"create_connector_session_api_v1_connectors_sessions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSessionRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSessionResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/connections/reconcile":{"post":{"tags":["connectors"],"summary":"Reconcile Connector Connection","description":"Bind only a Nango connection whose server-issued end_user.id matches this org.","operationId":"reconcile_connector_connection_api_v1_connectors_connections_reconcile_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReconcileResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/connections":{"get":{"tags":["connectors"],"summary":"List Connector Connections","description":"List Nango-backed connections and org-scoped ingested document counts.","operationId":"list_connector_connections_api_v1_connectors_connections_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ConnectorConnectionResponse"},"type":"array","title":"Response List Connector Connections Api V1 Connectors Connections Get"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/connections/{connection_id}":{"delete":{"tags":["connectors"],"summary":"Delete Connector Connection","description":"Disconnect externally when possible, then always remove the org-owned local row.","operationId":"delete_connector_connection_api_v1_connectors_connections__connection_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorDisconnectResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/connectors/connections/{connection_id}/sync":{"post":{"tags":["connectors"],"summary":"Sync Connector Connection","description":"Run the provider-specific ingestion for one org-owned connection.","operationId":"sync_connector_connection_api_v1_connectors_connections__connection_id__sync_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"connection_id","in":"path","required":true,"schema":{"type":"string","title":"Connection Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSyncResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/connectors/requests":{"post":{"tags":["connectors"],"summary":"Request Integration","description":"Create one idempotent provider request per org and provider name.","operationId":"request_integration_api_v1_connectors_requests_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationRequestCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IntegrationRequestResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/google-drive/ingest":{"post":{"tags":["connectors"],"summary":"Ingest Google Drive Documents","description":"Ingest explicitly Picker-selected Drive files into this org's context store.","operationId":"ingest_google_drive_documents_api_v1_connectors_google_drive_ingest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleDriveIngestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleDriveIngestResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/github/token":{"put":{"tags":["connectors"],"summary":"Store Github Token","description":"Validate and encryptedly store a caller-supplied GitHub token.","operationId":"store_github_token_api_v1_connectors_github_token_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubTokenRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubTokenStatusResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]},"delete":{"tags":["connectors"],"summary":"Delete Github Token","description":"Remove the caller's stored GitHub token.","operationId":"delete_github_token_api_v1_connectors_github_token_delete","responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/github/status":{"get":{"tags":["connectors"],"summary":"Get Github Status","description":"Report whether the caller has a stored GitHub token.","operationId":"get_github_status_api_v1_connectors_github_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubTokenStatusResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/github/ingest":{"post":{"tags":["connectors"],"summary":"Ingest Github Repositories","description":"Ingest explicitly selected GitHub repositories into this org's context store.","operationId":"ingest_github_repositories_api_v1_connectors_github_ingest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubIngestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GoogleDriveIngestResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/documents":{"get":{"tags":["connectors"],"summary":"List Company Context Documents","description":"List safe metadata for company-context documents owned by the caller's org.","operationId":"list_company_context_documents_api_v1_connectors_documents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/api__routers__connectors__CompanyContextDocumentResponse"},"type":"array","title":"Response List Company Context Documents Api V1 Connectors Documents Get"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/connectors/documents/{document_id}":{"delete":{"tags":["connectors"],"summary":"Delete Company Context Document","description":"Delete one document only when it belongs to the caller's organization.","operationId":"delete_company_context_document_api_v1_connectors_documents__document_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"document_id","in":"path","required":true,"schema":{"type":"string","title":"Document Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/conversations":{"get":{"tags":["linkedin-playground"],"summary":"List Conversations","description":"List conversations for the org's deterministically selected LinkedIn account.","operationId":"list_conversations_api_v1_linkedin_conversations_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque Unipile pagination cursor","title":"Cursor"},"description":"Opaque Unipile pagination cursor"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInReadPageResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/conversations/{chat_id}/messages":{"get":{"tags":["linkedin-playground"],"summary":"List Conversation Messages","description":"List messages only after binding the chat to the org's selected account.","operationId":"list_conversation_messages_api_v1_linkedin_conversations__chat_id__messages_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":512,"title":"Chat Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":30,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque Unipile pagination cursor","title":"Cursor"},"description":"Opaque Unipile pagination cursor"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkedInReadPageResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin/conversations/{chat_id}/reply":{"post":{"tags":["linkedin-playground"],"summary":"Reply To Conversation","description":"Reply into an existing LinkedIn chat from the inbox.\n\nThe other LinkedIn write endpoints on this router carry\n``_require_non_production`` because they were built as a playground: they\ntake an ``account_id`` from the client and can open a conversation with\nanyone. This one is deliberately production-safe and narrower on every axis\nthat matters:\n\n  * the sending account is resolved SERVER-SIDE from the caller's org, so a\n    client cannot nominate someone else's connected account;\n  * the chat must already be bound to that org and account in\n    ``LinkedInMessageStore`` — an unbound or foreign ``chat_id`` is a 404,\n    not a send, so a guessed id cannot reply into another org's thread;\n  * it can only continue a conversation that already exists. There is no\n    path here to start one, which is what makes it safe without the\n    daily/hourly connection caps the playground endpoints need.\n\nIt mirrors ``list_conversation_messages`` above — same org dependency, same\naccount resolution, same store binding — because reading and replying to a\nthread should be authorised identically.","operationId":"reply_to_conversation_api_v1_linkedin_conversations__chat_id__reply_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"chat_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":512,"title":"Chat Id"}},{"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/LinkedInConversationReplyRequest"}}}},"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/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/inbox":{"get":{"tags":["inbox"],"summary":"List Inbox","description":"Return one stable page from the last 30 days, newest first.\n\nResume state advances each source only for items emitted. Each retry skips\nidentities at or before the source's last-emitted key, so an upstream offset\nshift cannot duplicate rows. A provider failure returns a partial page and\nnames that source.","operationId":"list_inbox_api_v1_inbox_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque versioned merged-source cursor","title":"Cursor"},"description":"Opaque versioned merged-source cursor"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"channel","in":"query","required":false,"schema":{"enum":["all","email","linkedin"],"type":"string","default":"all","title":"Channel"}},{"name":"scope","in":"query","required":false,"schema":{"enum":["campaigns","all"],"type":"string","description":"Show only campaign-matched threads by default, or all inbox threads.","default":"campaigns","title":"Scope"},"description":"Show only campaign-matched threads by default, or all inbox threads."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboxListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/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"}},{"name":"provider_account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider 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"}},{"name":"provider_account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider 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/media/":{"post":{"tags":["media"],"summary":"Upload Media","description":"Upload an image to the caller's org media library (quota-enforced).","operationId":"upload_media_api_v1_media__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_media_api_v1_media__post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaAssetResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["media"],"summary":"List Media","description":"List the caller-org's media assets (keyset paginated, signed in parallel).\n\nTenant-scoped: returns ONLY the caller's org assets (org-shared). Each item\ncarries a short-lived signed URL; ``storage_path`` is NEVER returned.","operationId":"list_media_api_v1_media__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":24,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque keyset pagination cursor","title":"Cursor"},"description":"Opaque keyset pagination cursor"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaListResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/media/quota":{"get":{"tags":["media"],"summary":"Get Media Quota","description":"Return the caller-org's media usage for the dashboard quota indicator.\n\nRegistered BEFORE ``/{asset_id}`` so the literal ``quota`` path is not\ncaptured as a UUID path param.","operationId":"get_media_quota_api_v1_media_quota_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaQuotaResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/media/batch":{"post":{"tags":["media"],"summary":"Get Media Batch","description":"Resolve one page's media with one tenant-scoped metadata query.","operationId":"get_media_batch_api_v1_media_batch_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaBatchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaBatchResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/media/{asset_id}":{"get":{"tags":["media"],"summary":"Get Media","description":"Fetch a caller-scoped asset's metadata + a short-lived signed URL.\n\nOwnership-gate-before-sign: a non-owned asset is a 404 and is NEVER signed.","operationId":"get_media_api_v1_media__asset_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaAssetWithUrlResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["media"],"summary":"Delete Media","description":"Delete a caller-org asset's blob + row (idempotent, IDOR-safe).\n\nIDOR guard: a non-owned / already-gone asset is a 404 (NOT a silent 204).\nThe blob is deleted first (already-gone is non-fatal), then the row is\ndeleted org-scoped (org filter carried on the WRITE — TOCTOU).","operationId":"delete_media_api_v1_media__asset_id__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"asset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Asset Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/dashboard/snapshot":{"get":{"tags":["content_dashboard"],"summary":"Get Content Dashboard Snapshot","operationId":"get_content_dashboard_snapshot_api_v1_content_dashboard_snapshot_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDashboardSnapshotResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/inbox/":{"get":{"tags":["content_inbox"],"summary":"List Inbox","description":"List the caller-org's drafts (keyset paginated, org-scoped).\n\nTenant-scoped: returns ONLY the caller-org's drafts. A malformed cursor is a 400.","operationId":"list_inbox_api_v1_content_inbox__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["pending","approved","denied","snoozed","scheduled"],"type":"string"},{"type":"null"}],"description":"Filter by draft status","title":"Status"},"description":"Filter by draft status"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":24,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque keyset pagination cursor","title":"Cursor"},"description":"Opaque keyset pagination cursor"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftListResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["content_inbox"],"summary":"Create Inbox Draft","description":"Create one customer-authored draft in the current Content queue.\n\nThis is deliberately a draft creation path, not a second posting transport. The\nexisting schedule/Post now actions retain the public-publish confirmation, caps,\ntenant isolation, and dispatcher behavior. Manual drafts do not invoke an LLM or\nconsume the weekly generation allowance.","operationId":"create_inbox_draft_api_v1_content_inbox__post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftCreateRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/inbox/generate":{"post":{"tags":["content_inbox"],"summary":"Generate Inbox Draft","description":"Generate and persist one Content Inbox draft for review.\n\nFree surface (V3.2a re-gate): reachable by any org with the product flag on, NOT\ngated by the $20/mo add-on entitlement. Free-tier LLM spend is bounded by the\nper-(org, user) weekly generation cap (V3.2b, ``FREE_TIER_WEEKLY_GENERATION_CAP``\ngenerations per ET calendar week), checked HERE as a PRECHECK before the billable\nGemini call so an over-cap free user's request 402s before any LLM spend happens\n(``ContentDraftService.create_content_draft`` re-checks it as a backstop only).\nPaid/comped orgs are uncapped.","operationId":"generate_inbox_draft_api_v1_content_inbox_generate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftGenerateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/inbox/{draft_id}":{"get":{"tags":["content_inbox"],"summary":"Get Inbox Draft","description":"Fetch one caller-org draft. A non-owned / deleted draft is a 404 (IDOR-safe).","operationId":"get_inbox_draft_api_v1_content_inbox__draft_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Draft Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["content_inbox"],"summary":"Edit Inbox Draft","description":"Edit a draft's per-platform bodies / attached media (org-scoped write).\n\nOnly the explicitly-set fields are updated; an explicit ``media_asset_id: null``\ndetaches the image. An attached asset is ownership-gated (cross-org -> 404).","operationId":"edit_inbox_draft_api_v1_content_inbox__draft_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Draft Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftEditRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/inbox/{draft_id}/approve":{"post":{"tags":["content_inbox"],"summary":"Approve Inbox Draft","description":"Approve a draft (pending -> approved) and capture accepted voice samples.","operationId":"approve_inbox_draft_api_v1_content_inbox__draft_id__approve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Draft Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/inbox/{draft_id}/deny":{"post":{"tags":["content_inbox"],"summary":"Deny Inbox Draft","description":"Deny a draft (pending -> denied). 404 if not owned, 409 if not pending.","operationId":"deny_inbox_draft_api_v1_content_inbox__draft_id__deny_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Draft Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/inbox/{draft_id}/snooze":{"post":{"tags":["content_inbox"],"summary":"Snooze Inbox Draft","description":"Snooze a draft (pending -> snoozed). 404 if not owned, 409 if not pending.\n\nv1 snooze simply moves the draft out of the pending tab (no future-surface time).\nA scheduled re-surface (``snooze_until``) is a follow-up; the endpoint is a plain\naction like deny so the UI does not send a body.","operationId":"snooze_inbox_draft_api_v1_content_inbox__draft_id__snooze_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Draft Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/inbox/{draft_id}/restore":{"post":{"tags":["content_inbox"],"summary":"Restore Inbox Draft","description":"Restore an owned denied draft to pending for editing and rescheduling.","operationId":"restore_inbox_draft_api_v1_content_inbox__draft_id__restore_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Draft Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/inbox/{draft_id}/schedule":{"post":{"tags":["content_inbox"],"summary":"Schedule Inbox Draft","description":"Schedule a draft (pending|approved -> scheduled) AND enroll it into the dispatch queue.\n\nThe future-instant + DST-gap checks run SERVER-SIDE (a wall-clock+timezone is\nresolved via ZoneInfo, spring-forward gaps rejected); the per-org daily-schedule cap\nis enforced atomically inside the seam RPC. Scheduling now ATOMICALLY upserts the\ncontent_scheduled_posts dispatch row (E4.1b), so the dispatcher actually publishes the\npost. 404 if not owned, 409 if not pending/approved, 422 on a past/DST-gap time, 429 when the\ndaily cap is hit.","operationId":"schedule_inbox_draft_api_v1_content_inbox__draft_id__schedule_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"draft_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Draft Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftScheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentDraftResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/scheduled-posts/":{"get":{"tags":["content_scheduled_posts"],"summary":"List Scheduled Posts","description":"List the caller-org's scheduled posts in [from, to) (keyset paginated, org-scoped).\n\nTenant-scoped: returns ONLY the caller-org's posts. A malformed cursor is a 400.","operationId":"list_scheduled_posts_api_v1_content_scheduled_posts__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Range start (inclusive)","title":"From"},"description":"Range start (inclusive)"},{"name":"to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Range end (exclusive)","title":"To"},"description":"Range end (exclusive)"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Opaque keyset pagination cursor","title":"Cursor"},"description":"Opaque keyset pagination cursor"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledPostListResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/scheduled-posts/{post_id}":{"get":{"tags":["content_scheduled_posts"],"summary":"Get Scheduled Post","description":"Fetch one caller-org post. A non-owned / deleted post is a 404 (IDOR-safe).","operationId":"get_scheduled_post_api_v1_content_scheduled_posts__post_id__get","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":{"$ref":"#/components/schemas/ScheduledPostResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["content_scheduled_posts"],"summary":"Reschedule Scheduled Post","description":"Reschedule a post (calendar drag-drop). Re-validates future-time + DST-gap.\n\n409 if the post already started dispatching/published; 404 if not owned; 422 on a\npast/DST-gap time.","operationId":"reschedule_scheduled_post_api_v1_content_scheduled_posts__post_id__patch","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescheduleRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledPostResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["content_scheduled_posts"],"summary":"Cancel Scheduled Post","description":"Cancel a not-yet-dispatching post (status -> cancelled).\n\n409 if the post is publishing or already published (use resolve); 404 if not owned.","operationId":"cancel_scheduled_post_api_v1_content_scheduled_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":{"$ref":"#/components/schemas/ScheduledPostResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/scheduled-posts/{post_id}/resolve":{"post":{"tags":["content_scheduled_posts"],"summary":"Resolve Scheduled Post Leg","description":"Resolve a leg stuck in 'unknown' (retry re-arms it; cancel marks it skipped).\n\nNEVER-DOUBLE-POST: the resolve is CAS-safe and can never re-publish a leg that already\npublished. 404 if not owned; 409 if the leg is not targeted / not resolvable.","operationId":"resolve_scheduled_post_leg_api_v1_content_scheduled_posts__post_id__resolve_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"post_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Post Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveLegRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScheduledPostResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/signals/sources":{"get":{"tags":["content_signals"],"summary":"List Signal Sources","operationId":"list_signal_sources_api_v1_content_signals_sources_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceListResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/signals/sources/posthog":{"put":{"tags":["content_signals"],"summary":"Upsert Posthog Source","operationId":"upsert_posthog_source_api_v1_content_signals_sources_posthog_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostHogSourceUpsertRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceStatus"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/signals/sources/github":{"put":{"tags":["content_signals"],"summary":"Upsert Github Source","operationId":"upsert_github_source_api_v1_content_signals_sources_github_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubSourceUpsertRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SourceStatus"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/signals/sources/github/install-url":{"get":{"tags":["content_signals"],"summary":"Github Install Url","description":"Return a Bavlio GitHub App install URL for selected source-card repos.\n\nThe user starts this with an authenticated fetch; GitHub returns to the\nno-session callback with only the signed state. The state carries org/user and\nselected repositories, so the callback can store the org-scoped installation\nwithout asking the user to copy/paste an installation id.","operationId":"github_install_url_api_v1_content_signals_sources_github_install_url_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"repositories","in":"query","required":true,"schema":{"type":"array","items":{"type":"string"},"minItems":1,"title":"Repositories"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GitHubInstallUrlResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/signals/sources/github/callback":{"get":{"tags":["content_signals"],"summary":"Github Install Callback","description":"Store a completed GitHub App installation and return to Connections.\n\nGitHub redirects here as a top-level browser navigation, so there is no bearer\nauth. Trust is the HMAC state minted during the authenticated start step.","operationId":"github_install_callback_api_v1_content_signals_sources_github_callback_get","parameters":[{"name":"installation_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Installation Id"}},{"name":"setup_action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Setup Action"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}}],"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/content/signals/sources/{source}":{"delete":{"tags":["content_signals"],"summary":"Delete Signal Source","operationId":"delete_signal_source_api_v1_content_signals_sources__source__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"source","in":"path","required":true,"schema":{"enum":["posthog","github"],"type":"string","title":"Source"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Delete Signal Source Api V1 Content Signals Sources  Source  Delete"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/signals":{"get":{"tags":["content_signals"],"summary":"List Recent Signals","operationId":"list_recent_signals_api_v1_content_signals_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":14,"title":"Days"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalListResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/signals/suggestions":{"get":{"tags":["content_signals"],"summary":"List Signal Suggestions","operationId":"list_signal_suggestions_api_v1_content_signals_suggestions_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":14,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":12,"minimum":1,"default":12,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SignalSuggestionListResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/signals/refresh/posthog":{"post":{"tags":["content_signals"],"summary":"Refresh Posthog Signals","operationId":"refresh_posthog_signals_api_v1_content_signals_refresh_posthog_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":14,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/signals/refresh/github":{"post":{"tags":["content_signals"],"summary":"Refresh Github Signals","operationId":"refresh_github_signals_api_v1_content_signals_refresh_github_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"days","in":"query","required":false,"schema":{"type":"integer","maximum":30,"minimum":1,"default":14,"title":"Days"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/voice-config":{"get":{"tags":["content"],"summary":"Get Voice Config","description":"Return the caller-org's voice config (positioning pre-filled from the sender\nprofile when no config exists yet; ``updated_at`` null = unsaved pre-fill).","operationId":"get_voice_config_api_v1_content_voice_config_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceConfigResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["content"],"summary":"Update Voice Config","description":"Create or update the caller-org's voice config (idempotent upsert on org).","operationId":"update_voice_config_api_v1_content_voice_config_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceConfigUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceConfigResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/voice-config/auto-derive":{"post":{"tags":["content"],"summary":"Auto Derive Voice Config","description":"Auto-derive an EDITABLE PERSONAL voice-config draft for the AUTHENTICATED user.\n\nDerives the personal voice for the caller — ``user_id`` is taken from the\nauthenticated ``OrgContext`` (``org_context.user_id``), NEVER a client-supplied\nparam, so a caller can only ever derive their OWN voice (anti-cross-user). The\nLinkedIn arm consumes the person's persisted ``person_identities`` enrichment (no\nscrape); the X arm reads the connected timeline; both feed an LLM voice analysis\n(the repo's standard Gemini path) whose contributions are merged into the personal voice (tone/style/topics/\ndo/don't + the read posts as editable sample snippets), with positioning pre-filled\nfrom the sender profile. The draft is NOT saved -- the UI lets the user review/edit\nand persist via PUT. ``linkedin_arm_status`` (ok / absent / error) and\n``x_arm_status`` (derived / no_connection / needs_reauth / empty_timeline /\nunavailable) report each source independently.","operationId":"auto_derive_voice_config_api_v1_content_voice_config_auto_derive_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutoDeriveVoiceResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/person-voice":{"get":{"tags":["content"],"summary":"Get Person Voice","description":"Return the AUTHENTICATED user's persisted person voice (or an empty/unsaved shape\nwhen no row exists yet -- ``updated_at`` null signals the FE to auto-derive-and-save).\n\nScoped to ``org_context.org_id`` + ``org_context.user_id`` (the authenticated actor,\nnever a client param).","operationId":"get_person_voice_api_v1_content_person_voice_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonVoiceResponse"}}}},"401":{"description":"Unauthorized"}},"security":[{"HTTPBearer":[]}]},"put":{"tags":["content"],"summary":"Save Person Voice Edits","description":"Persist a USER-EDITED person voice and stamp ``manually_edited_at`` so future\nauto-derives no-clobber it.\n\nOnly the editable voice fields (``PersonVoiceUpdateRequest``: tone/style/topics/do/\ndont/sample_snippets) are accepted; the client can NOT write arm-status / provenance /\ninternal columns (undeclared on the request model AND not in the service voice\nallowlist). ``manually_edited_at`` is stamped server-side via the trusted provenance\nchannel. Scoped to the authenticated actor (``org_context.user_id``).","operationId":"save_person_voice_edits_api_v1_content_person_voice_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonVoiceUpdateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonVoiceResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/person-voice/auto-derive":{"post":{"tags":["content"],"summary":"Auto Derive And Save Person Voice","description":"Auto-build (or re-derive) AND PERSIST the authenticated user's person voice.\n\nThe time-to-value auto-build the FE Voice page calls when no voice exists. Flow:\n\n1. NO-CLOBBER pre-check: if a row already exists with ``manually_edited_at`` set (the\n   user edited it), a NORMAL call returns the EXISTING row untouched with\n   ``skipped_user_edited=true``. ``?force=true`` overrides and re-derives.\n2. Derive the draft via ``ContentVoiceAutoDeriveService`` (V2.1a, READ-ONLY +\n   fail-soft: never raises; each arm carries its own rich status).\n3. MAP the rich arm statuses to the migration-249 CHECK vocabulary before persisting:\n   LinkedIn is already ok/absent/error (pass-through); X collapses derived->ok,\n   {no_connection,empty_timeline,unavailable}->absent, needs_reauth->error. The\n   ORIGINAL rich reason is preserved in ``*_arm_detail`` so the FE keeps the nuance.\n4. Upsert the voice fields + MAPPED arm statuses + ``derived_at=now()`` + a bumped\n   ``derivation_version``. ``manually_edited_at`` is NOT set (a derive is not a user\n   edit). FAIL-SOFT: the derive never raises; an upsert failure surfaces a clear 502\n   (from the service) rather than a cryptic 500.\n\nThe response body echoes the RICH X status (the FE keeps the nuance) while the column\nstores the mapped CHECK value; ``voice`` carries the persisted (mapped) row.\n\n``user_id`` is the authenticated actor (``org_context.user_id``), never a client\nparam -- a caller can only ever derive/persist their OWN voice.","operationId":"auto_derive_and_save_person_voice_api_v1_content_person_voice_auto_derive_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Re-derive and overwrite even a manually-edited voice. Default false no-clobbers a user-edited voice (returns it untouched).","default":false,"title":"Force"},"description":"Re-derive and overwrite even a manually-edited voice. Default false no-clobbers a user-edited voice (returns it untouched)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonVoiceDeriveResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/addon/checkout":{"post":{"tags":["content_addon_checkout"],"summary":"Start a $20/mo Content add-on checkout via Autumn billing.attach (CAS lock)","description":"Authenticated, org-scoped Content add-on checkout gated by `BAVLIO_CONTENT_PRODUCT_ENABLED` (404 when off). Rate-limited 20/credential/hour AND 60/IP/hour. Returns a hosted Stripe `checkout_url` (status=open) or status=completed on an instant attach / comp / already-entitled org. Idempotent + double-charge-safe via the E5.1 per-org CAS lock. Success/cancel URLs are server-controlled.","operationId":"create_content_addon_checkout_api_v1_content_addon_checkout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Create Content Addon Checkout Api V1 Content Addon Checkout Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/oauth/{provider}/authorize":{"get":{"tags":["content-oauth"],"summary":"Authorize","description":"Start the OAuth connect flow: returns the provider authorize URL as JSON.\n\nThe FE fetches this WITH auth, then navigates the browser to the returned\nprovider URL. A 302 here is unreachable via a top-level browser nav because this\nendpoint is auth-gated: the FE initiates connect with ``window.location.assign``,\nwhich carries no Authorization header, so a redirecting endpoint would 401 before\nthe browser ever saw the Location. This is the same browser-nav-vs-Bearer\nconstraint as the callback, but inverted: the callback has no auth so it must\nredirect, while authorize NEEDS auth (to build the signed org-bound ``state``) so\nit must return data the authed fetch can read and then navigate to itself.","operationId":"authorize_api_v1_content_oauth__provider__authorize_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","description":"linkedin | x | gmail | outlook","title":"Provider"},"description":"linkedin | x | gmail | outlook"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/oauth/{provider}/callback":{"get":{"tags":["content-oauth"],"summary":"Callback","description":"Handle the provider callback: exchange + store, then 302 to the dashboard.\n\nNO ``get_org_context`` dependency: the provider sends the user's browser a\nTOP-LEVEL 302 to this URL, which carries no Authorization header, so a Bearer\ndependency would 401 before the body runs and the connect could never complete\n(matches the Google OAuth callback precedent in api/routers/google_auth.py).\nThe org/identity is re-anchored to the HMAC-signed ``state`` + the one-time-use\npending-flow row inside ``handle_callback`` (not the request session).","operationId":"callback_api_v1_content_oauth__provider__callback_get","parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","description":"linkedin | x | gmail","title":"Provider"},"description":"linkedin | x | gmail"},{"name":"code","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"}},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"}},{"name":"error","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/oauth/status":{"get":{"tags":["content-oauth"],"summary":"Status","description":"Per-provider connection status for the org (drives the E1.3 connect UI).\n\nReads the metadata columns ONLY (never the encrypted token bytea). org-scoped.","operationId":"status_api_v1_content_oauth_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Status Api V1 Content Oauth Status Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/oauth/mailbox/test-send":{"post":{"tags":["content-oauth"],"summary":"Mailbox Test Send","description":"Send a send-to-self test email through the org's connected mailbox.\n\nProves a connected Gmail/Outlook mailbox can actually send (and exercises the\n``gmail.send`` scope) by delivering a tiny email to the connected account's\nOWN address. Org-scoped: the mailbox is resolved from the caller's org only, so\norg A can never test-send org B's mailbox. Sends directly through the existing\nprovider transport (no internal-send endpoint / worker flag needed).","operationId":"mailbox_test_send_api_v1_content_oauth_mailbox_test_send_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxTestSendRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MailboxTestSendResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/content/oauth/{provider}":{"delete":{"tags":["content-oauth"],"summary":"Disconnect","description":"Disconnect one provider account; omission is allowed when exactly one exists.","operationId":"disconnect_api_v1_content_oauth__provider__delete","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","description":"linkedin | x | gmail | outlook","title":"Provider"},"description":"linkedin | x | gmail | outlook"},{"name":"account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Account Id"}},{"name":"provider_account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Account Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Disconnect Api V1 Content Oauth  Provider  Delete"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/content/connections/{provider}/default":{"post":{"tags":["content-oauth"],"summary":"Set Default Connection","description":"Atomically change the org default account for one provider.","operationId":"set_default_connection_api_v1_content_connections__provider__default_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","description":"linkedin | x | gmail | outlook","title":"Provider"},"description":"linkedin | x | gmail | outlook"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DefaultConnectionRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Set Default Connection Api V1 Content Connections  Provider  Default Post"}}}},"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/webhooks/supabase/user-created":{"post":{"tags":["webhooks"],"summary":"Handle Supabase User Created","description":"Provision a new Supabase signup into Autumn. Fail-open; never blocks signup.","operationId":"handle_supabase_user_created_api_v1_webhooks_supabase_user_created_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","security":[{"HTTPBearer":[]}],"parameters":[{"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":{"$ref":"#/components/schemas/ConversationListResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["agent"],"summary":"Create Conversation","description":"Create a new conversation.","operationId":"create_conversation_api_v1_agent_conversations_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateConversationRequest"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationSummary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/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"}}}}}}},"/v1/voice/session":{"post":{"tags":["voice-agent"],"summary":"Create Voice Session","description":"Mint an xAI ephemeral token and return the authenticated user's tool schemas.","operationId":"create_voice_session_v1_voice_session_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Create Voice Session V1 Voice Session Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/voice/tool-call":{"post":{"tags":["voice-agent"],"summary":"Execute Voice Tool","description":"Execute one allowlisted Bavi tool with authenticated server context.","operationId":"execute_voice_tool_v1_voice_tool_call_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceToolCallRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":{"type":"string"},"type":"object","title":"Response Execute Voice Tool V1 Voice Tool Call Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/v1/voice/test":{"get":{"tags":["voice-agent"],"summary":"Voice Test Page","description":"Serve the dependency-free browser tester.","operationId":"voice_test_page_v1_voice_test_get","responses":{"200":{"description":"Successful Response"}}}},"/api/v1/billing/portal":{"post":{"tags":["billing"],"summary":"Open the authenticated user's Autumn billing portal","operationId":"create_billing_portal_api_v1_billing_portal_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Create Billing Portal Api V1 Billing Portal Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/billing/checkout":{"post":{"tags":["billing"],"summary":"Start a Pro checkout via Autumn billing.attach with CAS lock","description":"Authenticated Pro checkout gated by `BAVLIO_PRO_CHECKOUT_ENABLED` (404 when off). Rate-limited 20/credential/hour AND 60/IP/hour. Returns a hosted Stripe `checkout_url` (status=open) or status=completed on an instant attach. Success/cancel URLs are server-controlled.","operationId":"create_checkout_api_v1_billing_checkout_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Create Checkout Api V1 Billing Checkout Post"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/billing/pricing-catalog":{"get":{"tags":["billing"],"summary":"Public Bavlio pricing catalog (static) + checkout_enabled flag","description":"Public pricing catalog sourced statically from the in-code Autumn catalog (PRO_STOP_VALUES + canonical plan ids). Carries `checkout_enabled` = the BAVLIO_PRO_CHECKOUT_ENABLED flag state so the frontend knows whether to route the Pro slider through /billing/checkout.","operationId":"get_pricing_catalog_api_v1_billing_pricing_catalog_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Get Pricing Catalog Api V1 Billing Pricing Catalog Get"}}}}}}},"/api/v1/email-finder/find-live":{"post":{"tags":["email-finder"],"summary":"Find Live","description":"Find one email inline. Idempotency-Key (8-255 ASCII chars) is required.","operationId":"find_live_api_v1_email_finder_find_live_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LiveFindRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Find Live Api V1 Email Finder Find Live Post"}}}},"400":{"description":"Missing Idempotency-Key (MISSING_IDEMPOTENCY_KEY), or an invalid 8-255 printable ASCII key/request body"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/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/verify-bulk":{"post":{"tags":["email-finder"],"summary":"Verify Bulk","description":"Canonical raw/list bulk verification.\n\nA single email verify is represented as a one-row bulk parent. The parent\nstays `job_type='bulk'` with `input_data.operation='verify_bulk'`; children\nremain normal `job_type='verify'` rows consumed by `ef_verify_email`.","operationId":"verify_bulk_api_v1_email_finder_verify_bulk_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkVerifyRequest"}}}},"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/verify-dataset":{"post":{"tags":["email-finder"],"summary":"Verify Dataset","description":"SMTP-verify every existing email in a dataset, writing each verdict to the\nSERVER-ONLY ev_* columns (migration 250) so the at-send gate can trust it.\n\nEligible = rows with an exact-key email AND a non-null generation token\n(last_session_id) — both required by the RPC writeback, so we never charge for\na guaranteed no-op. Charges 1 credit/email at fan-out (mirrors single /verify);\neach row task refunds a non-definitive (catch_all/unknown) verdict. Requires an\nIdempotency-Key (a replay returns the existing run, no re-charge). Child jobs\nare grouped by a run_id in input_data. Poll GET /verify-dataset/{job_id}.","operationId":"verify_dataset_api_v1_email_finder_verify_dataset_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyDatasetRequest"}}}},"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/verify-dataset/{job_id}":{"get":{"tags":["email-finder"],"summary":"Verify Dataset Status","description":"Aggregate a verify-dataset run's child verdicts (first-class counts).","operationId":"verify_dataset_status_api_v1_email_finder_verify_dataset__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","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/search-runs":{"get":{"tags":["email-finder"],"summary":"List Email Search Runs","description":"List current user's email-finder history for the Find Leads UI.","operationId":"list_email_search_runs_api_v1_email_finder_search_runs_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":20,"title":"Limit"}}],"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/runs/{run_id}":{"get":{"tags":["email-finder"],"summary":"Get Email Search Run Status","description":"Poll run-centric async email-search status without touching EF DB.","operationId":"get_email_search_run_status_api_v1_email_finder_runs__run_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run 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 all use the same shape: `name` with `domain` or `company`, or\nledger-only `linkedin_url`. Company-only rows are resolved via\n_resolve_company_domain before charging; unresolved rows are skipped with\nno charge and reported in `skipped_unresolved`.\n\nPR3b: variable-cost reservation. Reserves the MAX possible\n`email_finder_credits` (= len(rows)) up front via atomic check+sendEvent,\nthen refunds unused via negative track. Per AC3 CB22 cost-shape table.\n\nThin wrapper over `execute_bulk_search` (Stream C / PR-D commit 1). The\nBavi agent tool `find_emails_for_dataset` invokes the service directly,\nbypassing this HTTP layer.","operationId":"bulk_search_api_v1_email_finder_bulk_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkSearchRequest"}}}},"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/business-contact-enrichment":{"post":{"tags":["email-finder"],"summary":"Start Business Contact Enrichment","description":"Start business contact enrichment for exact eligible dataset rows.","operationId":"start_business_contact_enrichment_api_v1_email_finder_business_contact_enrichment_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessContactEnrichmentRequest"}}}},"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/contact-enrichment-from-dataset":{"post":{"tags":["email-finder"],"summary":"Start Business Contact Enrichment","description":"Start business contact enrichment for exact eligible dataset rows.","operationId":"start_business_contact_enrichment_api_v1_email_finder_contact_enrichment_from_dataset_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessContactEnrichmentRequest"}}}},"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/business-contact-enrichment/{job_id}/status":{"get":{"tags":["email-finder"],"summary":"Business Contact Enrichment Status","operationId":"business_contact_enrichment_status_api_v1_email_finder_business_contact_enrichment__job_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","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/contact-enrichment/{job_id}/status":{"get":{"tags":["email-finder"],"summary":"Business Contact Enrichment Status","operationId":"business_contact_enrichment_status_api_v1_email_finder_contact_enrichment__job_id__status_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","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/datasets/{dataset_id}/plan":{"post":{"tags":["email-finder"],"summary":"Dataset Method Plan","description":"Return a free, read-only email-method plan for an org-owned dataset.","operationId":"dataset_method_plan_api_v1_email_finder_datasets__dataset_id__plan_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/DatasetMethodPlanRequest"}}}},"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/datasets/{dataset_id}/execute":{"post":{"tags":["email-finder"],"summary":"Execute Dataset Method Plan","description":"Re-plan an org-owned dataset and execute every chargeable method bucket.","operationId":"execute_dataset_method_plan_api_v1_email_finder_datasets__dataset_id__execute_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}},{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetMethodExecuteRequest"}}}},"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/dataset-contact-preview":{"post":{"tags":["email-finder"],"summary":"Dataset Contact Preview","description":"Preview per-row contact routes for a dataset. Does not move credits.","operationId":"dataset_contact_preview_api_v1_email_finder_dataset_contact_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DatasetContactPreviewRequest"}}},"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-from-dataset":{"post":{"tags":["email-finder"],"summary":"Bulk From Dataset","description":"Bulk find on an existing dataset (PR-E1 of 2026-05-22).\n\nSame money semantics as `/bulk` but the rows come from a server-resolved\ndataset (via shared eligibility predicate) instead of the client's request\nbody. The frontend's Existing Datasets picker hits this route after a\nuser confirms the spend in the modal.\n\nSee `docs/plans/2026-05-22-bulk-find-email-existing-datasets-picker-plan.md`\n\"Backend route shape\" section for phase-by-phase ordering documentation,\ncrash-safety properties, and failure-mode mapping.\n\nHTTP semantics:\n- 200 → job enqueued (or replayed from idempotency cache)\n- 400 → missing `Idempotency-Key` header\n- 402 → insufficient credits (with `required` + `available` in detail)\n- 404 → dataset not found OR not owned by user\n- 409 → `REQUEST_IN_FLIGHT` | `IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY` |\n        `reconfirm_spend` (live `actual_estimated_credits` returned)\n- 422 → Pydantic validation OR `INELIGIBLE_SOURCE_TYPE` | `NO_ELIGIBLE_ROWS`\n        | `DATASET_FETCH_FAILED`","operationId":"bulk_from_dataset_api_v1_email_finder_bulk_from_dataset_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkFromDatasetRequest"}}}},"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/{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","format":"uuid","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/email-finder/verify-bulk/{job_id}":{"get":{"tags":["email-finder"],"summary":"Get Verify Bulk Status Alias","description":"Explicit verify-bulk polling alias for frontend clarity.","operationId":"get_verify_bulk_status_alias_api_v1_email_finder_verify_bulk__job_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","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/lead-finder/sessions/{session_id}":{"get":{"tags":["lead-finder"],"summary":"Get Session Status","description":"Rich lead-finder session status (additive; F-15 FE consumer is W4-C).\n\nExtends the bare-counts ``/batch/{id}/status`` with a terminal-aware status\nenum (processing/completed/partial/failed — fixing the infinite spinner on a\nfailed/stalled session), single-stage progress, a truncated sample of\nfailed-row reason codes (machine codes only, NO internals), and credit\nactuals ({reserved, charged, refunded}) that pair with the W3-A3 completion\nsettlement. Ownership-guarded (404-not-403, no existence oracle). Read-only.","operationId":"get_session_status_api_v1_lead_finder_sessions__session_id__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/linkedin-finder/datasets/{dataset_id}/company-role":{"post":{"tags":["linkedin-finder"],"summary":"Start Company Role Enrichment","description":"Start org-scoped company-and-role LinkedIn enrichment on ``bavlio:main``.","operationId":"start_company_role_enrichment_api_v1_linkedin_finder_datasets__dataset_id__company_role_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dataset Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/CompanyRoleEnrichmentRequest"},{"type":"null"}],"title":"Request"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Start Company Role Enrichment Api V1 Linkedin Finder Datasets  Dataset Id  Company Role Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/linkedin-finder/sessions/{session_id}":{"get":{"tags":["linkedin-finder"],"summary":"Get Company Role Enrichment Status","description":"Return the sibling enrichment status shape for an owned job.","operationId":"get_company_role_enrichment_status_api_v1_linkedin_finder_sessions__session_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Company Role Enrichment Status Api V1 Linkedin Finder Sessions  Session Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/lead-finding/parse-request":{"post":{"tags":["lead_finding"],"summary":"Parse Request","operationId":"parse_request_api_v1_lead_finding_parse_request_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseLeadRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadFilterEnvelope"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/lead-finding/find-leads":{"post":{"tags":["lead_finding"],"summary":"Find Leads","operationId":"find_leads_api_v1_lead_finding_find_leads_post","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ImplicitFindLeadsRequest"},{"$ref":"#/components/schemas/ExplicitFindLeadsRequest"}],"title":"Request"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ClarificationRequiredResponse"},{"$ref":"#/components/schemas/FindLeadsCompletedResponse"},{"$ref":"#/components/schemas/FindLeadsInProgressResponse"}],"title":"Response Find Leads Api V1 Lead Finding Find Leads Post"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/lead-finding/find-leads/{dataset_id}/continue":{"post":{"tags":["lead_finding"],"summary":"Continue Find Leads","operationId":"continue_find_leads_api_v1_lead_finding_find_leads__dataset_id__continue_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/ContinueLeadSearchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PreviewLeadSearchResponse"},{"$ref":"#/components/schemas/ContinueLeadSearchExhaustedResponse"},{"$ref":"#/components/schemas/FindLeadsCompletedResponse"},{"$ref":"#/components/schemas/FindLeadsInProgressResponse"}],"title":"Response Continue Find Leads Api V1 Lead Finding Find Leads  Dataset Id  Continue Post"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/lead-finding/enrichment-quote":{"get":{"tags":["lead_finding"],"summary":"Get Enrichment Quote","description":"Return the maximum quote plus all lower-cost cohort options.","operationId":"get_enrichment_quote_api_v1_lead_finding_enrichment_quote_get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"dataset_id","in":"query","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 Get Enrichment Quote Api V1 Lead Finding Enrichment Quote Get"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["lead_finding"],"summary":"Scope Enrichment Quote","description":"Recalculate the quote for a caller-selected subset without reserving credits.","operationId":"scope_enrichment_quote_api_v1_lead_finding_enrichment_quote_post","security":[{"HTTPBearer":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentQuoteRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Scope Enrichment Quote Api V1 Lead Finding Enrichment Quote Post"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/lead-search/parse":{"post":{"tags":["lead_search"],"summary":"Parse Lead Search","operationId":"parse_lead_search_api_v1_lead_search_parse_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseLeadSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseLeadSearchResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/lead-search/preview":{"post":{"tags":["lead_search"],"summary":"Preview Lead Search","operationId":"preview_lead_search_api_v1_lead_search_preview_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewLeadSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewLeadSearchResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/lead-search/runs/{run_id}/continue":{"post":{"tags":["lead_search"],"summary":"Continue Lead Search","operationId":"continue_lead_search_api_v1_lead_search_runs__run_id__continue_post","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContinueLeadSearchRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/PreviewLeadSearchResponse"},{"$ref":"#/components/schemas/ContinueLeadSearchExhaustedResponse"}],"title":"Response Continue Lead Search Api V1 Lead Search Runs  Run Id  Continue Post"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/lead-search/execute":{"post":{"tags":["lead_search"],"summary":"Execute Lead Search","operationId":"execute_lead_search_api_v1_lead_search_execute_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteLeadSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ExecuteLeadSearchResponse"},{"$ref":"#/components/schemas/ExecuteLeadSearchInProgressResponse"}],"title":"Response Execute Lead Search Api V1 Lead Search Execute Post"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/lead-search/runs/{run_id}":{"get":{"tags":["lead_search"],"summary":"Get Lead Search Run","operationId":"get_lead_search_run_api_v1_lead_search_runs__run_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"run_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Run Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadSearchRunStatusResponse"}}}},"401":{"description":"Unauthorized"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/domains/purchase/search":{"post":{"tags":["domain-purchase"],"summary":"Search Domain","description":"Validate availability and persist a billing/price snapshot quote.","operationId":"search_domain_api_v1_domains_purchase_search_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainSearchRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Search Domain Api V1 Domains Purchase Search Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/domains/purchase":{"post":{"tags":["domain-purchase"],"summary":"Purchase Domain","description":"Create or replay a purchase and synchronously drive its money path.","operationId":"purchase_domain_api_v1_domains_purchase_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DomainPurchaseRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Purchase Domain Api V1 Domains Purchase Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/domains/purchase/{purchase_id}":{"get":{"tags":["domain-purchase"],"summary":"Get Purchase","description":"Return one sanitized purchase status under actor/org-member authz.","operationId":"get_purchase_api_v1_domains_purchase__purchase_id__get","security":[{"HTTPBearer":[]}],"parameters":[{"name":"purchase_id","in":"path","required":true,"schema":{"type":"string","title":"Purchase Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response Get Purchase Api V1 Domains Purchase  Purchase Id  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/domains/purchases":{"get":{"tags":["domain-purchase"],"summary":"List Purchases","description":"Rediscover the caller's active actor-owned or org-funded purchases.","operationId":"list_purchases_api_v1_domains_purchases_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"title":"Response List Purchases Api V1 Domains Purchases Get"}}}}},"security":[{"HTTPBearer":[]}]}},"/api/v1/webhooks/stripe/domains":{"post":{"tags":["domain-stripe-webhooks"],"summary":"Stripe Domain Webhook","description":"Verify, ledger, claim, and process one domain event without touching Porkbun.","operationId":"stripe_domain_webhook_api_v1_webhooks_stripe_domains_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/webhooks/autumn":{"get":{"tags":["webhooks","webhooks"],"summary":"Health Check","description":"Health endpoint mirrors the bavimail webhook pattern.","operationId":"health_check_api_v1_webhooks_autumn_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}},"post":{"tags":["webhooks","webhooks"],"summary":"Autumn Webhook","description":"Receive an Autumn webhook delivery.\n\nFlow:\n    1. Read raw body + Svix headers.\n    2. Verify signature via svix.webhooks.Webhook (auto-rejects skew >5min).\n    3. Reject events older than _MAX_EVENT_AGE_SECONDS as 410 Gone.\n    4. Flag OFF or non-tier-mutating event -> insert-only audit row\n       (UNIQUE(svix_id) collision returns 200); no entitlement mutation.\n    5. Flag ON + tier-mutating event:\n       a. Require a customer_id; resolve the local user (G5 unmapped -> 5xx).\n       b. Re-fetch canonical Autumn state (G4); 404 -> 5xx manual_review,\n          transient -> 503.\n       c. Hand off to the atomic sync_autumn_entitlement RPC (unified\n          insert-or-claim + advisory lock + watermark + mirror write).\n          in_flight -> 503; processed/replay/stale -> 200.\n\nReturn 200 within 5s per Autumn (Svix-managed) delivery contract.","operationId":"autumn_webhook_api_v1_webhooks_autumn_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/warmup/domains/{domain_id}/enable":{"post":{"tags":["warmup"],"summary":"Enable Warmup","description":"Flip warm-up ON for a domain the caller owns. Idempotent.","operationId":"enable_warmup_api_v1_warmup_domains__domain_id__enable_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":{"title":"Response Enable Warmup Api V1 Warmup Domains  Domain Id  Enable Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/warmup/domains/{domain_id}/disable":{"post":{"tags":["warmup"],"summary":"Disable Warmup","description":"Flip warm-up OFF: delete the domain_warmup row + its alias rows.\n\nuser_id IDOR guard: delete is scoped to (user_id=caller, domain_id),\nso a foreign domain simply deletes nothing (404).","operationId":"disable_warmup_api_v1_warmup_domains__domain_id__disable_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 Disable Warmup Api V1 Warmup Domains  Domain Id  Disable Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/warmup/status":{"get":{"tags":["warmup"],"summary":"Get Warmup Status","description":"Per-user warm-up status (domain reputation + per-alias ramp).\n\nAuthoritative scope: WHERE user_id=caller. The BaviMail still-present\nfilter is BEST-EFFORT + FAIL-OPEN: hide BaviMail-absent domains when\nBaviMail is reachable; return rows UNFILTERED on a BaviMail outage.\nNo deletes happen here.","operationId":"get_warmup_status_api_v1_warmup_status_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Warmup Status Api V1 Warmup Status Get"}}}}},"security":[{"HTTPBearer":[]}]}}},"components":{"schemas":{"AcceptInviteResponse":{"properties":{"org_id":{"type":"string","format":"uuid","title":"Org Id"},"name":{"type":"string","title":"Name"},"role":{"type":"string","title":"Role","default":"member"}},"type":"object","required":["org_id","name"],"title":"AcceptInviteResponse","description":"Response for POST /api/v1/orgs/invites/{token}/accept on success (F2).\n\nThe accepter has joined ``org_id`` as a 'member'; their personal org was\nretired by the accept transaction. Returns the joined org so the frontend can\nre-resolve the user's active org without a separate fetch."},"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"},"AddLeadsResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"added":{"type":"integer","title":"Added"},"skipped_duplicate_count":{"type":"integer","title":"Skipped Duplicate Count"},"skipped":{"additionalProperties":{"type":"integer"},"type":"object","title":"Skipped"},"warnings":{"items":{"$ref":"#/components/schemas/LaunchWarning"},"type":"array","title":"Warnings"},"row_count":{"type":"integer","title":"Row Count"}},"type":"object","required":["campaign_id","added","skipped_duplicate_count","skipped","warnings","row_count"],"title":"AddLeadsResponse","description":"Outcome of appending and enrolling leads into a live campaign."},"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."},"AnnualRevenueRange":{"properties":{"lower_bound_usd":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Lower Bound Usd"},"upper_bound_usd":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Upper Bound Usd"}},"additionalProperties":false,"type":"object","title":"AnnualRevenueRange","description":"USD bounds compiled with provider `=>` lower and `=<` upper operators."},"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"},"sources":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sources"},"claim_sentences":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Claim Sentences"},"body_clean":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Clean"},"claim_sentences_stale":{"type":"boolean","title":"Claim Sentences Stale","default":false}},"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"},"reconnect_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Reconnect Account Id","description":"Bavlio connected_accounts.id to re-authenticate in place. When set, Unipile re-auths the existing provider account instead of creating a new one."},"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."},"AuthorizeResponse":{"properties":{"authorize_url":{"type":"string","title":"Authorize Url"}},"type":"object","required":["authorize_url"],"title":"AuthorizeResponse","description":"The provider authorize URL the FE navigates the browser to."},"AutoDeriveVoiceResponse":{"properties":{"user_id":{"type":"string","title":"User Id","default":""},"tone":{"type":"string","title":"Tone","default":""},"style":{"type":"string","title":"Style","default":""},"positioning":{"type":"string","title":"Positioning","default":""},"topics":{"items":{"type":"string"},"type":"array","title":"Topics"},"do_guidelines":{"items":{"type":"string"},"type":"array","title":"Do Guidelines"},"dont_guidelines":{"items":{"type":"string"},"type":"array","title":"Dont Guidelines"},"sample_snippets":{"items":{"type":"string"},"type":"array","title":"Sample Snippets"},"linkedin_arm_status":{"type":"string","title":"Linkedin Arm Status"},"linkedin_arm_detail":{"type":"string","title":"Linkedin Arm Detail","default":""},"x_arm_status":{"type":"string","title":"X Arm Status"},"x_arm_detail":{"type":"string","title":"X Arm Detail","default":""}},"type":"object","required":["linkedin_arm_status","x_arm_status"],"title":"AutoDeriveVoiceResponse","description":"An auto-derived, EDITABLE PERSONAL voice-config PRE-FILL (V2.1a re-key). NOT\nsaved -- the UI hands the (user-edited) fields to the existing PUT to persist.\n\nThe voice fields mirror ``VoiceConfigResponse`` so the UI can pre-fill the same\nform. ``user_id`` is whose personal voice this draft is for (the authenticated\nactor, echoed back; the client never supplies it). Per-arm status fields report\nhow each source resolved: ``linkedin_arm_status`` (ok / absent / error — the arm\nnow CONSUMES the person's persisted LinkedIn enrichment, no scrape) and\n``x_arm_status`` (derived / no_connection / needs_reauth / empty_timeline /\nunavailable), each with an optional content-free ``*_detail``."},"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."},"BavimailConnectionResponse":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"BavimailConnectionResponse","description":"Secret-free BaviMail connection state."},"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."},"BetweenNumericFilter-Input":{"properties":{"operator":{"type":"string","const":"between","title":"Operator"},"value":{"$ref":"#/components/schemas/NumericBetweenValue"}},"additionalProperties":false,"type":"object","required":["operator","value"],"title":"BetweenNumericFilter"},"BetweenNumericFilter-Output":{"additionalProperties":true,"type":"object"},"BetweenRevenueFilter":{"properties":{"operator":{"type":"string","const":"between","title":"Operator"},"value":{"$ref":"#/components/schemas/NumericBetweenValue"},"currency":{"anyOf":[{"type":"string","const":"USD"},{"type":"null"}],"title":"Currency"}},"additionalProperties":false,"type":"object","required":["operator","value"],"title":"BetweenRevenueFilter"},"Body_create_post_api_v1_linkedin_posts__post":{"properties":{"text":{"type":"string","maxLength":3000,"minLength":1,"title":"Text"},"schedule_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Schedule At"},"connected_account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connected Account Id"},"provider_account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Account Id"},"media_asset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Media Asset 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_upload_campaign_attachments_api_v1_bavimail_attachments_post":{"properties":{"files":{"items":{"type":"string","format":"binary"},"type":"array","title":"Files"}},"type":"object","required":["files"],"title":"Body_upload_campaign_attachments_api_v1_bavimail_attachments_post"},"Body_upload_company_context_document_api_v1_company_context_documents_upload_post":{"properties":{"file":{"type":"string","format":"binary","title":"File"},"title":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Title"}},"type":"object","required":["file"],"title":"Body_upload_company_context_document_api_v1_company_context_documents_upload_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"},"Body_upload_media_api_v1_media__post":{"properties":{"file":{"type":"string","format":"binary","title":"File"}},"type":"object","required":["file"],"title":"Body_upload_media_api_v1_media__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."},"BulkFromDatasetRequest":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id","description":"Dataset UUID owned by the authenticated user"},"client_estimated_credits":{"type":"integer","exclusiveMinimum":0.0,"title":"Client Estimated Credits","description":"User-confirmed estimate from the modal. Must be > 0."},"find_on_invalid":{"type":"boolean","title":"Find On Invalid","default":true}},"type":"object","required":["dataset_id","client_estimated_credits"],"title":"BulkFromDatasetRequest","description":"Request body for /bulk-from-dataset.\n\nFields:\n- `dataset_id`: target dataset UUID (must be owned by the authenticated user\n  AND have an eligible `source_type`).\n- `client_estimated_credits`: REQUIRED. The estimate the user agreed to when\n  they confirmed the spend in the modal. Server tolerance gate fires if\n  `3 * len(eligible_rows) > 1.2 * client_estimated_credits`, returning 409\n  with `actual_estimated_credits` so the frontend can re-display the modal\n  with the live number."},"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} rows or ledger-only {linkedin_url} rows"},"file_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"File Name","description":"Original upload filename"}},"type":"object","required":["rows"],"title":"BulkSearchRequest"},"BulkVerifyRequest":{"properties":{"emails":{"items":{"type":"string","format":"email"},"type":"array","maxItems":5000,"minItems":1,"title":"Emails"},"file_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"File Name"},"force":{"type":"boolean","title":"Force","description":"Reserved for cache-bypass compatibility","default":false},"require_full_batch":{"type":"boolean","title":"Require Full Batch","description":"Require enough available credits for the full batch before enqueueing.","default":false}},"type":"object","required":["emails"],"title":"BulkVerifyRequest"},"BusinessContactEnrichmentRequest":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id","description":"Dataset UUID owned by the authenticated organization"},"client_estimated_credits":{"type":"integer","minimum":0.0,"title":"Client Estimated Credits"},"mode":{"type":"string","pattern":"^(business|needs_review|all)$","title":"Mode","default":"business"},"route_mode":{"type":"string","pattern":"^website$","title":"Route Mode","default":"website"}},"type":"object","required":["dataset_id","client_estimated_credits"],"title":"BusinessContactEnrichmentRequest"},"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."},"CampaignActivityResponse":{"properties":{"events":{"items":{"$ref":"#/components/schemas/CampaignTimelineEvent"},"type":"array","title":"Events"},"total":{"type":"integer","title":"Total"},"has_more":{"type":"boolean","title":"Has More","default":false},"next_before":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Before"}},"type":"object","required":["events","total"],"title":"CampaignActivityResponse","description":"Campaign-wide activity feed (A4b). `has_more` signals a `before`-paged\n\"load more\" can fetch an older window; `next_before` is the oldest event's\ntimestamp to pass as the next `before` (clients may also use it verbatim)."},"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},"sent_count":{"type":"integer","title":"Sent Count","default":0},"deduped_sent_count":{"type":"integer","title":"Deduped Sent Count","default":0},"delivered_count":{"type":"integer","title":"Delivered Count","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."},"CampaignDraftAudienceResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"},"campaign_type":{"type":"string","title":"Campaign Type"},"campaign_status":{"type":"string","const":"draft","title":"Campaign Status"},"rows":{"items":{"$ref":"#/components/schemas/DraftAudienceRow"},"type":"array","title":"Rows"},"total":{"type":"integer","title":"Total"},"page":{"type":"integer","title":"Page"},"page_size":{"type":"integer","title":"Page Size"},"total_pages":{"type":"integer","title":"Total Pages"},"columns":{"items":{"type":"string"},"type":"array","title":"Columns"},"latest_session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Latest Session Id"},"audience_semantics":{"type":"string","const":"selected_dataset","title":"Audience Semantics","default":"selected_dataset"},"advisory":{"$ref":"#/components/schemas/DraftAudienceAdvisory"}},"type":"object","required":["campaign_id","dataset_id","campaign_type","campaign_status","rows","total","page","page_size","total_pages","columns","latest_session_id","advisory"],"title":"CampaignDraftAudienceResponse","description":"Read-only selected dataset preview for a draft campaign."},"CampaignLaunchRequest":{"properties":{"force":{"type":"boolean","title":"Force","default":false}},"type":"object","title":"CampaignLaunchRequest","description":"Optional controls for a campaign launch request."},"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","preview","active","processing","completed","replied","bounced","unsubscribed","failed","paused","invalid","skipped","waiting_acceptance","connected","connection_ignored","rate_limited"],"title":"CampaignLeadStatus","description":"Campaign lead status values.\n\n`SKIPPED` is a new terminal status introduced by the commonality\nthreshold filter (plan 2026-05-21-commonality-threshold-filter, AC-19).\nDispatcher selection (`status IN ('active', 'connected')`) already\nnaturally excludes it. The DB CHECK constraint expansion lives in PR-2a."},"CampaignListItem":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"dataset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Dataset Id"},"discovery_enabled":{"type":"boolean","title":"Discovery Enabled","default":false},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"status":{"$ref":"#/components/schemas/CampaignStatus"},"total_leads":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Leads"},"processed_leads":{"type":"integer","title":"Processed Leads","default":0},"metrics":{"anyOf":[{"$ref":"#/components/schemas/CampaignMetrics"},{"type":"null"}]},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"daily_limit":{"type":"integer","title":"Daily Limit"},"sending_window_start":{"type":"string","format":"time","title":"Sending Window Start"},"sending_window_end":{"type":"string","format":"time","title":"Sending Window End"},"min_interval_seconds":{"type":"integer","title":"Min Interval Seconds"},"timezone":{"type":"string","title":"Timezone"},"steps_config":{"items":{"$ref":"#/components/schemas/CampaignStepConfig"},"type":"array","title":"Steps Config"},"alias_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Alias Ids"},"connected_account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Connected Account Id"},"send_days":{"items":{"type":"string"},"type":"array","title":"Send Days"},"launch_type":{"$ref":"#/components/schemas/CampaignLaunchType"},"start_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"End Date"},"steps":{"anyOf":[{"items":{"$ref":"#/components/schemas/CampaignStepConfig"},"type":"array"},{"type":"null"}],"title":"Steps"},"launch_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Launch Error"},"system_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Prompt"},"unreviewed_launch_policy":{"$ref":"#/components/schemas/UnreviewedLaunchPolicy","default":"launch_default"},"paused_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Paused Reason"},"playground_discovery_dismissed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Playground Discovery Dismissed At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"launched_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Launched At"}},"type":"object","required":["campaign_id","user_id","name","type","status","daily_limit","sending_window_start","sending_window_end","min_interval_seconds","timezone","steps_config","send_days","launch_type","created_at","updated_at"],"title":"CampaignListItem","description":"Public campaign fields returned by the campaign list endpoint."},"CampaignListResponse":{"properties":{"campaigns":{"items":{"$ref":"#/components/schemas/CampaignListItem"},"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."},"CampaignMergeField":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"example":{"anyOf":[{},{"type":"null"}],"title":"Example"}},"type":"object","required":["key","label"],"title":"CampaignMergeField","description":"A merge tag available from a campaign's selected dataset."},"CampaignMergeFieldsResponse":{"properties":{"fields":{"items":{"$ref":"#/components/schemas/CampaignMergeField"},"type":"array","title":"Fields"}},"type":"object","required":["fields"],"title":"CampaignMergeFieldsResponse","description":"Insertable merge tags for campaign message personalization."},"CampaignMetrics":{"properties":{"sent":{"type":"integer","title":"Sent","default":0},"delivered":{"type":"integer","title":"Delivered","default":0},"opened":{"type":"integer","title":"Opened","default":0},"clicked":{"type":"integer","title":"Clicked","default":0},"replied":{"type":"integer","title":"Replied","default":0},"bounced":{"type":"integer","title":"Bounced","default":0},"unsubscribed":{"type":"integer","title":"Unsubscribed","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"},"linkedin_requests_sent":{"type":"integer","title":"Linkedin Requests Sent","default":0},"linkedin_accepted":{"type":"integer","title":"Linkedin Accepted","default":0},"linkedin_replied":{"type":"integer","title":"Linkedin Replied","default":0},"linkedin_acceptance_rate":{"type":"string","title":"Linkedin Acceptance Rate","default":"0.0"},"linkedin_reply_rate":{"type":"string","title":"Linkedin Reply Rate","default":"0.0"},"channel":{"type":"string","title":"Channel","description":"Metrics channel: 'email', 'linkedin', or 'mixed'. For 'mixed', both the generic email fields and the linkedin_* fields are meaningful.","default":"email"}},"type":"object","title":"CampaignMetrics","description":"Channel-aware engagement metrics for the campaigns LIST page.\n\nPopulated by the batch RPC get_campaigns_stats_summary_by_org (migration\n391); rates use the SAME numerators/denominators and formatting as\nget_campaign_stats so LIST and DETAIL never disagree. Field names match\nthe frontend's metrics contract (src/services/api/campaigns.js)."},"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":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Dataset Id","description":"Associated dataset ID"},"discovery_enabled":{"type":"boolean","title":"Discovery Enabled","description":"Whether continuous discovery is currently enabled.","default":false},"discovery_targeting":{"anyOf":[{"$ref":"#/components/schemas/DiscoveryTargeting"},{"type":"null"}],"description":"What continuous discovery enforces against LinkedIn data, and which saved filters it cannot verify."},"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"},"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_mailbox_ids":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Connected Mailbox Ids","description":"Connected mailbox emails to send from (peer of alias_ids, mig 272)"},"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)."},"locked_through":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Locked Through","description":"Highest step index reached by a non-terminal lead. Steps up to and including this are locked; later steps are the editable tail."},"metrics":{"anyOf":[{"$ref":"#/components/schemas/CampaignMetrics"},{"type":"null"}],"description":"Per-campaign engagement metrics (open_rate/reply_rate etc.) for the list view. Same computation as GET /campaigns/{id}/stats."},"compliance_footer_enabled":{"type":"boolean","title":"Compliance Footer Enabled","description":"CASL opt-in: compliance footer enabled for this campaign.","default":false},"list_unsub_enabled":{"type":"boolean","title":"List Unsub Enabled","description":"CASL opt-in: List-Unsubscribe header enabled for this campaign.","default":false},"compliance_risk_ack_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Compliance Risk Ack At","description":"§9 risk-shift audit: when the no-footer risk was acknowledged."},"compliance_risk_ack_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Compliance Risk Ack By","description":"§9 risk-shift audit: user who acknowledged (frontend-written)."},"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","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."},"CampaignSourceList":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"archived":{"type":"boolean","title":"Archived","default":false},"first_added_at":{"type":"string","format":"date-time","title":"First Added At"},"last_added_at":{"type":"string","format":"date-time","title":"Last Added At"},"add_count":{"type":"integer","title":"Add Count"}},"type":"object","required":["dataset_id","first_added_at","last_added_at","add_count"],"title":"CampaignSourceList","description":"A dataset previously added to a campaign audience."},"CampaignSourceListsResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"sources":{"items":{"$ref":"#/components/schemas/CampaignSourceList"},"type":"array","title":"Sources"}},"type":"object","required":["campaign_id","sources"],"title":"CampaignSourceListsResponse","description":"Datasets previously added to a campaign audience."},"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},"variants":{"items":{"$ref":"#/components/schemas/CampaignVariantStat"},"type":"array","title":"Variants"}},"type":"object","title":"CampaignStatsResponse","description":"Response model for single campaign stats (detail page)."},"CampaignStatus":{"type":"string","enum":["draft","launching","scoring","review_ready","scheduled","active","draining","paused","completed","failed"],"title":"CampaignStatus","description":"Campaign status values.\n\n`SCORING` and `REVIEW_READY` are the commonality-threshold extension\nstates (plan 2026-05-21-commonality-threshold-filter, AC-17 / B2).\nThey are enumerated here so that every reader of `campaigns.status`\nsees the full set; the DB CHECK constraint expansion lives in PR-2a.\nUntil `COMMONALITY_THRESHOLD_ENABLED=true`, no campaign row should\ncarry these values in production (feature-flag-gated at the\ncustomer-entry endpoints — see plan §\"Feature flag policy\")."},"CampaignStepAttachment":{"properties":{"attachment_id":{"type":"string","minLength":1,"title":"Attachment Id","description":"BaviMail stored attachment id"},"filename":{"type":"string","maxLength":255,"minLength":1,"title":"Filename","description":"Original file name"},"mime_type":{"type":"string","title":"Mime Type","description":"MIME type (must be in the allowlist)"},"size_bytes":{"type":"integer","maximum":4000000.0,"minimum":1.0,"title":"Size Bytes","description":"File size in bytes"},"sha256":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sha256","description":"Content hash from BaviMail (integrity/dedup)"}},"type":"object","required":["attachment_id","filename","mime_type","size_bytes"],"title":"CampaignStepAttachment","description":"Reference to a BaviMail-stored file attached to an email step.\n\nThe bytes live in BaviMail attachment storage (uploaded via the attachment\nproxy, which enforces the size + MIME allowlist on the real bytes). Only this\nreference is persisted in `steps_config`; the worker re-fetches the bytes by\n`attachment_id` at send time. The field-level caps here are defense-in-depth\nagainst a hand-crafted steps_config that bypasses the upload gate."},"CampaignStepConfig":{"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)"},"include_catch_all":{"type":"boolean","title":"Include Catch All","description":"Explicit consent to include catch-all recipients in this email step. False excludes them from enrollment and sending.","default":false},"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},"track_opens":{"type":"boolean","title":"Track Opens","description":"Enable open tracking (pixel) for this step. Alias sends only.","default":false},"attachments":{"anyOf":[{"items":{"$ref":"#/components/schemas/CampaignStepAttachment"},"type":"array","maxItems":3},{"type":"null"}],"title":"Attachments","description":"Files attached to this email step (BaviMail-stored refs). Intended for warm follow-ups; attachments hurt cold-step deliverability."},"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"},"gate":{"anyOf":[{"$ref":"#/components/schemas/StepGate"},{"type":"null"}],"description":"Optional conditional-branch gate (v1: accepted-signal only)."},"end_sequence":{"type":"boolean","title":"End Sequence","description":"When True, a lead that finishes this step is completed instead of advancing to the next step. Only legal on a step inside a gate's accepted lane whose immediate successor is that gate's gate_on_timeout_step (isolates the two branch lanes). Legacy steps_config rows lack this key and parse as False.","default":false}},"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."},"CampaignStepCopyDraftRequest":{"properties":{"channel":{"type":"string","minLength":1,"title":"Channel"},"action_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action Type"},"sender_profile_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Sender Profile Id"},"campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Name"},"instruction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instruction"},"merge_fields":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Merge Fields"},"existing_copy":{"anyOf":[{"$ref":"#/components/schemas/ExistingCopy"},{"type":"null"}]},"sequence_context":{"anyOf":[{"items":{"$ref":"#/components/schemas/SequenceStepContext"},"type":"array"},{"type":"null"}],"title":"Sequence Context"},"step_index":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Step Index","description":"Zero-based index of the sequence step being generated."}},"type":"object","required":["channel"],"title":"CampaignStepCopyDraftRequest","description":"Fixed request contract consumed by the campaign step editor."},"CampaignStepCopyDraftResponse":{"properties":{"channel":{"type":"string","title":"Channel"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"body":{"type":"string","title":"Body"},"mode":{"type":"string","enum":["compose","critique"],"title":"Mode"},"findings":{"items":{"$ref":"#/components/schemas/Finding"},"type":"array","title":"Findings"}},"type":"object","required":["channel","subject","body","mode","findings"],"title":"CampaignStepCopyDraftResponse","description":"Drafted campaign-step copy and optional critique findings."},"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)"},"message_template":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message Template","description":"Inline LinkedIn variant message text (Option B). Required for a LinkedIn TEMPLATE variant (per action_type); rejected on an email TEMPLATE variant, which must use template_id instead."},"prompt_name":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Prompt Name","description":"Optional saved-prompt name from sender_profile.sender_data.prompts[]. Matched case-insensitively at send time. Only valid when 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."},"CampaignTimelineEvent":{"properties":{"event_type":{"type":"string","title":"Event Type"},"source":{"$ref":"#/components/schemas/CampaignTimelineEventSource"},"occurred_at":{"type":"string","format":"date-time","title":"Occurred At"},"campaign_lead_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Lead Id"},"step":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Step"},"job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Job Id"},"variant_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Label"},"attempt_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attempt Label"},"detail":{"additionalProperties":true,"type":"object","title":"Detail"}},"type":"object","required":["event_type","source","occurred_at"],"title":"CampaignTimelineEvent","description":"One normalized event in a lead timeline (A4a) or campaign activity feed\n(A4b). Shared artifact across both endpoints.\n\n`occurred_at` is when the event happened (the send/claim time for a job\nlifecycle event, the webhook receipt time for an engagement event, the\nprovider event time for a BaviMail event) — distinct from a row's\n`created_at`, which is when our DB recorded it."},"CampaignTimelineEventSource":{"type":"string","enum":["job","engagement","bavimail"],"title":"CampaignTimelineEventSource","description":"Origin of a normalized timeline/activity event.\n\n`job` = outbound_jobs lifecycle (local). `engagement` = engagement_log\n(local webhook mirror). `bavimail` = BaviMail email-events API (remote,\ncached, degradable). Local sources always serve even when BaviMail is down."},"CampaignVariantStat":{"properties":{"channel":{"type":"string","title":"Channel"},"step":{"type":"integer","title":"Step"},"variant_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Label"},"source_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Type"},"sent":{"type":"integer","title":"Sent","default":0},"accepted":{"type":"integer","title":"Accepted","default":0},"delivered":{"type":"integer","title":"Delivered","default":0},"replied":{"type":"integer","title":"Replied","default":0}},"type":"object","required":["channel","step"],"title":"CampaignVariantStat","description":"One row of the two-source per-variant breakdown (PR4).\n\nEmail rows come from outbound_jobs, LinkedIn rows from campaign_actions; the\nRPC UNION ALLs them. `accepted` is LinkedIn-only (connection_request connect\nphase); `delivered` is email-only. Counts are COUNT(DISTINCT campaign_lead_id)."},"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."},"CatalogueProviderResponse":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"categories":{"items":{"type":"string"},"type":"array","title":"Categories"},"state":{"type":"string","title":"State"},"connected":{"type":"boolean","title":"Connected"},"requested":{"type":"boolean","title":"Requested"},"required_config":{"items":{"$ref":"#/components/schemas/RequiredConnectorConfigFieldResponse"},"type":"array","title":"Required Config"}},"type":"object","required":["slug","name","categories","state","connected","requested","required_config"],"title":"CatalogueProviderResponse"},"CatalogueResponse":{"properties":{"providers":{"items":{"$ref":"#/components/schemas/CatalogueProviderResponse"},"type":"array","title":"Providers"},"total":{"type":"integer","title":"Total"},"connectors_enabled":{"type":"boolean","title":"Connectors Enabled"},"connector_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Connector Limit"}},"type":"object","required":["providers","total","connectors_enabled","connector_limit"],"title":"CatalogueResponse"},"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."},"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."},"ClaimSentence":{"properties":{"sentence_text":{"type":"string","title":"Sentence Text","description":"Canonical claim phrasing (LLM-emitted)","default":""},"source_indices":{"items":{"type":"integer"},"type":"array","title":"Source Indices","description":"1-indexed into the SOURCES block; empty = ungrounded"},"body_offset_start":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Body Offset Start","description":"UTF-16 code-unit offset in body_clean (inclusive); None if unmatched"},"body_offset_end":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Body Offset End","description":"UTF-16 code-unit offset in body_clean (exclusive); None if unmatched"}},"type":"object","title":"ClaimSentence","description":"A single factual claim sentence + its source bindings + body offsets.\n\nPlan AC-9. Single shared model imported by both ``EmailGeneration`` and\n``CommonalityMetadata``. The LLM emits ``sentence_text`` + ``source_indices``;\nthe deterministic post-processor emits the UTF-16 code-unit offsets.\n\nOffsets are NULL when the sentence cannot be located in ``body_clean``\n(AC-12 unmatched-sentence rule). Frontend skips the inline marker for\nunmatched claims (AC-9a safety net + AC-26 ungrounded-warning surface\nvia ``CommonalityMetadata.ungrounded_claim_count``)."},"ClarificationRequiredResponse":{"properties":{"status":{"type":"string","const":"clarification_required","title":"Status","default":"clarification_required"},"question":{"type":"string","title":"Question"}},"type":"object","required":["question"],"title":"ClarificationRequiredResponse"},"CodeResponse":{"properties":{"referral_code":{"type":"string","title":"Referral Code"}},"type":"object","required":["referral_code"],"title":"CodeResponse"},"CombineDatasetsRequest":{"properties":{"source_dataset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"minItems":2,"title":"Source Dataset Ids"},"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"}},"additionalProperties":false,"type":"object","required":["source_dataset_ids","name"],"title":"CombineDatasetsRequest","description":"Source datasets and display name for a combined campaign list."},"CombineDatasetsResponse":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"},"name":{"type":"string","title":"Name"},"row_count":{"type":"integer","title":"Row Count"},"source_count":{"type":"integer","title":"Source Count"},"skipped_duplicate_count":{"type":"integer","title":"Skipped Duplicate Count"}},"type":"object","required":["dataset_id","name","row_count","source_count","skipped_duplicate_count"],"title":"CombineDatasetsResponse","description":"Combined dataset created from all available unique source leads."},"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":""},"composite_score":{"anyOf":[{"type":"number","maximum":1.0,"minimum":0.0},{"type":"null"}],"title":"Composite Score","description":"Composite commonality score in [0, 1] computed by compute_commonality_composite(). None on legacy rows and on rows where scoring has not yet completed."},"signal_categories":{"items":{"type":"string"},"type":"array","title":"Signal Categories","description":"String values of SignalCategory entries the analyzer emitted. Mirrors agentic.email_pipeline.personalization.SignalCategory but is kept as list[str] here to keep this lightweight DTO free of an agentic import. Empty list on legacy rows."},"score_breakdown":{"anyOf":[{"additionalProperties":{"type":"number"},"type":"object"},{"type":"null"}],"title":"Score Breakdown","description":"Per-signal numeric breakdown that fed into composite_score (keys: confidence, rarity, relevance). None on legacy rows."},"sources":{"items":{"$ref":"#/components/schemas/PersonalizationSource"},"type":"array","title":"Sources","description":"Per-URL personalization sources (AC-15). Empty = no research surface available."},"claim_sentences":{"items":{"$ref":"#/components/schemas/ClaimSentence"},"type":"array","title":"Claim Sentences","description":"Per-claim source bindings + offsets (AC-16)."},"ungrounded_claim_count":{"type":"integer","minimum":0.0,"title":"Ungrounded Claim Count","description":"Count of claim_sentences with empty source_indices (AC-10a).","default":0},"body_clean":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Clean","description":"LLM plain-text body verbatim; offsets index against this (AC-12)."},"research_context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Research Context","description":"Lever 3: aggregated research context used to produce this draft. Surfaced so the playground can cache it per-lead and re-draft prompt-only iterations with the personalizer alone. None on paths that don't run research."}},"type":"object","required":["commonality_found","confidence_score","research_sources","generation_time_ms","model_used"],"title":"CommonalityMetadata","description":"Metadata about the discovered commonality.\n\nThe optional fields below (`composite_score`, `signal_categories`,\n`score_breakdown`) are written by the commonality-threshold scoring\npipeline (`api/services/commonality_scoring.py`). They are absent on\nlegacy rows and on rows produced by the original send-path pipeline\nthat has not yet been re-scored; readers MUST treat them as optional\n(AC-3 backwards-compat — every existing read-site asserted in\n`tests/unit/test_commonality_metadata_backwards_compat.py`)."},"CompanyContextSearchHitResponse":{"properties":{"chunk_id":{"type":"string","title":"Chunk Id"},"document_id":{"type":"string","title":"Document Id"},"chunk_index":{"type":"integer","title":"Chunk Index"},"content":{"type":"string","title":"Content"},"document_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document Title"},"similarity":{"type":"number","title":"Similarity"}},"type":"object","required":["chunk_id","document_id","chunk_index","content","similarity"],"title":"CompanyContextSearchHitResponse"},"CompanyContextSearchRequest":{"properties":{"query":{"type":"string","maxLength":16000,"minLength":1,"title":"Query"},"limit":{"type":"integer","maximum":50.0,"minimum":1.0,"title":"Limit","default":10}},"type":"object","required":["query"],"title":"CompanyContextSearchRequest"},"CompanyCriteria":{"properties":{"names":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Explicit company names."},"domains":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Explicit company domains."},"industries":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Employer industry labels such as Software or Publishing. Do not combine multiple concepts into one value."},"categories":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Atomic Crust company taxonomy values. Common values include B2B, SaaS, Artificial Intelligence (AI), Media, and Publishing. Put each explicit concept in its own value and use match=all when every concept is required. Do not add an employer filter that would turn a cross-scope OR into AND."},"keywords":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Fuzzy concepts that describe the employer when no exact taxonomy applies."},"country_codes":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Company-location countries. Prefer full names such as United Kingdom, United States, or Canada; common abbreviations and ISO alpha-2/alpha-3 codes are accepted."},"headcount":{"anyOf":[{"$ref":"#/components/schemas/IntegerRange"},{"type":"null"}],"description":"Current employer employee-count range. This is never the number of leads to return."},"annual_revenue":{"anyOf":[{"$ref":"#/components/schemas/AnnualRevenueRange"},{"type":"null"}],"description":"Estimated annual revenue in USD. Compile the lower bound to revenue.estimated.lower_bound_usd and the upper bound to revenue.estimated.upper_bound_usd."},"funding_stages":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Normalized company funding stages, one per value: pre_seed, angel, seed, series_a, series_b, series_c, venture, private_equity, or ipo. Use match=any."}},"additionalProperties":false,"type":"object","title":"CompanyCriteria"},"CompanyFactPatchRequest":{"properties":{"content":{"anyOf":[{"type":"string","maxLength":4000,"minLength":1},{"type":"null"}],"title":"Content"},"status":{"anyOf":[{"type":"string","const":"rejected"},{"type":"null"}],"title":"Status"}},"additionalProperties":false,"type":"object","title":"CompanyFactPatchRequest"},"CompanyFactResponse":{"properties":{"id":{"type":"string","title":"Id"},"document_id":{"type":"string","title":"Document Id"},"fact_type":{"type":"string","enum":["positioning","icp","proof_point","objection","rebuttal","differentiator","capability","pricing","voice_sample"],"title":"Fact Type"},"content":{"type":"string","title":"Content"},"confidence":{"type":"number","title":"Confidence"},"source_span_start":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Source Span Start"},"source_span_end":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Source Span End"},"source_updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Updated At"},"status":{"type":"string","enum":["active","superseded","conflicted","rejected"],"title":"Status"},"reviewed_by_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reviewed By User Id"},"reviewed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reviewed At"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["id","document_id","fact_type","content","confidence","status","created_at","updated_at"],"title":"CompanyFactResponse"},"CompanyRoleEnrichmentRequest":{"properties":{"target_role":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Target Role"},"max_rows":{"anyOf":[{"type":"integer","maximum":100000.0,"minimum":1.0},{"type":"null"}],"title":"Max Rows"}},"additionalProperties":false,"type":"object","title":"CompanyRoleEnrichmentRequest","description":"Optional target-role override applied to every eligible row."},"CompleteOnboardingRequest":{"properties":{"exit_to_page":{"type":"string","title":"Exit To Page","description":"Dashboard page to open after completing onboarding.","default":"dashboard"},"segment":{"type":"string","title":"Segment","description":"Optional frontend segment/persona.","default":""},"goals":{"type":"string","title":"Goals","description":"Optional setup goals summary.","default":""},"signup_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signup Source","description":"Optional acquisition source."},"signup_source_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signup Source Detail","description":"Optional detail when the acquisition source is other."}},"type":"object","title":"CompleteOnboardingRequest","description":"Request body for completing onboarding outside the chat stream."},"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."},"ConnectBavimailRequest":{"properties":{"api_key":{"type":"string","maxLength":512,"minLength":8,"format":"password","title":"Api Key","writeOnly":true}},"type":"object","required":["api_key"],"title":"ConnectBavimailRequest","description":"User-supplied BaviMail credential."},"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)."},"ConnectedAccountListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"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},"weekly_connection_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weekly Connection Limit"},"used_today":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Used Today"},"effective_daily_limits":{"anyOf":[{"additionalProperties":{"type":"integer"},"type":"object"},{"type":"null"}],"title":"Effective Daily Limits"},"connections_today":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Connections Today"},"messages_today":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Messages Today"},"effective_daily_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Effective Daily Limit"}},"type":"object","required":["id","provider","status"],"title":"ConnectedAccountListItem","description":"Public connected-account fields returned by the list endpoint."},"ConnectedAccountListResponse":{"properties":{"accounts":{"items":{"$ref":"#/components/schemas/ConnectedAccountListItem"},"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},"weekly_connection_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Weekly Connection Limit"},"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","pending_eviction"],"title":"ConnectedAccountStatus"},"ConnectorConnectionResponse":{"properties":{"id":{"type":"string","title":"Id"},"provider":{"type":"string","title":"Provider"},"provider_name":{"type":"string","title":"Provider Name"},"status":{"type":"string","title":"Status"},"connected_at":{"type":"string","title":"Connected At"},"last_synced_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Synced At"},"document_count":{"type":"integer","title":"Document Count"}},"type":"object","required":["id","provider","provider_name","status","connected_at","document_count"],"title":"ConnectorConnectionResponse"},"ConnectorDisconnectResponse":{"properties":{"disconnected":{"type":"boolean","title":"Disconnected"},"provider_revoked":{"type":"boolean","title":"Provider Revoked"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["disconnected","provider_revoked"],"title":"ConnectorDisconnectResponse"},"ConnectorDocumentIngestResponse":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"source_kind":{"type":"string","title":"Source Kind"},"chunk_count":{"type":"integer","title":"Chunk Count"},"embedded_count":{"type":"integer","title":"Embedded Count"},"indexing_status":{"type":"string","enum":["indexed","not_relevant","failed","skipped"],"title":"Indexing Status"}},"type":"object","required":["id","title","source_kind","chunk_count","embedded_count","indexing_status"],"title":"ConnectorDocumentIngestResponse"},"ConnectorSessionRequest":{"properties":{"provider":{"type":"string","maxLength":200,"minLength":1,"title":"Provider"},"config":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"title":"Config"}},"type":"object","required":["provider"],"title":"ConnectorSessionRequest"},"ConnectorSessionResponse":{"properties":{"provider":{"type":"string","title":"Provider"},"session_token":{"type":"string","title":"Session Token"},"connect_url":{"type":"string","title":"Connect Url"},"expires_at":{"type":"string","title":"Expires At"}},"type":"object","required":["provider","session_token","connect_url","expires_at"],"title":"ConnectorSessionResponse"},"ConnectorSkippedResponse":{"properties":{"ref":{"type":"string","title":"Ref"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["ref","reason"],"title":"ConnectorSkippedResponse"},"ConnectorSyncResponse":{"properties":{"ingested":{"type":"integer","title":"Ingested"},"updated":{"type":"integer","title":"Updated"},"unchanged":{"type":"integer","title":"Unchanged"},"skipped":{"items":{"$ref":"#/components/schemas/ConnectorSkippedResponse"},"type":"array","title":"Skipped"},"complete":{"type":"boolean","title":"Complete"}},"type":"object","required":["ingested","updated","unchanged","skipped","complete"],"title":"ConnectorSyncResponse"},"ContentConnectionSignal":{"properties":{"provider":{"type":"string","title":"Provider"},"connected":{"type":"boolean","title":"Connected"},"needs_reauth":{"type":"boolean","title":"Needs Reauth","default":false},"scope":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scope"}},"type":"object","required":["provider","connected"],"title":"ContentConnectionSignal"},"ContentDashboardSnapshotResponse":{"properties":{"connections":{"items":{"$ref":"#/components/schemas/ContentConnectionSignal"},"type":"array","title":"Connections"},"voice":{"$ref":"#/components/schemas/ContentVoiceSignal"},"drafts":{"$ref":"#/components/schemas/ContentDraftSignal"},"schedule":{"$ref":"#/components/schemas/ContentScheduleSignal"}},"type":"object","required":["connections","voice","drafts","schedule"],"title":"ContentDashboardSnapshotResponse"},"ContentDraftCreateRequest":{"properties":{"linkedin_body":{"anyOf":[{"type":"string","maxLength":3000},{"type":"null"}],"title":"Linkedin Body"},"x_body":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"X Body"},"media_asset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Media Asset Id"},"media_asset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"title":"Media Asset Ids"},"idempotency_key":{"type":"string","maxLength":120,"minLength":8,"title":"Idempotency Key"}},"type":"object","required":["idempotency_key"],"title":"ContentDraftCreateRequest","description":"Create a customer-authored Inbox draft without invoking generation."},"ContentDraftEditRequest":{"properties":{"linkedin_body":{"anyOf":[{"type":"string","maxLength":3000},{"type":"null"}],"title":"Linkedin Body"},"x_body":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"X Body"},"media_asset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Media Asset Id"},"media_asset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"title":"Media Asset Ids"}},"type":"object","title":"ContentDraftEditRequest","description":"Edit a draft's per-platform bodies / attached media.\n\nAll fields optional; only the provided fields are updated. ``media_asset_id=None``\nis AMBIGUOUS in JSON (absent vs explicit null), so the service uses Pydantic's\n``model_fields_set`` to distinguish \"not provided\" (leave as-is) from \"explicitly\ncleared\" (detach the image). At least one field must be present."},"ContentDraftGenerateRequest":{"properties":{"topic":{"type":"string","maxLength":1200,"minLength":3,"title":"Topic"},"signal_ref":{"anyOf":[{"type":"string","maxLength":300,"minLength":3},{"type":"null"}],"title":"Signal Ref","description":"Optional source-card ref from /content/signals/suggestions. When set, generation is grounded in that org-scoped signal's copied facts."},"media_asset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Media Asset Id"},"media_asset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"title":"Media Asset Ids"},"platforms":{"anyOf":[{"items":{"type":"string","enum":["linkedin","x"]},"type":"array","maxItems":2,"minItems":1},{"type":"null"}],"title":"Platforms","description":"Target platforms for the draft. Omit to use all default platforms. LinkedIn and X are generated by default today."},"idempotency_key":{"type":"string","maxLength":120,"minLength":8,"title":"Idempotency Key"}},"type":"object","required":["topic","idempotency_key"],"title":"ContentDraftGenerateRequest","description":"Generate and persist a new Inbox draft from a customer topic/seed."},"ContentDraftListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ContentDraftResponse"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"ContentDraftListResponse","description":"Keyset-paginated page of Inbox drafts."},"ContentDraftResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","enum":["pending","approved","denied","snoozed","scheduled"],"title":"Status"},"linkedin_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Body"},"x_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X Body"},"media_asset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Media Asset Id"},"media_asset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Media Asset Ids"},"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"voice_config_snapshot":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Voice Config Snapshot"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"topic":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Topic"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","status","created_at","updated_at"],"title":"ContentDraftResponse","description":"A single Inbox draft card (list-row + get + action responses).\n\nNEVER includes ``dedupe_key`` (internal CAS key). ``voice_config_snapshot`` is the\nvoice config stamped at generate time (E3.1); the UI may render it read-only."},"ContentDraftScheduleRequest":{"properties":{"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"local_datetime":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Local Datetime"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"provider_account_id":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Provider Account Id","description":"LinkedIn OAuth account to pin for this scheduled post. Omit to snapshot the org's LinkedIn default when the dispatch row is created."},"linkedin_account_id":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Linkedin Account Id"},"x_account_id":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"X Account Id"}},"type":"object","title":"ContentDraftScheduleRequest","description":"Schedule a draft to publish at a future instant.\n\nTwo input shapes (exactly one): an ABSOLUTE ``scheduled_at`` (tz-aware), OR a\nper-tenant wall-clock ``local_datetime`` (naive) + IANA ``timezone``. The server\nresolves the wall-clock via ZoneInfo, rejects past-time + DST-gap, and enforces the\nper-day cap. Scheduling enrolls the draft into the dispatch queue (E4.1b)."},"ContentDraftSignal":{"properties":{"pending":{"type":"integer","title":"Pending","default":0},"scheduled":{"type":"integer","title":"Scheduled","default":0},"snoozed":{"type":"integer","title":"Snoozed","default":0},"denied":{"type":"integer","title":"Denied","default":0}},"type":"object","title":"ContentDraftSignal"},"ContentScheduleSignal":{"properties":{"upcoming":{"type":"integer","title":"Upcoming","default":0},"needs_attention":{"type":"integer","title":"Needs Attention","default":0},"posted":{"type":"integer","title":"Posted","default":0}},"type":"object","title":"ContentScheduleSignal"},"ContentVoiceSignal":{"properties":{"company_configured":{"type":"boolean","title":"Company Configured"},"person_configured":{"type":"boolean","title":"Person Configured"},"company_updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Updated At"},"person_updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Person Updated At"}},"type":"object","required":["company_configured","person_configured"],"title":"ContentVoiceSignal"},"ContinueLeadSearchExhaustedResponse":{"properties":{"exhausted":{"type":"boolean","title":"Exhausted","default":true},"delivered_count":{"type":"integer","title":"Delivered Count","default":0},"charged_credits":{"type":"integer","title":"Charged Credits","default":0}},"type":"object","title":"ContinueLeadSearchExhaustedResponse"},"ContinueLeadSearchRequest":{"properties":{"requested_count":{"type":"integer","minimum":1.0,"title":"Requested Count"},"idempotency_key":{"type":"string","maxLength":180,"minLength":1,"title":"Idempotency Key"}},"additionalProperties":false,"type":"object","required":["requested_count","idempotency_key"],"title":"ContinueLeadSearchRequest"},"ConversationListResponse":{"properties":{"conversations":{"items":{"$ref":"#/components/schemas/ConversationSummary"},"type":"array","title":"Conversations"}},"type":"object","required":["conversations"],"title":"ConversationListResponse"},"ConversationSummary":{"properties":{"id":{"type":"string","title":"Id"},"thread_id":{"type":"string","title":"Thread Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"}},"type":"object","required":["id","thread_id","title","created_at","updated_at"],"title":"ConversationSummary"},"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"},"CreateDatasetSubsetRequest":{"properties":{"row_generation_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":5000,"minItems":1,"title":"Row Generation Ids"},"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"}},"additionalProperties":false,"type":"object","required":["row_generation_ids","name"],"title":"CreateDatasetSubsetRequest","description":"Exact stable rows to snapshot into a new dataset."},"CreateDatasetSubsetResponse":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"},"name":{"type":"string","title":"Name"},"row_count":{"type":"integer","title":"Row Count"}},"type":"object","required":["dataset_id","name","row_count"],"title":"CreateDatasetSubsetResponse","description":"New dataset created from the stable-row selection."},"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."},"CreditTransactionListResponse":{"properties":{"transactions":{"items":{"$ref":"#/components/schemas/CreditTransactionResponse"},"type":"array","title":"Transactions"},"pagination":{"$ref":"#/components/schemas/CreditTransactionPagination"}},"type":"object","required":["transactions","pagination"],"title":"CreditTransactionListResponse","description":"Paginated public credit transaction response."},"CreditTransactionPagination":{"properties":{"total":{"type":"integer","title":"Total"},"limit":{"type":"integer","title":"Limit"},"offset":{"type":"integer","title":"Offset"},"has_more":{"type":"boolean","title":"Has More"}},"type":"object","required":["total","limit","offset","has_more"],"title":"CreditTransactionPagination","description":"Offset pagination metadata for credit transactions."},"CreditTransactionResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"operation_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Operation Type"},"credits_amount":{"type":"integer","title":"Credits Amount"},"credits_after":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Credits After"},"notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Session Id"}},"type":"object","required":["id","created_at","operation_type","credits_amount","credits_after"],"title":"CreditTransactionResponse","description":"Public credit transaction fields."},"DatasetContactPreviewRequest":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id","description":"Dataset UUID owned by the authenticated user"}},"type":"object","required":["dataset_id"],"title":"DatasetContactPreviewRequest"},"DatasetMethodCreditEstimate":{"properties":{"find":{"type":"integer","minimum":0.0,"title":"Find"},"verify":{"type":"integer","minimum":0.0,"title":"Verify"}},"type":"object","required":["find","verify"],"title":"DatasetMethodCreditEstimate"},"DatasetMethodExecuteRequest":{"properties":{"force_find":{"type":"boolean","title":"Force Find","default":false},"method_override":{"anyOf":[{"type":"string","enum":["person","company"]},{"type":"null"}],"title":"Method Override"},"find_on_invalid":{"type":"boolean","title":"Find On Invalid","default":true},"estimated_credits":{"anyOf":[{"$ref":"#/components/schemas/DatasetMethodCreditEstimate"},{"type":"null"}]},"client_estimated_credits":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Client Estimated Credits"}},"type":"object","title":"DatasetMethodExecuteRequest"},"DatasetMethodPlanRequest":{"properties":{"force_find":{"type":"boolean","title":"Force Find","default":false},"method_override":{"anyOf":[{"type":"string","enum":["person","company"]},{"type":"null"}],"title":"Method Override"},"find_on_invalid":{"type":"boolean","title":"Find On Invalid","default":true}},"type":"object","title":"DatasetMethodPlanRequest"},"DatasetRowUsageRequest":{"properties":{"row_generation_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":5000,"minItems":1,"title":"Row Generation Ids"}},"additionalProperties":false,"type":"object","required":["row_generation_ids"],"title":"DatasetRowUsageRequest","description":"Stable source rows whose copied destinations should be returned."},"DatasetRowUsageResponse":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"},"usage":{"additionalProperties":{"items":{"$ref":"#/components/schemas/RowUsageDestination"},"type":"array"},"propertyNames":{"format":"uuid"},"type":"object","title":"Usage"}},"type":"object","required":["dataset_id","usage"],"title":"DatasetRowUsageResponse","description":"Copied destinations keyed by source row_generation_id."},"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)"},"source_category":{"type":"string","enum":["lead_finder","file_upload","api","manual","internal","other"],"title":"Source Category","description":"Canonical dataset source category"},"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","source_category","row_count","created_at","updated_at"],"title":"DatasetWithLatestSession"},"DefaultConnectionRequest":{"properties":{"provider_account_id":{"type":"string","minLength":1,"title":"Provider Account Id"}},"type":"object","required":["provider_account_id"],"title":"DefaultConnectionRequest","description":"The provider account that should become the org default."},"DeleteDatasetRowsRequest":{"properties":{"row_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":200,"minItems":1,"title":"Row Ids"}},"type":"object","required":["row_ids"],"title":"DeleteDatasetRowsRequest","description":"Bounded set of opaque stable row IDs to delete atomically."},"DeleteDatasetRowsResponse":{"properties":{"dataset_id":{"type":"string","title":"Dataset Id"},"deleted_count":{"type":"integer","title":"Deleted Count"},"row_count":{"type":"integer","title":"Row Count"}},"type":"object","required":["dataset_id","deleted_count","row_count"],"title":"DeleteDatasetRowsResponse","description":"Result of an atomic dataset-row deletion."},"DiscoveryTargeting":{"properties":{"enforced":{"items":{"type":"string"},"type":"array","title":"Enforced"},"not_enforceable":{"items":{"type":"string"},"type":"array","title":"Not Enforceable"}},"type":"object","required":["enforced","not_enforceable"],"title":"DiscoveryTargeting","description":"Continuous-discovery filters grouped by LinkedIn enforceability."},"DocumentIngestResponse":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"source_kind":{"type":"string","title":"Source Kind"},"chunk_count":{"type":"integer","title":"Chunk Count"},"embedded_count":{"type":"integer","title":"Embedded Count"},"indexing_status":{"type":"string","enum":["indexed","not_relevant","failed","skipped"],"title":"Indexing Status"}},"type":"object","required":["id","title","source_kind","chunk_count","embedded_count","indexing_status"],"title":"DocumentIngestResponse"},"DomainPurchaseRequest":{"properties":{"quote_id":{"type":"string","maxLength":36,"minLength":36,"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","title":"Quote Id"},"client_key":{"type":"string","maxLength":36,"minLength":36,"pattern":"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$","title":"Client Key"}},"type":"object","required":["quote_id","client_key"],"title":"DomainPurchaseRequest","description":"Idempotent purchase request bound to one quote."},"DomainSearchRequest":{"properties":{"domain":{"type":"string","maxLength":255,"minLength":1,"title":"Domain"}},"type":"object","required":["domain"],"title":"DomainSearchRequest","description":"Requested domain name before canonicalization."},"DraftAudienceAdvisory":{"properties":{"code":{"type":"string","title":"Code"},"message":{"type":"string","title":"Message"}},"type":"object","required":["code","message"],"title":"DraftAudienceAdvisory","description":"Channel-specific qualification notice for a selected dataset."},"DraftAudienceRow":{"properties":{"row_index":{"type":"integer","title":"Row Index"},"lead_data":{"additionalProperties":true,"type":"object","title":"Lead Data"}},"type":"object","required":["row_index","lead_data"],"title":"DraftAudienceRow","description":"A selected dataset row shown before campaign launch."},"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."},"EmailFindRequest":{"properties":{"candidates":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"title":"Candidates","description":"Pre-computed candidate list [{email, pattern, confidence}, ...] sorted by confidence desc."},"first_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Last Name"},"domain":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Domain"}},"type":"object","title":"EmailFindRequest","description":"Request body for ``POST /api/x402/v1/email/find``.\n\nAgents either pass pre-computed ``candidates`` or pass ``first_name`` +\n``last_name`` + ``domain`` and we generate canonical candidate patterns."},"EmailFindResponse":{"properties":{"found":{"type":"boolean","title":"Found"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"pattern":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pattern"},"result":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Result"},"is_catch_all":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Catch All"},"backend":{"type":"string","title":"Backend"}},"type":"object","required":["found","backend"],"title":"EmailFindResponse"},"EmailValidateRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email","description":"Email address to validate"}},"type":"object","required":["email"],"title":"EmailValidateRequest"},"EmailValidateResponse":{"properties":{"email":{"type":"string","title":"Email"},"normalized":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Normalized"},"valid_format":{"type":"boolean","title":"Valid Format"},"has_mx":{"type":"boolean","title":"Has Mx"},"is_disposable":{"type":"boolean","title":"Is Disposable"},"is_role":{"type":"boolean","title":"Is Role"},"risk_level":{"type":"string","title":"Risk Level"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"backend":{"type":"string","title":"Backend"}},"type":"object","required":["email","valid_format","has_mx","is_disposable","is_role","risk_level","backend"],"title":"EmailValidateResponse"},"EmailVerifyRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email","description":"Email address to SMTP-verify"}},"type":"object","required":["email"],"title":"EmailVerifyRequest","description":"Request body for ``POST /api/x402/v1/email/verify``."},"EmailVerifyResponse":{"properties":{"email":{"type":"string","title":"Email"},"result":{"type":"string","title":"Result"},"is_catch_all":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Catch All"},"backend":{"type":"string","title":"Backend"}},"type":"object","required":["email","result","backend"],"title":"EmailVerifyResponse","description":"Response body — a stable subset of the underlying SMTP verify result."},"EmbeddingRetryResponse":{"properties":{"retried_count":{"type":"integer","title":"Retried Count"},"ready_count":{"type":"integer","title":"Ready Count"},"failed_count":{"type":"integer","title":"Failed Count"}},"type":"object","required":["retried_count","ready_count","failed_count"],"title":"EmbeddingRetryResponse"},"EngagementEvent":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"prospect_identifier":{"type":"string","title":"Prospect Identifier"},"prospect_identifier_type":{"type":"string","enum":["email","linkedin_provider_id","prospect_uuid"],"title":"Prospect Identifier Type"},"channel":{"type":"string","enum":["email","linkedin"],"title":"Channel"},"event_type":{"type":"string","enum":["sent","received","classified","state_transition","suppressed","cross_channel_engagement_detected"],"title":"Event Type"},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id"},"campaign_lead_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Lead Id"},"classification_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Classification Id"},"raw_event_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Raw Event Id"},"payload_summary":{"additionalProperties":true,"type":"object","title":"Payload Summary"},"occurred_at":{"type":"string","title":"Occurred At"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["id","user_id","prospect_identifier","prospect_identifier_type","channel","event_type","occurred_at","created_at"],"title":"EngagementEvent","description":"Projection of an ``engagement_log`` row for read API consumers."},"EngagementListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/EngagementEvent"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"EngagementListResponse"},"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."},"EnrichmentQuoteRequest":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"},"selection":{"additionalProperties":{"type":"string"},"type":"object","title":"Selection"}},"additionalProperties":false,"type":"object","required":["dataset_id"],"title":"EnrichmentQuoteRequest","description":"A dataset and the cohort actions the caller wants included in the quote."},"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."},"ExecuteLeadSearchInProgressResponse":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id"},"status":{"type":"string","title":"Status","default":"in_progress"},"poll":{"type":"string","title":"Poll"}},"type":"object","required":["run_id","poll"],"title":"ExecuteLeadSearchInProgressResponse"},"ExecuteLeadSearchRequest":{"properties":{"confirmation_id":{"type":"string","format":"uuid","title":"Confirmation Id"}},"additionalProperties":false,"type":"object","required":["confirmation_id"],"title":"ExecuteLeadSearchRequest"},"ExecuteLeadSearchResponse":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id"},"dataset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Dataset Id"},"delivered_count":{"type":"integer","title":"Delivered Count"},"charged_credits":{"type":"integer","title":"Charged Credits"},"deduped_all":{"type":"boolean","title":"Deduped All","default":false}},"type":"object","required":["run_id","dataset_id","delivered_count","charged_credits"],"title":"ExecuteLeadSearchResponse"},"ExistingCopy":{"properties":{"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"body":{"type":"string","title":"Body"}},"type":"object","required":["body"],"title":"ExistingCopy","description":"Existing campaign-step copy that should be critiqued when its body is non-blank."},"ExplicitFindLeadsRequest":{"properties":{"filters":{"$ref":"#/components/schemas/LeadFilters"},"schema_version":{"type":"string","const":"1","title":"Schema Version","default":"1"},"auto_enrich":{"type":"boolean","title":"Auto Enrich","default":true},"target":{"anyOf":[{"type":"string","enum":["people","companies"]},{"type":"null"}],"title":"Target"},"idempotency_key":{"type":"string","maxLength":180,"minLength":1,"title":"Idempotency Key"}},"additionalProperties":false,"type":"object","required":["filters","idempotency_key"],"title":"ExplicitFindLeadsRequest"},"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."},"FindLeadsCompletedResponse":{"additionalProperties":true,"type":"object"},"FindLeadsInProgressResponse":{"additionalProperties":true,"type":"object"},"Finding":{"properties":{"dimension":{"type":"string","enum":["hook","legitimacy","offer","cta","style","deliverability"],"title":"Dimension"},"severity":{"type":"string","enum":["high","medium","low"],"title":"Severity"},"issue":{"type":"string","minLength":1,"title":"Issue"},"suggestion":{"type":"string","minLength":1,"title":"Suggestion"},"excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Excerpt"}},"type":"object","required":["dimension","severity","issue","suggestion"],"title":"Finding","description":"One actionable problem found in supplied outreach copy."},"FirstLookAccepted":{"properties":{"look_id":{"type":"string","title":"Look Id"},"status":{"type":"string","enum":["running","done"],"title":"Status"},"stage":{"type":"string","title":"Stage"}},"additionalProperties":false,"type":"object","required":["look_id","status","stage"],"title":"FirstLookAccepted","description":"Accepted or cache-hit first-look response."},"FirstLookRequest":{"properties":{"website":{"type":"string","maxLength":253,"minLength":4,"title":"Website"}},"additionalProperties":false,"type":"object","required":["website"],"title":"FirstLookRequest","description":"Strict public first-look request."},"FirstLookResponse":{"properties":{"look_id":{"type":"string","title":"Look Id"},"status":{"type":"string","enum":["running","done","failed"],"title":"Status"},"stage":{"type":"string","title":"Stage"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"sells":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sells"},"sells_to":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sells To"},"hq_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hq Location"},"leads":{"items":{"$ref":"#/components/schemas/PublicFirstLookLead"},"type":"array","title":"Leads"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"}},"additionalProperties":false,"type":"object","required":["look_id","status","stage"],"title":"FirstLookResponse","description":"Poll response with no provider identity or contact fields."},"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"},"GitHubIngestRequest":{"properties":{"repos":{"items":{"type":"string"},"type":"array","maxItems":10,"minItems":1,"title":"Repos"}},"type":"object","required":["repos"],"title":"GitHubIngestRequest"},"GitHubInstallUrlResponse":{"properties":{"install_url":{"type":"string","title":"Install Url"}},"type":"object","required":["install_url"],"title":"GitHubInstallUrlResponse"},"GitHubSourceUpsertRequest":{"properties":{"installation_id":{"type":"string","maxLength":80,"minLength":1,"title":"Installation Id"},"repositories":{"items":{"type":"string"},"type":"array","maxItems":20,"minItems":1,"title":"Repositories"},"enabled":{"type":"boolean","title":"Enabled","default":true}},"type":"object","required":["installation_id","repositories"],"title":"GitHubSourceUpsertRequest"},"GitHubTokenRequest":{"properties":{"token":{"type":"string","maxLength":1024,"minLength":1,"title":"Token"}},"type":"object","required":["token"],"title":"GitHubTokenRequest"},"GitHubTokenStatusResponse":{"properties":{"connected":{"type":"boolean","title":"Connected"},"account_login":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Login"}},"type":"object","required":["connected"],"title":"GitHubTokenStatusResponse"},"GoogleDriveIngestRequest":{"properties":{"file_ids":{"items":{"type":"string"},"type":"array","maxItems":25,"minItems":1,"title":"File Ids"}},"type":"object","required":["file_ids"],"title":"GoogleDriveIngestRequest"},"GoogleDriveIngestResponse":{"properties":{"ingested":{"type":"integer","title":"Ingested"},"updated":{"type":"integer","title":"Updated"},"unchanged":{"type":"integer","title":"Unchanged"},"skipped":{"items":{"$ref":"#/components/schemas/SkippedDocumentResponse"},"type":"array","title":"Skipped"},"documents":{"items":{"$ref":"#/components/schemas/ConnectorDocumentIngestResponse"},"type":"array","title":"Documents"}},"type":"object","required":["ingested","updated","unchanged","skipped","documents"],"title":"GoogleDriveIngestResponse"},"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"},"ImplicitFindLeadsRequest":{"properties":{"query":{"type":"string","maxLength":1000,"minLength":1,"title":"Query"},"count":{"anyOf":[{"type":"integer","maximum":500.0,"minimum":1.0},{"type":"null"}],"title":"Count"},"auto_enrich":{"type":"boolean","title":"Auto Enrich","default":true},"target":{"anyOf":[{"type":"string","enum":["people","companies"]},{"type":"null"}],"title":"Target"},"idempotency_key":{"type":"string","maxLength":180,"minLength":1,"title":"Idempotency Key"}},"additionalProperties":false,"type":"object","required":["query","idempotency_key"],"title":"ImplicitFindLeadsRequest"},"InboxActionEligibility":{"properties":{"can_reply":{"type":"boolean","title":"Can Reply"},"reason":{"anyOf":[{"type":"string","enum":["suppressed","opted_out","eligibility_unavailable"]},{"type":"null"}],"title":"Reason"},"suppressed":{"type":"boolean","title":"Suppressed"},"casl_status":{"type":"string","enum":["not_required","ready","missing_identity","unavailable"],"title":"Casl Status"}},"type":"object","required":["can_reply","reason","suppressed","casl_status"],"title":"InboxActionEligibility"},"InboxCounterpart":{"properties":{"name":{"type":"string","title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"linkedin_provider_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Provider Id"}},"type":"object","required":["name"],"title":"InboxCounterpart"},"InboxItem":{"properties":{"thread_id":{"type":"string","title":"Thread Id"},"channel":{"type":"string","enum":["email","linkedin"],"title":"Channel"},"counterpart":{"$ref":"#/components/schemas/InboxCounterpart"},"last_message":{"$ref":"#/components/schemas/InboxLastMessage"},"campaign_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Id"},"campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Name"},"lead_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lead Id"},"intent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Intent"},"sentiment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sentiment"},"followup_scheduled":{"type":"boolean","title":"Followup Scheduled","default":false},"action_eligibility":{"$ref":"#/components/schemas/InboxActionEligibility"}},"type":"object","required":["thread_id","channel","counterpart","last_message","action_eligibility"],"title":"InboxItem"},"InboxLastMessage":{"properties":{"at":{"type":"string","title":"At"},"dir":{"type":"string","enum":["inbound","outbound","unknown"],"title":"Dir"},"snippet":{"type":"string","title":"Snippet"}},"type":"object","required":["at","dir","snippet"],"title":"InboxLastMessage"},"InboxListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/InboxItem"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Opaque resume cursor. Each source advances only after its pending items are emitted."},"degraded_sources":{"items":{"type":"string"},"type":"array","title":"Degraded Sources","description":"Providers or enrichment layers that failed while this partial page was built."},"visibility":{"$ref":"#/components/schemas/InboxVisibility","description":"The intentionally asymmetric ownership scope of each upstream source."},"window_days":{"type":"integer","const":30,"title":"Window Days","description":"Fixed recent-view window anchored when the first page is requested.","default":30}},"type":"object","required":["items"],"title":"InboxListResponse","description":"A 30-day snapshot page; unread state is deliberately absent in v1."},"InboxVisibility":{"properties":{"email":{"type":"string","const":"actor_scoped","title":"Email","description":"BaviMail rows visible through the authenticated actor's API key.","default":"actor_scoped"},"linkedin":{"type":"string","const":"org_scoped","title":"Linkedin","description":"Conversations visible through the org's selected LinkedIn account.","default":"org_scoped"}},"type":"object","title":"InboxVisibility"},"IntegerRange":{"properties":{"minimum":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Minimum"},"maximum":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Maximum"}},"additionalProperties":false,"type":"object","title":"IntegerRange"},"IntegrationRequestCreate":{"properties":{"provider_slug":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Provider Slug"},"provider_name":{"type":"string","maxLength":200,"minLength":1,"title":"Provider Name"},"note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Note"}},"type":"object","required":["provider_name"],"title":"IntegrationRequestCreate"},"IntegrationRequestResponse":{"properties":{"id":{"type":"string","title":"Id"},"provider_name":{"type":"string","title":"Provider Name"},"status":{"type":"string","title":"Status"}},"type":"object","required":["id","provider_name","status"],"title":"IntegrationRequestResponse"},"InviteCreateRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email","description":"Invitee email (normalized to lowercase server-side)"}},"type":"object","required":["email"],"title":"InviteCreateRequest","description":"Body for POST /api/v1/orgs/invites."},"InviteResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"org_id":{"type":"string","format":"uuid","title":"Org Id"},"email":{"type":"string","title":"Email"},"status":{"type":"string","title":"Status"},"token":{"type":"string","title":"Token"},"accept_url":{"type":"string","title":"Accept Url"},"invited_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Invited By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["id","org_id","email","status","token","accept_url","created_at","expires_at"],"title":"InviteResponse","description":"A single org invite. ``token`` / ``accept_url`` are returned to the caller in\nF1 (no email delivery yet); F2/F3 wire actual accept-link delivery."},"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"},"skipped_by_reason":{"additionalProperties":{"type":"integer"},"type":"object","title":"Skipped By Reason"},"verified_rows":{"type":"integer","title":"Verified Rows","default":0},"force_enrolled_rows":{"type":"integer","title":"Force Enrolled Rows","default":0}},"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"},"lead_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lead Name"}},"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","unresolved_template_fields","previously_contacted","pending_invite","provider_resolution_partial","provider_temporarily_unavailable","autumn_quota_exceeded","autumn_preflight_unavailable","autumn_customer_unmapped","autumn_db_unavailable","autumn_auth_failed","autumn_malformed_response","autumn_di_misconfigured","autumn_linkedin_slot_exceeded","autumn_linkedin_slot_unavailable","autumn_outbound_emails_exceeded","autumn_linkedin_dms_exceeded"],"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."},"LeadFilterEnvelope":{"additionalProperties":true,"type":"object"},"LeadFilters":{"properties":{"count":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/ScalarNumericFilter-Input"},{"$ref":"#/components/schemas/BetweenNumericFilter-Input"}],"discriminator":{"propertyName":"operator","mapping":{"between":"#/components/schemas/BetweenNumericFilter-Input","eq":"#/components/schemas/ScalarNumericFilter-Input","gt":"#/components/schemas/ScalarNumericFilter-Input","gte":"#/components/schemas/ScalarNumericFilter-Input","lt":"#/components/schemas/ScalarNumericFilter-Input","lte":"#/components/schemas/ScalarNumericFilter-Input"}}},{"type":"null"}],"title":"Count"},"title":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Title"},"schools":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Schools"},"industry":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Industry"},"categories":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}]},"location":{"anyOf":[{"type":"string","maxLength":240,"minLength":1},{"type":"null"}],"title":"Location"},"radius":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Radius"},"radius_unit":{"anyOf":[{"type":"string","enum":["mi","km"]},{"type":"null"}],"title":"Radius Unit"},"company":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Company"},"domain":{"anyOf":[{"type":"string","maxLength":253,"minLength":1},{"type":"null"}],"title":"Domain"},"keywords":{"anyOf":[{"type":"string","maxLength":240,"minLength":1},{"type":"null"}],"title":"Keywords"},"seniority":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Seniority"},"annual_revenue":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/ScalarRevenueFilter-Input"},{"$ref":"#/components/schemas/BetweenRevenueFilter"}],"discriminator":{"propertyName":"operator","mapping":{"between":"#/components/schemas/BetweenRevenueFilter","eq":"#/components/schemas/ScalarRevenueFilter-Input","gt":"#/components/schemas/ScalarRevenueFilter-Input","gte":"#/components/schemas/ScalarRevenueFilter-Input","lt":"#/components/schemas/ScalarRevenueFilter-Input","lte":"#/components/schemas/ScalarRevenueFilter-Input"}}},{"type":"null"}],"title":"Annual Revenue"},"headcount":{"anyOf":[{"oneOf":[{"$ref":"#/components/schemas/ScalarNumericFilter-Input"},{"$ref":"#/components/schemas/BetweenNumericFilter-Input"}],"discriminator":{"propertyName":"operator","mapping":{"between":"#/components/schemas/BetweenNumericFilter-Input","eq":"#/components/schemas/ScalarNumericFilter-Input","gt":"#/components/schemas/ScalarNumericFilter-Input","gte":"#/components/schemas/ScalarNumericFilter-Input","lt":"#/components/schemas/ScalarNumericFilter-Input","lte":"#/components/schemas/ScalarNumericFilter-Input"}}},{"type":"null"}],"title":"Headcount"}},"additionalProperties":false,"type":"object","title":"LeadFilters","description":"Closed v1 parsed form shared by parse and execution."},"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"},"LeadMessage":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id","description":"Outbound job ID (stable, deep-linkable)"},"step":{"type":"integer","title":"Step","description":"1-indexed sequence step"},"variant_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Label","description":"A/B variant label"},"alias_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Alias Id","description":"Sending alias ID"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject","description":"Rendered subject (null if not yet generated)"},"body_html":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Html","description":"Rendered HTML body when the stored body is HTML. UNSANITIZED stored email HTML interpolating lead/LLM-generated data — clients MUST sanitize (e.g. DOMPurify) before rendering. Never inject as raw HTML."},"body_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Text","description":"Plain-text body, when the stored body is plain"},"sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sent At","description":"Claim time (immediately before send, ±worker latency); populated only for terminal-sent statuses, null otherwise (incl. legacy sent rows with no claim timestamp). NOT enrolment time."},"message_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message Id","description":"BaviMail email ID (provider message id)"},"status":{"type":"string","title":"Status","description":"Raw outbound_jobs.status (13 possible: queued, claimed, claimed_stranded, generating, sending, sent, scheduled, cancelled, failed, bounced, complained, delivered, skipped). Clients MUST render unknown values safely — the set may grow."}},"type":"object","required":["job_id","step","status"],"title":"LeadMessage","description":"A single sent (or pending) email for a campaign lead.\n\nSourced from `outbound_jobs.content` (JSONB written by the send worker).\nRows that have not reached send (queued/scheduled/claimed/generating) are\nincluded with `subject`/`body_*` null so the same UI drawer can preview\nupcoming steps. `status` is the raw `outbound_jobs.status` value (a wider\nset than `OutboundJobStatus`, e.g. `claimed`/`skipped`), passed through\nverbatim rather than coerced so the contract never crashes on a new state."},"LeadMessagesResponse":{"properties":{"messages":{"items":{"$ref":"#/components/schemas/LeadMessage"},"type":"array","title":"Messages","description":"Messages ordered by step"},"total":{"type":"integer","title":"Total","description":"Number of messages returned"}},"type":"object","required":["messages","total"],"title":"LeadMessagesResponse","description":"Per-step sent/pending email content for one campaign lead, step asc."},"LeadSearchPlan":{"properties":{"requested_count":{"type":"integer","minimum":1.0,"title":"Requested Count","default":3},"natural_language_query":{"type":"string","maxLength":500,"minLength":1,"title":"Natural Language Query","description":"Complete self-contained semantic search request passed to the provider. Copy an initial self-contained request unchanged; after a follow-up tweak, rewrite the full resolved request rather than passing only the conversational delta."},"person":{"$ref":"#/components/schemas/PersonCriteria"},"company":{"$ref":"#/components/schemas/CompanyCriteria"},"required_output_fields":{"items":{"type":"string","enum":["full_name","title","company_name","company_domain","linkedin_url","employee_count","employee_range","funding_stage","industry"]},"type":"array","title":"Required Output Fields","description":"Fields requested for the customer-visible result. Provider discovery rows may render a missing optional field as unavailable; cache reuse still requires fresh evidence for requested fields. Prefer employee_count over employee_range when exact count is available.","default":["full_name","title","company_name","company_domain","linkedin_url"]},"unresolved_constraints":{"items":{"type":"string"},"type":"array","title":"Unresolved Constraints","default":[]}},"additionalProperties":false,"type":"object","required":["natural_language_query"],"title":"LeadSearchPlan","description":"Stable tool boundary between Bavi's model and search providers."},"LeadSearchRunStatusResponse":{"properties":{"run_id":{"type":"string","format":"uuid","title":"Run Id"},"status":{"type":"string","title":"Status"},"dataset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Dataset Id"},"requested_count":{"type":"integer","title":"Requested Count"},"delivered_count":{"type":"integer","title":"Delivered Count"},"charged_credits":{"type":"integer","title":"Charged Credits"},"deduped_all":{"type":"boolean","title":"Deduped All","default":false},"plan":{"$ref":"#/components/schemas/LeadSearchPlan"}},"type":"object","required":["run_id","status","dataset_id","requested_count","delivered_count","charged_credits","plan"],"title":"LeadSearchRunStatusResponse"},"LeadTimelineResponse":{"properties":{"events":{"items":{"$ref":"#/components/schemas/CampaignTimelineEvent"},"type":"array","title":"Events"},"total":{"type":"integer","title":"Total"},"degraded":{"type":"boolean","title":"Degraded","default":false}},"type":"object","required":["events","total"],"title":"LeadTimelineResponse","description":"Per-lead timeline (A4a). `degraded` is true when BaviMail enrichment was\nunavailable and only local events are shown."},"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."},"LinkedInConversationReplyRequest":{"properties":{"text":{"type":"string","maxLength":8000,"minLength":1,"title":"Text"}},"type":"object","required":["text"],"title":"LinkedInConversationReplyRequest","description":"Reply into an EXISTING LinkedIn chat from the inbox.\n\nDeliberately narrower than ``LinkedInMessageRequest``: no ``account_id``,\nno ``provider_id``, no ``identifier``. The account is resolved server-side\nfrom the caller's org and the chat is authorised against it, so a client\ncannot name the sending account or open a new conversation with someone who\nhas not written to us. Replying to an existing thread is the one LinkedIn\nwrite that is safe to expose in production."},"LinkedInFindUrlRequest":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name","description":"Full name of the person"},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company","description":"Optional company or organization name"},"location":{"type":"string","maxLength":2,"minLength":2,"title":"Location","description":"Two-letter ASCII country code used to bias the search region","default":"us"}},"type":"object","required":["name"],"title":"LinkedInFindUrlRequest","description":"Request body for ``POST /api/x402/v1/linkedin/find-url``."},"LinkedInFindUrlResponse":{"properties":{"status":{"type":"string","title":"Status"},"query":{"type":"string","title":"Query"},"linkedin_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Url"},"profiles":{"items":{"$ref":"#/components/schemas/LinkedInProfile"},"type":"array","title":"Profiles"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["status","query"],"title":"LinkedInFindUrlResponse"},"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":[]},"media_asset_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Media Asset Id"},"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"},"LinkedInProfile":{"properties":{"url":{"type":"string","title":"Url"},"title":{"type":"string","title":"Title","default":""},"snippet":{"type":"string","title":"Snippet","default":""},"match_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Match Confidence"},"match_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Match Reason"}},"type":"object","required":["url"],"title":"LinkedInProfile"},"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"},"LinkedInReadPageResponse":{"properties":{"items":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"LinkedInReadPageResponse"},"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"},"LiveFindRequest":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Name"},"domain":{"anyOf":[{"type":"string","maxLength":253},{"type":"null"}],"title":"Domain"},"company":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Company"},"linkedin_url":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Linkedin Url"},"budget_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Budget Seconds"}},"type":"object","title":"LiveFindRequest","description":"One live email lookup in either direct or LinkedIn form."},"MailboxTestSendRequest":{"properties":{"provider":{"type":"string","title":"Provider"},"account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account"}},"type":"object","required":["provider"],"title":"MailboxTestSendRequest","description":"Body for POST /mailbox/test-send: which connected mailbox to prove."},"MailboxTestSendResponse":{"properties":{"ok":{"type":"boolean","title":"Ok"},"provider":{"type":"string","title":"Provider"},"account":{"type":"string","title":"Account"},"outcome":{"type":"string","title":"Outcome"},"message_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message Id"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"}},"type":"object","required":["ok","provider","account","outcome"],"title":"MailboxTestSendResponse","description":"The transport outcome of a send-to-self connection test."},"MediaAssetResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"size_bytes":{"type":"integer","title":"Size Bytes"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","size_bytes","created_at"],"title":"MediaAssetResponse","description":"Safe metadata for a single media asset (upload + get responses)."},"MediaAssetWithUrlResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"size_bytes":{"type":"integer","title":"Size Bytes"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"signed_url":{"type":"string","title":"Signed Url"}},"type":"object","required":["id","size_bytes","created_at","signed_url"],"title":"MediaAssetWithUrlResponse","description":"Media asset metadata plus a short-lived signed URL (GET {id})."},"MediaBatchRequest":{"properties":{"media_asset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"title":"Media Asset Ids"}},"type":"object","required":["media_asset_ids"],"title":"MediaBatchRequest","description":"Ordered media IDs needed to render one Inbox or calendar page."},"MediaBatchResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/MediaListItem"},"type":"array","title":"Items"}},"type":"object","required":["items"],"title":"MediaBatchResponse","description":"Owned assets in stable first-request order; missing IDs are omitted."},"MediaListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"size_bytes":{"type":"integer","title":"Size Bytes"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"signed_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Signed Url"}},"type":"object","required":["id","size_bytes","created_at"],"title":"MediaListItem","description":"A list-row projection: safe metadata + a short-lived signed URL.\n\n``signed_url`` is nullable: a row whose blob is gone or whose sign call\ntransiently failed still lists (the FE refetches on a broken ``<img>``)."},"MediaListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/MediaListItem"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"MediaListResponse","description":"Keyset-paginated page of media assets."},"MediaQuotaResponse":{"properties":{"used_bytes":{"type":"integer","title":"Used Bytes"},"cap_bytes":{"type":"integer","title":"Cap Bytes"},"count":{"type":"integer","title":"Count"},"image_cap":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Image Cap"}},"type":"object","required":["used_bytes","cap_bytes","count"],"title":"MediaQuotaResponse","description":"Org media usage for the dashboard quota indicator."},"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"},"NewsletterSubscribeRequest":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},"type":"object","required":["email"],"title":"NewsletterSubscribeRequest","description":"Public newsletter subscription request."},"NewsletterSubscribeResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"NewsletterSubscribeResponse","description":"Enumeration-safe newsletter subscription response."},"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},"forward_replies_enabled":{"type":"boolean","title":"Forward Replies Enabled","default":false},"forward_to_email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Forward To Email"},"review_queue_email_digest":{"type":"string","enum":["disabled","realtime","hourly","daily"],"title":"Review Queue Email Digest","default":"daily"}},"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"},"forward_replies_enabled":{"type":"boolean","title":"Forward Replies Enabled","default":false},"forward_to_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Forward To Email"},"review_queue_email_digest":{"type":"string","enum":["disabled","realtime","hourly","daily"],"title":"Review Queue Email Digest","default":"daily"}},"type":"object","required":["email_enabled","whatsapp_enabled","notify_on_reply","notify_on_bounce","notify_on_complaint"],"title":"NotificationPreferencesResponse"},"NumericBetweenValue":{"properties":{"min":{"type":"string","title":"Min"},"max":{"type":"string","title":"Max"}},"additionalProperties":false,"type":"object","required":["min","max"],"title":"NumericBetweenValue"},"OrgComplianceResponse":{"properties":{"compliance_legal_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Compliance Legal Name"},"compliance_mailing_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Compliance Mailing Address"},"force_compliance":{"type":"boolean","title":"Force Compliance","default":false},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},"type":"object","title":"OrgComplianceResponse","description":"The org's CASL compliance identity + reseller override (read model).\n\nMirrors what the frontend reads: legal name, mailing address, the read-only\n``force_compliance`` flag, and the org display name. Unset fields are returned\nas null (the frontend coerces to \"\")."},"OrgComplianceUpdateRequest":{"properties":{"compliance_legal_name":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Compliance Legal Name"},"compliance_mailing_address":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Compliance Mailing Address"}},"type":"object","title":"OrgComplianceUpdateRequest","description":"Body for PUT /api/v1/orgs/compliance.\n\nONLY the sender identity + address are user-settable. ``force_compliance`` is a\nreseller/operator control and is intentionally absent — a client that sends it\nhas it ignored (extra fields dropped), never written. Both fields are trimmed;\na blank value clears the field (stored as NULL)."},"OrgMember":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"role":{"type":"string","title":"Role"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["user_id","role"],"title":"OrgMember","description":"A resolved org member (organization_members row joined to auth.users)."},"OrgMembersResponse":{"properties":{"org_id":{"type":"string","format":"uuid","title":"Org Id"},"members":{"items":{"$ref":"#/components/schemas/OrgMember"},"type":"array","title":"Members"},"pending_invites":{"items":{"$ref":"#/components/schemas/PendingInvite"},"type":"array","title":"Pending Invites"}},"type":"object","required":["org_id","members","pending_invites"],"title":"OrgMembersResponse","description":"Roster for GET /api/v1/orgs/members: members + pending invites, org-scoped."},"ParseLeadRequest":{"properties":{"text":{"type":"string","maxLength":1000,"minLength":1,"title":"Text"},"schema_version":{"type":"string","const":"1","title":"Schema Version","default":"1"}},"additionalProperties":false,"type":"object","required":["text"],"title":"ParseLeadRequest"},"ParseLeadSearchRequest":{"properties":{"query":{"type":"string","maxLength":500,"minLength":1,"title":"Query"},"requested_count":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Requested Count"}},"additionalProperties":false,"type":"object","required":["query"],"title":"ParseLeadSearchRequest"},"ParseLeadSearchResponse":{"properties":{"plan":{"$ref":"#/components/schemas/LeadSearchPlan"},"unresolved_constraints":{"items":{"type":"string"},"type":"array","title":"Unresolved Constraints"},"server_max_requested_count":{"type":"integer","title":"Server Max Requested Count"}},"type":"object","required":["plan","unresolved_constraints","server_max_requested_count"],"title":"ParseLeadSearchResponse"},"PendingInvite":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","title":"Email"},"status":{"type":"string","title":"Status"},"invited_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Invited By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["id","email","status","created_at","expires_at"],"title":"PendingInvite","description":"A pending invite as surfaced in the members roster (no token exposed here —\nthe token is only returned at create time)."},"PersonCriteria":{"properties":{"titles":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Current-role nouns/titles such as founder, co-founder, CEO, freelancer, publisher, editor, journalist, or VP Sales. Use match=any for alternatives. Use singular provider labels (founders becomes founder). Hard-filter only titles the user stated; the semantic query handles synonyms."},"schools":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Free-text university, college, or school names stated by the user."},"seniorities":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Provider-supported current-role seniority labels only."},"keywords":{"anyOf":[{"$ref":"#/components/schemas/TextCriterion"},{"type":"null"}],"description":"Observable fuzzy concepts that describe the person's public profile/headline, not their employer or unobservable private behavior."},"locations":{"anyOf":[{"items":{"$ref":"#/components/schemas/PersonLocation"},"type":"array","maxItems":20,"minItems":1},{"type":"null"}],"title":"Locations","description":"Structured places where the person may be based. Each item is one alternative, and every populated city, region/state, and country component in that item must match. Never use this for company headquarters and never put prose in a component."}},"additionalProperties":false,"type":"object","title":"PersonCriteria"},"PersonLocation":{"properties":{"city":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"City"},"region":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Region","description":"Full region/state name, not an abbreviation inferred from prose."},"country":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Country","description":"Full country name preferred (for example, United Kingdom rather than UK)."},"radius":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Radius","description":"Optional search radius around the location; requires city or region."},"radius_unit":{"anyOf":[{"type":"string","enum":["mi","km"]},{"type":"null"}],"title":"Radius Unit","description":"Unit for the optional search radius; required whenever radius is present."}},"additionalProperties":false,"type":"object","title":"PersonLocation"},"PersonVoiceDeriveResponse":{"properties":{"voice":{"$ref":"#/components/schemas/PersonVoiceResponse"},"skipped_user_edited":{"type":"boolean","title":"Skipped User Edited","default":false},"linkedin_arm_status":{"type":"string","title":"Linkedin Arm Status"},"linkedin_arm_detail":{"type":"string","title":"Linkedin Arm Detail","default":""},"x_arm_status":{"type":"string","title":"X Arm Status"},"x_arm_detail":{"type":"string","title":"X Arm Detail","default":""}},"type":"object","required":["voice","linkedin_arm_status","x_arm_status"],"title":"PersonVoiceDeriveResponse","description":"Result of the auto-derive-and-save (POST). ``voice`` is the persisted row (or, on\na no-clobber skip, the EXISTING user-edited row). ``skipped_user_edited`` is true when\na normal call left a manually-edited voice untouched. The per-arm status echoes the\nRICH X status (derived / no_connection / needs_reauth / empty_timeline / unavailable)\n+ the collapsed LinkedIn status (ok / absent / error) so the FE keeps the nuance even\nthough the persisted column stores the mapped CHECK value."},"PersonVoiceResponse":{"properties":{"tone":{"type":"string","title":"Tone","default":""},"style":{"type":"string","title":"Style","default":""},"topics":{"items":{"type":"string"},"type":"array","title":"Topics"},"do_guidelines":{"items":{"type":"string"},"type":"array","title":"Do Guidelines"},"dont_guidelines":{"items":{"type":"string"},"type":"array","title":"Dont Guidelines"},"sample_snippets":{"items":{"type":"string"},"type":"array","title":"Sample Snippets"},"linkedin_arm_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Arm Status"},"linkedin_arm_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Linkedin Arm Detail"},"x_arm_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X Arm Status"},"x_arm_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X Arm Detail"},"derived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Derived At"},"manually_edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Manually Edited At"},"derivation_version":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Derivation Version"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","title":"PersonVoiceResponse","description":"The persisted PERSON voice (+ per-arm status + provenance). ``updated_at`` null\nmeans no row yet -- the FE auto-derive-and-saves on first load. The arm-status\ncolumns are the migration-249 CHECK vocabulary ('ok'/'absent'/'error') and may be\nnull until a derive has run; the ``*_arm_detail`` carry the original rich reason."},"PersonVoiceUpdateRequest":{"properties":{"tone":{"type":"string","maxLength":2000,"title":"Tone","default":""},"style":{"type":"string","maxLength":2000,"title":"Style","default":""},"topics":{"items":{"type":"string","maxLength":500},"type":"array","maxItems":25,"title":"Topics"},"do_guidelines":{"items":{"type":"string","maxLength":500},"type":"array","maxItems":25,"title":"Do Guidelines"},"dont_guidelines":{"items":{"type":"string","maxLength":500},"type":"array","maxItems":25,"title":"Dont Guidelines"},"sample_snippets":{"items":{"type":"string","maxLength":1000},"type":"array","maxItems":25,"title":"Sample Snippets"}},"type":"object","title":"PersonVoiceUpdateRequest","description":"Save-edits payload (PUT). ONLY the editable voice fields are declared, so a client\ncan never write arm-status / provenance / internal columns (an undeclared field is\nsilently dropped — critical pattern #58 — and the service additionally allowlists). No\n``positioning`` (company layer). The route stamps ``manually_edited_at`` server-side so\nfuture auto-derives no-clobber the user's edits."},"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."},"sources":{"items":{"$ref":"#/components/schemas/PersonalizationSource"},"type":"array","title":"Sources","description":"Per-URL personalization sources surfaced for the citations panel (plan AC-15). Empty when no research surface was available or when the preview path supplied research_context without a sources array."},"claim_sentences":{"items":{"$ref":"#/components/schemas/ClaimSentence"},"type":"array","title":"Claim Sentences","description":"LLM-emitted factual-claim sentences with their `source_indices` (1-indexed into `sources`) and UTF-16 code-unit offsets into `body_clean` (plan AC-16). Empty list when the LLM emitted no claims or when no sources were available to ground them."},"ungrounded_claim_count":{"type":"integer","minimum":0.0,"title":"Ungrounded Claim Count","description":"Count of `claim_sentences` with empty `source_indices` (plan AC-10a). Used by the frontend to render the ungrounded warning banner.","default":0},"body_clean":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Clean","description":"The LLM plain-text email body verbatim — the same string as `email_body`, surfaced separately so frontends can index `claim_sentences[].body_offset_*` against a stable reference even if `email_body` is later mutated by signature stitching elsewhere in the pipeline (plan AC-12). None on pre-feature responses."}},"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":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"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"},"channel":{"type":"string","title":"Channel","description":"Channel: 'email' (default) or 'linkedin'","default":"email"}},"type":"object","required":["campaign_lead_id","step_index","variant_label","sender_profile_id"],"title":"PersonalizationRequest","description":"Request to personalize content for a campaign lead.\n\nEmail is the default channel (backward-compat). A LinkedIn AI\npersonalization request (epic 2) sets `channel=\"linkedin\"`; for that\nchannel `job_id` is OPTIONAL (synthetic / None — used only for\nmetadata/logging, NEVER for settlement) and the response omits the\nemail-only subject/sender_email/recipient_email fields."},"PersonalizationResponse":{"properties":{"job_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"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":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Personalized Subject","description":"Personalized email subject (email channel only)"},"personalized_body":{"type":"string","title":"Personalized Body","description":"Personalized body"},"sender_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Email","description":"Sender email from profile (email channel only)"},"recipient_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipient Email","description":"Recipient email address (email channel only)"},"credits_consumed":{"type":"integer","title":"Credits Consumed","description":"Credits consumed for personalization"},"all_claims_ungrounded":{"type":"boolean","title":"All Claims Ungrounded","description":"W3-D1: True when the message made factual claims and every one is ungrounded. The Lambda worker's pre-send quality gate treats this as a typed terminal no-send.","default":false}},"type":"object","required":["campaign_lead_id","personalized_body","credits_consumed"],"title":"PersonalizationResponse","description":"Response containing personalized content.\n\nEmail responses carry the full email shape (subject + sender/recipient\nemail). LinkedIn responses OMIT those email-only fields (they are None)\nand return only `personalized_body` + `credits_consumed`\n(+ `all_claims_ungrounded`). The email fields are OPTIONAL so the\nLinkedIn shape validates; an email response is byte-for-byte identical\nto the pre-epic-2 shape because the worker always populates them."},"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"},"PersonalizationSource":{"properties":{"index":{"type":"integer","minimum":0.0,"title":"Index","description":"1-indexed position in the SOURCES block; 0 = not assigned","default":0},"tool_names":{"items":{"type":"string"},"type":"array","title":"Tool Names"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"url_anchor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url Anchor"},"accessed_at":{"type":"string","title":"Accessed At","default":""},"excerpt":{"type":"string","title":"Excerpt","default":""},"status":{"type":"string","title":"Status","default":"success"}},"type":"object","title":"PersonalizationSource","description":"Per-URL source record surfaced on personalization responses.\n\nPlan AC-15. Produced by ``aggregate_research_results`` + ``dedupe_and_cap``\nin PR-1 as a dict; PR-2 lifts the dict into this Pydantic shape on the\n``CommonalityMetadata.sources`` response field.\n\n``tool_names`` is PLURAL because the AC-6 dedup merge rule unions\nper-emission singular ``tool_name`` values across duplicates. ``index``\nis 1-indexed; assigned at LLM-block serialization time (AC-8 ordering:\ndedup -> cap -> THEN index)."},"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"},"step_index":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Step Index","description":"Sequence step these drafts were generated for (shared across all jobs in the batch). Lets the review UI recover the batch's active step server-side after a reload. None when no job carries a step."},"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"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"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"},"sources":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Sources"},"claim_sentences":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Claim Sentences"},"body_clean":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body Clean"},"working_draft":{"anyOf":[{"$ref":"#/components/schemas/WorkingDraftState"},{"type":"null"}],"description":"The reviewer's auto-saved unapproved edit for this lead's step, if any. This is the NON-POLLED full-content channel for the working draft: the 3s status poll only carries has_working_draft + working_draft_updated_at, and the frontend seeds the edited row from this field (delivered once at batch-settle / refresh). None when the reviewer hasn't edited this step."}},"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)."},"lead_display":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Lead Display","description":"Human-readable lead label (full name -> company -> email -> None) resolved from dataset_rows.lead_data, so the review UI can show a name instead of the campaign_lead_id UUID."},"has_working_draft":{"type":"boolean","title":"Has Working Draft","description":"True when an auto-saved in-progress edit exists for this lead's batch step. This is a FLAG only — the polled status endpoint never ships the working-draft subject/body (a full body per lead would bloat the 3s poll to megabytes on large batches). The frontend seeds the actual edited content from the non-polled drafts fetch (GET /playground/drafts), which carries the full working_draft.","default":false},"working_draft_updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Working Draft Updated At","description":"When the working draft was last auto-saved, so the UI can show a freshness hint without shipping the body on the poll. None when no working draft exists for this step."}},"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."},"PlaygroundRegenerateRequest":{"properties":{"step_index":{"type":"integer","maximum":32.0,"minimum":1.0,"title":"Step Index","description":"Campaign step to regenerate a draft for."},"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":"PlaygroundRegenerateRequest","description":"POST /campaigns/{id}/playground/leads/{lead_id}/regenerate body."},"PlaygroundStepPromptResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"step_index":{"type":"integer","title":"Step Index"},"prompt":{"type":"string","title":"Prompt"},"source":{"type":"string","title":"Source"},"variant_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Label"},"sender_profile_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Profile Id"}},"type":"object","required":["campaign_id","step_index","prompt","source"],"title":"PlaygroundStepPromptResponse","description":"Read-only resolved personalization prompt for a step. Returned by\nGET /playground/prompt. Lets the review UI show the prompt in use without\nenqueueing a batch and without being gated behind batch controls."},"PostHogSourceUpsertRequest":{"properties":{"host":{"type":"string","maxLength":200,"minLength":8,"title":"Host","default":"https://us.posthog.com"},"project_id":{"type":"string","maxLength":80,"minLength":1,"title":"Project Id"},"personal_api_key":{"type":"string","maxLength":500,"minLength":8,"title":"Personal Api Key"},"enabled":{"type":"boolean","title":"Enabled","default":true}},"type":"object","required":["project_id","personal_api_key"],"title":"PostHogSourceUpsertRequest"},"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)."},"PreviewLeadSearchRequest":{"properties":{"plan":{"$ref":"#/components/schemas/LeadSearchPlan"},"idempotency_key":{"type":"string","maxLength":180,"minLength":1,"title":"Idempotency Key"}},"additionalProperties":false,"type":"object","required":["plan","idempotency_key"],"title":"PreviewLeadSearchRequest"},"PreviewLeadSearchResponse":{"properties":{"maximum_charge_credits":{"type":"integer","title":"Maximum Charge Credits"},"balance_after":{"type":"integer","title":"Balance After"},"requested_count":{"type":"integer","title":"Requested Count"},"confirmation_id":{"type":"string","format":"uuid","title":"Confirmation Id"},"expires_at":{"type":"string","title":"Expires At"},"plan":{"$ref":"#/components/schemas/LeadSearchPlan"}},"type":"object","required":["maximum_charge_credits","balance_after","requested_count","confirmation_id","expires_at","plan"],"title":"PreviewLeadSearchResponse"},"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."},"Prospect":{"properties":{"id":{"type":"string","title":"Id"},"linkedin_url":{"type":"string","title":"Linkedin Url"},"full_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name"},"headline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Headline"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"company":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"}},"type":"object","required":["id","linkedin_url"],"title":"Prospect"},"ProspectSearchRequest":{"properties":{"tags":{"items":{"type":"string"},"type":"array","maxItems":25,"minItems":1,"title":"Tags","description":"Content tags (overlap match). 1-25 tags, alphanumeric + space/hyphen/underscore, 1-64 chars each."},"limit":{"type":"integer","maximum":100.0,"minimum":1.0,"title":"Limit","default":20}},"type":"object","required":["tags"],"title":"ProspectSearchRequest"},"ProspectSearchResponse":{"properties":{"count":{"type":"integer","title":"Count"},"results":{"items":{"$ref":"#/components/schemas/Prospect"},"type":"array","title":"Results"}},"type":"object","required":["count","results"],"title":"ProspectSearchResponse"},"ProviderRequest":{"properties":{"provider":{"type":"string","maxLength":200,"minLength":1,"title":"Provider"}},"type":"object","required":["provider"],"title":"ProviderRequest"},"PublicFirstLookLead":{"properties":{"full_name":{"type":"string","title":"Full Name"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"company_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Name"},"location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"}},"additionalProperties":false,"type":"object","required":["full_name"],"title":"PublicFirstLookLead","description":"Allowlisted public projection of a lead-search result."},"QueueItemDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"prospect_identifier":{"type":"string","title":"Prospect Identifier"},"prospect_identifier_type":{"type":"string","enum":["email","linkedin_provider_id","prospect_uuid"],"title":"Prospect Identifier Type"},"channel":{"type":"string","enum":["email","linkedin"],"title":"Channel"},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id"},"campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Name"},"campaign_lead_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Lead Id"},"classification_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Classification Id"},"triggering_engagement_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Triggering Engagement Id"},"status":{"type":"string","enum":["pending","resolved","auto_resolved","expired"],"title":"Status"},"resolution_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Action"},"resolution_action_params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Resolution Action Params"},"resolution_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Note"},"resolved_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved By"},"resolved_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved At"},"notes":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Notes"},"created_at":{"type":"string","title":"Created At"},"expires_at":{"type":"string","title":"Expires At"},"reply_classification":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Reply Classification"}},"type":"object","required":["id","user_id","prospect_identifier","prospect_identifier_type","channel","status","created_at","expires_at"],"title":"QueueItemDetail","description":"Detail-view projection: includes the joined classification row."},"QueueItemSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"prospect_identifier":{"type":"string","title":"Prospect Identifier"},"prospect_identifier_type":{"type":"string","enum":["email","linkedin_provider_id","prospect_uuid"],"title":"Prospect Identifier Type"},"channel":{"type":"string","enum":["email","linkedin"],"title":"Channel"},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id"},"campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Name"},"campaign_lead_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Lead Id"},"classification_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Classification Id"},"triggering_engagement_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Triggering Engagement Id"},"status":{"type":"string","enum":["pending","resolved","auto_resolved","expired"],"title":"Status"},"resolution_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Action"},"resolution_action_params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Resolution Action Params"},"resolution_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Note"},"resolved_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved By"},"resolved_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved At"},"notes":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Notes"},"created_at":{"type":"string","title":"Created At"},"expires_at":{"type":"string","title":"Expires At"}},"type":"object","required":["id","user_id","prospect_identifier","prospect_identifier_type","channel","status","created_at","expires_at"],"title":"QueueItemSummary","description":"List-view projection of a ``review_queue_items`` row."},"QueueListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/QueueItemSummary"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"QueueListResponse"},"QueueResolveRequest":{"properties":{"resolution_action":{"type":"string","enum":["continue","stop","stop_and_suppress","reply_manually","pause_n_days","pause_until_date","switch_channel"],"title":"Resolution Action","description":"One of the seven actions from review_queue_items.resolution_action CHECK (migration 149)."},"resolution_action_params":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Resolution Action Params","description":"Per-action params. pause_n_days requires {'days': <positive int>}; pause_until_date requires {'until': <ISO timestamptz>}; other actions ignore."},"resolution_note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Resolution Note","description":"Optional operator note (audit trail)."}},"type":"object","required":["resolution_action"],"title":"QueueResolveRequest","description":"Body for POST /api/v1/queue/{item_id}/resolve."},"QueueResolveResponse":{"properties":{"queue_item_id":{"type":"string","format":"uuid","title":"Queue Item Id"},"resolved":{"type":"boolean","title":"Resolved"},"current_status":{"type":"string","title":"Current Status"},"resolution_action":{"type":"string","title":"Resolution Action"},"suppressed":{"type":"boolean","title":"Suppressed","description":"True only when resolution_action='stop_and_suppress' AND the suppression row was written (or already existed)."}},"type":"object","required":["queue_item_id","resolved","current_status","resolution_action","suppressed"],"title":"QueueResolveResponse","description":"Body for POST /api/v1/queue/{item_id}/resolve happy path."},"QueueStatsResponse":{"properties":{"counts_by_status":{"additionalProperties":{"type":"integer"},"type":"object","title":"Counts By Status"}},"type":"object","required":["counts_by_status"],"title":"QueueStatsResponse"},"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."},"ReconcileResponse":{"properties":{"connected":{"type":"boolean","title":"Connected"},"connection":{"anyOf":[{"$ref":"#/components/schemas/ConnectorConnectionResponse"},{"type":"null"}]}},"type":"object","required":["connected","connection"],"title":"ReconcileResponse"},"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"},"RefreshResponse":{"properties":{"source":{"type":"string","title":"Source"},"mode":{"type":"string","title":"Mode"},"inserted":{"type":"integer","title":"Inserted"},"signals":{"items":{"$ref":"#/components/schemas/SignalResponse"},"type":"array","title":"Signals"}},"type":"object","required":["source","mode","inserted","signals"],"title":"RefreshResponse"},"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."},"RequiredConnectorConfigFieldResponse":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"help":{"type":"string","title":"Help"},"example":{"type":"string","title":"Example"}},"type":"object","required":["key","label","help","example"],"title":"RequiredConnectorConfigFieldResponse"},"RescheduleRequest":{"properties":{"scheduled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Scheduled At"},"local_datetime":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Local Datetime"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"}},"type":"object","title":"RescheduleRequest","description":"Reschedule (calendar drag-drop) a scheduled post to a new instant.\n\nSame two-shape contract as the inbox schedule: an absolute ``scheduled_at`` OR a\nwall-clock ``local_datetime`` + IANA ``timezone`` (DST-gap rejected server-side)."},"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."},"ResolveLegRequest":{"properties":{"leg":{"type":"string","enum":["linkedin","x"],"title":"Leg"},"action":{"type":"string","enum":["retry","cancel"],"title":"Action"}},"type":"object","required":["leg","action"],"title":"ResolveLegRequest","description":"Resolve a leg stuck in ``unknown`` (the dispatcher's never-double-post outcome).\n\n``leg`` = which channel; ``action`` = retry (re-arm the leg for a fresh dispatch) or\ncancel (mark the leg skipped, the user will not retry)."},"RevocationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"org_id":{"type":"string","format":"uuid","title":"Org Id"},"email":{"type":"string","title":"Email"},"status":{"type":"string","title":"Status"}},"type":"object","required":["id","org_id","email","status"],"title":"RevocationResponse","description":"Response for POST /api/v1/orgs/invites/{id}/revoke. TOKEN-FREE on purpose:\nany member can revoke (V1 all-permissions), so echoing the accept token here\nwould be a token-harvest vector (an attacker accepts as the invitee once F2\nships). Mirrors the token-free ``PendingInvite`` exposure."},"RowUsageDestination":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["dataset_id","name"],"title":"RowUsageDestination","description":"Dataset containing a copy of a source row."},"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"},"SaveWorkingDraftRequest":{"properties":{"campaign_lead_id":{"type":"string","format":"uuid","title":"Campaign Lead Id","description":"Lead whose working draft is being saved."},"step_index":{"type":"integer","maximum":32.0,"minimum":1.0,"title":"Step Index","description":"Step number the working draft belongs to (1-indexed)."},"subject":{"type":"string","maxLength":998,"title":"Subject","description":"In-progress subject (may be empty while typing)."},"body":{"type":"string","maxLength":50000,"title":"Body","description":"In-progress body (may be empty while typing)."}},"type":"object","required":["campaign_lead_id","step_index","subject","body"],"title":"SaveWorkingDraftRequest","description":"PUT /campaigns/{id}/playground/draft body.\n\nA working draft is an in-progress edit that AUTO-SAVES as the reviewer\ntypes — it NEVER sends. Unlike ApproveLeadRequest this deliberately does\nNOT reject blank or `{{placeholder}}`-bearing content: mid-edit the field\ncan be empty or half-typed, and the draft is never a ship action. Approve\nstays the only path that freezes a sendable blob."},"SaveWorkingDraftResponse":{"properties":{"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"campaign_lead_id":{"type":"string","format":"uuid","title":"Campaign Lead Id"},"step_index":{"type":"integer","title":"Step Index"},"working_draft":{"$ref":"#/components/schemas/WorkingDraftState"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["campaign_id","campaign_lead_id","step_index","working_draft","updated_at"],"title":"SaveWorkingDraftResponse","description":"PUT /campaigns/{id}/playground/draft response."},"ScalarNumericFilter-Input":{"properties":{"operator":{"type":"string","enum":["eq","lt","gt","lte","gte"],"title":"Operator"},"value":{"type":"string","title":"Value"}},"additionalProperties":false,"type":"object","required":["operator","value"],"title":"ScalarNumericFilter"},"ScalarNumericFilter-Output":{"additionalProperties":true,"type":"object"},"ScalarRevenueFilter-Input":{"properties":{"operator":{"type":"string","enum":["eq","lt","gt","lte","gte"],"title":"Operator"},"value":{"type":"string","title":"Value"},"currency":{"anyOf":[{"type":"string","const":"USD"},{"type":"null"}],"title":"Currency"}},"additionalProperties":false,"type":"object","required":["operator","value"],"title":"ScalarRevenueFilter"},"ScalarRevenueFilter-Output":{"additionalProperties":true,"type":"object"},"ScheduledPostListResponse":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ScheduledPostResponse"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"}},"type":"object","required":["items"],"title":"ScheduledPostListResponse","description":"A page of scheduled posts (date-range query for the calendar)."},"ScheduledPostPlatformResponse":{"properties":{"post_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Post Id"},"body":{"type":"string","title":"Body"},"media_asset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Media Asset Ids"},"status":{"type":"string","enum":["pending","published","unknown","defer","needs_reauth","skipped"],"title":"Status"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Id"}},"type":"object","required":["body","status"],"title":"ScheduledPostPlatformResponse","description":"One targeted platform leg in a scheduled-post response."},"ScheduledPostResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"draft_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Draft Id"},"scheduled_at":{"type":"string","format":"date-time","title":"Scheduled At"},"status":{"type":"string","enum":["scheduled","dispatching","published","partial","failed","cancelled"],"title":"Status"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"media_required":{"type":"boolean","title":"Media Required"},"platforms":{"additionalProperties":{"$ref":"#/components/schemas/ScheduledPostPlatformResponse"},"propertyNames":{"enum":["linkedin","x"]},"type":"object","title":"Platforms"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","scheduled_at","status","media_required","platforms","created_at","updated_at"],"title":"ScheduledPostResponse","description":"One scheduled post (calendar cell + dispatcher-FE row).\n\nNEVER includes claim_token / claim_expires_at (internal lease). Targeted platforms\nare represented by their presence in ``platforms``; untargeted platforms are absent."},"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"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"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"},"prompt_names":{"items":{"type":"string"},"type":"array","title":"Prompt Names","description":"Names of saved prompts on this profile (from sender_data.prompts[].name). Body/text intentionally omitted from list/search responses to keep payloads light and avoid leaking long prompt bodies into the campaign launcher."},"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},"send_mechanism":{"type":"string","enum":["bavimail","gmail","outlook"],"title":"Send Mechanism","description":"Outbound send mechanism bound to this sender identity.","default":"bavimail"},"connected_mailbox_account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connected Mailbox Account","description":"Connected mailbox account key, e.g. the Gmail address."}},"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},"send_mechanism":{"type":"string","enum":["bavimail","gmail","outlook"],"title":"Send Mechanism","description":"Outbound send mechanism for this sender identity.","default":"bavimail"},"connected_mailbox_account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connected Mailbox Account","description":"Connected mailbox account key, e.g. the Gmail address."}},"type":"object","required":["profile_name","sender_data"],"title":"SenderProfileCreate","description":"Request model for creating a sender profile."},"SenderProfileListItem":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"profile_name":{"type":"string","title":"Profile Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"sender_data":{"$ref":"#/components/schemas/DynamicSenderData"},"usage_count":{"type":"integer","title":"Usage Count","default":0},"is_default":{"type":"boolean","title":"Is Default","default":false},"send_mechanism":{"type":"string","enum":["bavimail","gmail","outlook"],"title":"Send Mechanism","default":"bavimail"},"connected_mailbox_account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connected Mailbox Account"}},"type":"object","required":["profile_name","sender_data"],"title":"SenderProfileListItem","description":"Public sender-profile fields returned by the list endpoint."},"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"},"send_mechanism":{"anyOf":[{"type":"string","enum":["bavimail","gmail","outlook"]},{"type":"null"}],"title":"Send Mechanism","description":"Outbound send mechanism for this sender identity."},"connected_mailbox_account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connected Mailbox Account","description":"Connected mailbox account key, e.g. the Gmail address."}},"type":"object","title":"SenderProfileUpdate","description":"Request model for updating a sender profile."},"SequenceStepContext":{"properties":{"step":{"type":"integer","title":"Step"},"channel":{"type":"string","enum":["email","linkedin"],"title":"Channel"},"action_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action Type"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"}},"type":"object","required":["step","channel"],"title":"SequenceStepContext","description":"Current copy for another step in the campaign sequence."},"SessionResultsResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session identifier"},"session_status":{"type":"string","title":"Session Status","description":"Current processing session status"},"dataset_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dataset Id","description":"Persisted dataset identifier"},"is_current_dataset_session":{"type":"boolean","title":"Is Current Dataset Session","description":"Whether row identities belong to the dataset's current session"},"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","session_status","is_current_dataset_session","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."},"SignalListResponse":{"properties":{"signals":{"items":{"$ref":"#/components/schemas/SignalResponse"},"type":"array","title":"Signals"}},"type":"object","required":["signals"],"title":"SignalListResponse"},"SignalResponse":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"source":{"type":"string","title":"Source"},"type":{"type":"string","title":"Type"},"title":{"type":"string","title":"Title"},"payload":{"additionalProperties":true,"type":"object","title":"Payload"},"occurred_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occurred At"},"dedupe_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Dedupe Key"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["source","type","title","payload"],"title":"SignalResponse"},"SignalSuggestionListResponse":{"properties":{"suggestions":{"items":{"$ref":"#/components/schemas/SignalSuggestionResponse"},"type":"array","title":"Suggestions"}},"type":"object","required":["suggestions"],"title":"SignalSuggestionListResponse"},"SignalSuggestionResponse":{"properties":{"source_ref":{"type":"string","title":"Source Ref"},"source":{"type":"string","title":"Source"},"signal_type":{"type":"string","title":"Signal Type"},"bucket":{"type":"string","title":"Bucket"},"title":{"type":"string","title":"Title"},"angle":{"type":"string","title":"Angle"},"facts":{"items":{"type":"string"},"type":"array","title":"Facts"},"occurred_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Occurred At"}},"type":"object","required":["source_ref","source","signal_type","bucket","title","angle","facts"],"title":"SignalSuggestionResponse"},"SkippedDocumentResponse":{"properties":{"file_id":{"type":"string","title":"File Id"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["file_id","reason"],"title":"SkippedDocumentResponse"},"SourceDocumentIngestResponse":{"properties":{"document_id":{"type":"string","title":"Document Id"},"title":{"type":"string","title":"Title"},"source_kind":{"type":"string","enum":["upload","url"],"title":"Source Kind"},"chunk_count":{"type":"integer","title":"Chunk Count"},"embedded_count":{"type":"integer","title":"Embedded Count"},"indexing_status":{"type":"string","enum":["indexed","not_relevant","failed","skipped"],"title":"Indexing Status"}},"type":"object","required":["document_id","title","source_kind","chunk_count","embedded_count","indexing_status"],"title":"SourceDocumentIngestResponse"},"SourceListResponse":{"properties":{"sources":{"items":{"$ref":"#/components/schemas/SourceStatus"},"type":"array","title":"Sources"}},"type":"object","required":["sources"],"title":"SourceListResponse"},"SourceStatus":{"properties":{"source":{"type":"string","enum":["posthog","github"],"title":"Source"},"enabled":{"type":"boolean","title":"Enabled"},"needs_reauth":{"type":"boolean","title":"Needs Reauth"},"last_polled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Polled At"},"updated_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["source","enabled","needs_reauth"],"title":"SourceStatus"},"StarterTemplate":{"properties":{"id":{"type":"string","title":"Id","description":"Stable slug: intro | value | follow_up"},"name":{"type":"string","title":"Name","description":"Display name"},"subject":{"type":"string","title":"Subject","description":"Subject line with {{merge}} tokens"},"body":{"type":"string","title":"Body","description":"Body with {{merge}} tokens"}},"type":"object","required":["id","name","subject","body"],"title":"StarterTemplate","description":"A single generated starter template (subject + body with merge tokens)."},"StarterTemplatesResponse":{"properties":{"templates":{"items":{"$ref":"#/components/schemas/StarterTemplate"},"type":"array","title":"Templates","description":"Generated starter templates"},"generated_from_profile":{"type":"boolean","title":"Generated From Profile","description":"True when built from the org's sender profile; False = generic fallback"}},"type":"object","required":["templates","generated_from_profile"],"title":"StarterTemplatesResponse","description":"Starter templates generated from the org's default sender profile."},"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"},"StepGate":{"properties":{"gate_on":{"type":"string","title":"Gate On","description":"Signal that satisfies the gate. v1 supports 'accepted' only."},"gate_timeout_days":{"type":"integer","maximum":30.0,"minimum":1.0,"title":"Gate Timeout Days","description":"Days to wait for the signal before routing to the timeout step."},"gate_on_timeout_step":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Gate On Timeout Step","description":"Step to route to on timeout (null = complete the lead)."}},"type":"object","required":["gate_on","gate_timeout_days"],"title":"StepGate","description":"Conditional-branch gate on a sequence step (v1: `accepted` only).\n\nA gate parks the sequence at this step until `gate_on` is satisfied, then\nruns the step. If the signal does not arrive within `gate_timeout_days`,\nthe sequence routes to `gate_on_timeout_step` (or completes the lead when\nthat is null). Cross-step legality (predecessor must be a connection_request,\ntarget must be downstream + email, etc.) is enforced on the parent request,\nwhere the full step list is in scope."},"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."},"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."},"TextCriterion":{"properties":{"values":{"items":{"type":"string"},"type":"array","maxItems":20,"minItems":1,"title":"Values"},"match":{"type":"string","enum":["any","all"],"title":"Match","default":"any"}},"additionalProperties":false,"type":"object","required":["values"],"title":"TextCriterion"},"TextIngestRequest":{"properties":{"title":{"type":"string","maxLength":500,"minLength":1,"title":"Title"},"text":{"type":"string","title":"Text"},"source_url":{"anyOf":[{"type":"string","maxLength":4096},{"type":"null"}],"title":"Source Url"},"source_kind":{"type":"string","enum":["connector","upload","url","agent"],"title":"Source Kind","default":"upload"},"external_id":{"anyOf":[{"type":"string","maxLength":1024},{"type":"null"}],"title":"External Id"}},"type":"object","required":["title","text"],"title":"TextIngestRequest"},"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"},"weekly_connection_limit":{"anyOf":[{"type":"integer","maximum":200.0,"minimum":1.0},{"type":"null"}],"title":"Weekly Connection Limit","description":"Rolling 7-day invite ceiling for this account; the daily ceiling is this // 7. Send null to return to the platform default."}},"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."},"UrlIngestRequest":{"properties":{"url":{"type":"string","maxLength":2083,"minLength":1,"title":"Url"},"title":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Title"}},"type":"object","required":["url"],"title":"UrlIngestRequest"},"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."},"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."},"VerifyDatasetRequest":{"properties":{"dataset_id":{"type":"string","format":"uuid","title":"Dataset Id"}},"type":"object","required":["dataset_id"],"title":"VerifyDatasetRequest"},"VoiceConfigResponse":{"properties":{"tone":{"type":"string","title":"Tone","default":""},"style":{"type":"string","title":"Style","default":""},"positioning":{"type":"string","title":"Positioning","default":""},"topics":{"items":{"type":"string"},"type":"array","title":"Topics"},"do_guidelines":{"items":{"type":"string"},"type":"array","title":"Do Guidelines"},"dont_guidelines":{"items":{"type":"string"},"type":"array","title":"Dont Guidelines"},"sample_snippets":{"items":{"type":"string"},"type":"array","title":"Sample Snippets"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","title":"VoiceConfigResponse","description":"The org's voice config. ``updated_at`` is null for an unsaved pre-fill."},"VoiceConfigUpdateRequest":{"properties":{"tone":{"type":"string","maxLength":2000,"title":"Tone","default":""},"style":{"type":"string","maxLength":2000,"title":"Style","default":""},"positioning":{"type":"string","maxLength":2000,"title":"Positioning","default":""},"topics":{"items":{"type":"string","maxLength":500},"type":"array","maxItems":25,"title":"Topics"},"do_guidelines":{"items":{"type":"string","maxLength":500},"type":"array","maxItems":25,"title":"Do Guidelines"},"dont_guidelines":{"items":{"type":"string","maxLength":500},"type":"array","maxItems":25,"title":"Dont Guidelines"},"sample_snippets":{"items":{"type":"string","maxLength":1000},"type":"array","maxItems":25,"title":"Sample Snippets"}},"type":"object","title":"VoiceConfigUpdateRequest","description":"Update payload. Every field a client may send is declared here (critical\npattern #58: an undeclared field is silently dropped). All fields optional so\na partial save keeps unspecified fields at their submitted value -- the service\nwrites the full row, so the client should send the complete config."},"VoiceToolCallRequest":{"properties":{"name":{"type":"string","minLength":1,"title":"Name"},"arguments":{"additionalProperties":true,"type":"object","title":"Arguments"},"call_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Call Id"},"user_consented":{"type":"boolean","title":"User Consented","default":false}},"type":"object","required":["name"],"title":"VoiceToolCallRequest","description":"A Grok Voice function call to execute with authenticated server context."},"WorkingDraftState":{"properties":{"subject":{"type":"string","title":"Subject"},"body":{"type":"string","title":"Body"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["subject","body"],"title":"WorkingDraftState","description":"A saved-but-unapproved working draft for one (lead, step)."},"WorkspacePromptAttachment":{"properties":{"sender_profile_id":{"type":"string","title":"Sender Profile Id"}},"type":"object","required":["sender_profile_id"],"title":"WorkspacePromptAttachment"},"WorkspacePromptCreate":{"properties":{"name":{"type":"string","title":"Name","description":"Prompt name"},"text":{"type":"string","title":"Text","description":"Prompt body (100-5000 chars)"}},"type":"object","required":["name","text"],"title":"WorkspacePromptCreate"},"WorkspacePromptList":{"properties":{"prompts":{"items":{"$ref":"#/components/schemas/WorkspacePromptOut"},"type":"array","title":"Prompts"}},"type":"object","required":["prompts"],"title":"WorkspacePromptList"},"WorkspacePromptOut":{"properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"text":{"type":"string","title":"Text"},"created_at":{"type":"string","title":"Created At"},"updated_at":{"type":"string","title":"Updated At"},"created_by_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created By User Id"},"attached_profile_ids":{"items":{"type":"string"},"type":"array","title":"Attached Profile Ids"}},"type":"object","required":["id","name","text","created_at","updated_at"],"title":"WorkspacePromptOut"},"WorkspacePromptUpdate":{"properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"New prompt name"},"text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Text","description":"New prompt body"}},"type":"object","title":"WorkspacePromptUpdate"},"api__models__campaigns__AddLeadsRequest":{"properties":{"source_dataset_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"minItems":1,"title":"Source Dataset Ids"}},"additionalProperties":false,"type":"object","required":["source_dataset_ids"],"title":"AddLeadsRequest","description":"Lists whose unique rows should be appended to a live campaign audience."},"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":"Exact confirmation or checkpointed frontend-interaction resume payload."}},"type":"object","title":"ChatRequest"},"api__routers__company_context__CompanyContextDocumentResponse":{"properties":{"id":{"type":"string","title":"Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"source_kind":{"type":"string","title":"Source Kind"},"chunk_count":{"type":"integer","title":"Chunk Count"},"awaiting_embedding_count":{"type":"integer","title":"Awaiting Embedding Count"},"created_at":{"type":"string","title":"Created At"}},"type":"object","required":["id","source_kind","chunk_count","awaiting_embedding_count","created_at"],"title":"CompanyContextDocumentResponse"},"api__routers__connectors__CompanyContextDocumentResponse":{"properties":{"id":{"type":"string","title":"Id"},"provider":{"type":"string","title":"Provider"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"mime_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mime Type"},"byte_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Byte Size"},"fetched_at":{"type":"string","title":"Fetched At"}},"type":"object","required":["id","provider","fetched_at"],"title":"CompanyContextDocumentResponse"},"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__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."},"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":"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":"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)."}]}