{"openapi":"3.1.0","info":{"title":"FastAPI","version":"0.1.0"},"paths":{"/auth/jwt/login":{"post":{"tags":["auth"],"summary":"Auth:Cookie.Login","operationId":"auth-auth:cookie.login","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/fastapi___compat__v2__Body_auth-auth_cookie__login"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorModel"},"examples":{"LOGIN_BAD_CREDENTIALS":{"summary":"Bad credentials or the user is inactive.","value":{"detail":"LOGIN_BAD_CREDENTIALS"}},"LOGIN_USER_NOT_VERIFIED":{"summary":"The user is not verified.","value":{"detail":"LOGIN_USER_NOT_VERIFIED"}}}}}},"204":{"description":"No Content"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/jwt/logout":{"post":{"tags":["auth"],"summary":"Auth:Cookie.Logout","operationId":"auth-auth:cookie.logout","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"401":{"description":"Missing token or inactive user."},"204":{"description":"No Content"}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/auth/bearer/login":{"post":{"tags":["auth"],"summary":"Auth:Jwt.Login","operationId":"auth-auth:jwt.login","requestBody":{"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/fastapi___compat__v2__Body_auth-auth_jwt__login"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerResponse"},"example":{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiOTIyMWZmYzktNjQwZi00MzcyLTg2ZDMtY2U2NDJjYmE1NjAzIiwiYXVkIjoiZmFzdGFwaS11c2VyczphdXRoIiwiZXhwIjoxNTcxNTA0MTkzfQ.M10bjOe45I5Ncu_uXvOmVV8QxnL-nZfcH96U90JaocI","token_type":"bearer"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorModel"},"examples":{"LOGIN_BAD_CREDENTIALS":{"summary":"Bad credentials or the user is inactive.","value":{"detail":"LOGIN_BAD_CREDENTIALS"}},"LOGIN_USER_NOT_VERIFIED":{"summary":"The user is not verified.","value":{"detail":"LOGIN_USER_NOT_VERIFIED"}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/bearer/logout":{"post":{"tags":["auth"],"summary":"Logout Bearer Token","description":"Logout desktop/API clients by revoking the submitted refresh token.","operationId":"auth-logout_bearer_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerLogoutRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/forgot-password":{"post":{"tags":["auth"],"summary":"Reset:Forgot Password","operationId":"auth-reset:forgot_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_auth-reset_forgot_password"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/reset-password":{"post":{"tags":["auth"],"summary":"Reset:Reset Password","operationId":"auth-reset:reset_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_auth-reset_reset_password"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorModel"},"examples":{"RESET_PASSWORD_BAD_TOKEN":{"summary":"Bad or expired token.","value":{"detail":"RESET_PASSWORD_BAD_TOKEN"}},"RESET_PASSWORD_INVALID_PASSWORD":{"summary":"Password validation failed.","value":{"detail":{"code":"RESET_PASSWORD_INVALID_PASSWORD","reason":"Password should be at least 3 characters"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/request-verify-token":{"post":{"tags":["auth"],"summary":"Verify:Request-Token","operationId":"auth-verify:request-token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_auth-verify_request-token"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/verify":{"post":{"tags":["auth"],"summary":"Verify:Verify","operationId":"auth-verify:verify","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Body_auth-verify_verify"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorModel"},"examples":{"VERIFY_USER_BAD_TOKEN":{"summary":"Bad token, not existing user or not the e-mail currently set for the user.","value":{"detail":"VERIFY_USER_BAD_TOKEN"}},"VERIFY_USER_ALREADY_VERIFIED":{"summary":"The user is already verified.","value":{"detail":"VERIFY_USER_ALREADY_VERIFIED"}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/users/me":{"get":{"tags":["users"],"summary":"Users:Current User","operationId":"users-users:current_user","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"401":{"description":"Missing token or inactive user."}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"patch":{"tags":["users"],"summary":"Users:Patch Current User","operationId":"users-users:patch_current_user","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"401":{"description":"Missing token or inactive user."},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorModel"},"examples":{"UPDATE_USER_EMAIL_ALREADY_EXISTS":{"summary":"A user with this email already exists.","value":{"detail":"UPDATE_USER_EMAIL_ALREADY_EXISTS"}},"UPDATE_USER_INVALID_PASSWORD":{"summary":"Password validation failed.","value":{"detail":{"code":"UPDATE_USER_INVALID_PASSWORD","reason":"Password should beat least 3 characters"}}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/auth/users/{id}":{"get":{"tags":["users"],"summary":"Users:User","operationId":"users-users:user","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","title":"Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"401":{"description":"Missing token or inactive user."},"403":{"description":"Not a superuser."},"404":{"description":"The user does not exist."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["users"],"summary":"Users:Patch User","operationId":"users-users:patch_user","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","title":"Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserRead"}}}},"401":{"description":"Missing token or inactive user."},"403":{"description":"Not a superuser."},"404":{"description":"The user does not exist."},"400":{"content":{"application/json":{"examples":{"UPDATE_USER_EMAIL_ALREADY_EXISTS":{"summary":"A user with this email already exists.","value":{"detail":"UPDATE_USER_EMAIL_ALREADY_EXISTS"}},"UPDATE_USER_INVALID_PASSWORD":{"summary":"Password validation failed.","value":{"detail":{"code":"UPDATE_USER_INVALID_PASSWORD","reason":"Password should beat least 3 characters"}}}},"schema":{"$ref":"#/components/schemas/ErrorModel"}}},"description":"Bad Request"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["users"],"summary":"Users:Delete User","operationId":"users-users:delete_user","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","title":"Id"}}],"responses":{"204":{"description":"Successful Response"},"401":{"description":"Missing token or inactive user."},"403":{"description":"Not a superuser."},"404":{"description":"The user does not exist."},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/bearer/refresh":{"post":{"tags":["auth"],"summary":"Refresh Bearer Token","description":"Refresh access token using refresh token (for desktop/API clients).\n\nUnlike the JWT refresh endpoint, this accepts refresh token in request body\nand returns the new access token in the response body.","operationId":"auth-refresh_bearer_token","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerRefreshRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BearerRefreshResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/jwt/refresh":{"post":{"tags":["auth"],"summary":"Refresh Access Token","description":"Refresh the access token using a refresh token.\n\nThe refresh token is read from the HTTP-only cookie.\nA new access token is set as an HTTP-only cookie in the response.","operationId":"auth-refresh_access_token","parameters":[{"name":"refresh_token","in":"cookie","required":false,"schema":{"type":"string","title":"Refresh Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/auth/jwt/logout-all":{"post":{"tags":["auth"],"summary":"Logout With Cookie Cleanup","description":"Logout and clear both access and refresh token cookies.\n\nThis endpoint also revokes the refresh token in the database.","operationId":"auth-logout_with_cookie_cleanup","parameters":[{"name":"refresh_token","in":"cookie","required":false,"schema":{"type":"string","title":"Refresh Token"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls":{"get":{"tags":["calls"],"summary":"List Calls","description":"List calls with filtering and pagination.\n\nAgents see their own calls, team leads see calls snapshotted to their team,\nand admins see all calls.","operationId":"calls-list_calls","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"scenario","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by scenario (multiple allowed)","title":"Scenario"},"description":"Filter by scenario (multiple allowed)"},{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter calls from this date","title":"Date From"},"description":"Filter calls from this date"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Filter calls to this date","title":"Date To"},"description":"Filter calls to this date"},{"name":"agent_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by agent ID","title":"Agent Id"},"description":"Filter by agent ID"},{"name":"min_score","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Minimum qa_score (inclusive)","title":"Min Score"},"description":"Minimum qa_score (inclusive)"},{"name":"max_score","in":"query","required":false,"schema":{"anyOf":[{"type":"number"},{"type":"null"}],"description":"Maximum qa_score (inclusive)","title":"Max Score"},"description":"Maximum qa_score (inclusive)"},{"name":"call_source","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by call source (multiple allowed)","title":"Call Source"},"description":"Filter by call source (multiple allowed)"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by call status (multiple allowed)","title":"Status"},"description":"Filter by call status (multiple allowed)"},{"name":"call_mode","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by call mode (multiple allowed)","title":"Call Mode"},"description":"Filter by call mode (multiple allowed)"},{"name":"call_direction","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by call direction (multiple allowed)","title":"Call Direction"},"description":"Filter by call direction (multiple allowed)"},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by user IDs (multiple allowed)","title":"User Id"},"description":"Filter by user IDs (multiple allowed)"},{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Team filter; team leads are fixed to their assigned team","title":"Team Id"},"description":"Team filter; team leads are fixed to their assigned team"},{"name":"telephony_result","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by telephony result (multiple allowed)","title":"Telephony Result"},"description":"Filter by telephony result (multiple allowed)"},{"name":"answered_by","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by answered_by classification (multiple allowed)","title":"Answered By"},"description":"Filter by answered_by classification (multiple allowed)"},{"name":"conversation_outcome","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by conversation outcome (multiple allowed)","title":"Conversation Outcome"},"description":"Filter by conversation outcome (multiple allowed)"},{"name":"idv_status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by IDV status: verified, partial, incomplete, or not_required (multiple allowed)","title":"Idv Status"},"description":"Filter by IDV status: verified, partial, incomplete, or not_required (multiple allowed)"},{"name":"workflow_disposition","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by autonomous workflow action (multiple allowed)","title":"Workflow Disposition"},"description":"Filter by autonomous workflow action (multiple allowed)"},{"name":"agent_end_reason","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by normalized autonomous ending reason (multiple allowed)","title":"Agent End Reason"},"description":"Filter by normalized autonomous ending reason (multiple allowed)"},{"name":"coaching_feedback_rating","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by coaching feedback rating (multiple allowed)","title":"Coaching Feedback Rating"},"description":"Filter by coaching feedback rating (multiple allowed)"},{"name":"has_transfer_in","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter calls that received a transfer (transferred_from_call_id IS NOT NULL)","title":"Has Transfer In"},"description":"Filter calls that received a transfer (transferred_from_call_id IS NOT NULL)"},{"name":"has_transfer_out","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter calls that were transferred out (transferred_to_call_id IS NOT NULL)","title":"Has Transfer Out"},"description":"Filter calls that were transferred out (transferred_to_call_id IS NOT NULL)"},{"name":"has_dashboard_open","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter calls where the dashboard was open during the call (dashboard_open_duration_ms > 0)","title":"Has Dashboard Open"},"description":"Filter calls where the dashboard was open during the call (dashboard_open_duration_ms > 0)"},{"name":"crm_linked","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by actual CRM account link. True requires decision=linked; false includes calls with no link or a none_of_these decision.","title":"Crm Linked"},"description":"Filter by actual CRM account link. True requires decision=linked; false includes calls with no link or a none_of_these decision."},{"name":"is_starred","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by whether calls are saved for later review","title":"Is Starred"},"description":"Filter by whether calls are saved for later review"},{"name":"customer_number","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by customer phone number (partial match)","title":"Customer Number"},"description":"Filter by customer phone number (partial match)"},{"name":"tag_key","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by detected call tag keys (multiple allowed)","title":"Tag Key"},"description":"Filter by detected call tag keys (multiple allowed)"},{"name":"client","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by classified client (multiple allowed)","title":"Client"},"description":"Filter by classified client (multiple allowed)"},{"name":"campaign_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter to calls placed by these outbound campaigns (multiple allowed). Manual dials and callback rows match no campaign.","title":"Campaign Id"},"description":"Filter to calls placed by these outbound campaigns (multiple allowed). Manual dials and callback rows match no campaign."},{"name":"sort_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Column to sort by: started_at, qa_score, duration_seconds","title":"Sort By"},"description":"Column to sort by: started_at, qa_score, duration_seconds"},{"name":"sort_order","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Sort direction: asc or desc","default":"desc","title":"Sort Order"},"description":"Sort direction: asc or desc"},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_CallListItem_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/filter-options":{"get":{"tags":["calls"],"summary":"Get Filter Options","description":"Get available filter options for call history.\n\nReturns distinct values for scenarios, agents, statuses, modes, and sources.\nOptions follow the same agent/team/admin visibility scope as the call list.","operationId":"calls-get_filter_options","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Team filter; team leads are fixed to their assigned team","title":"Team Id"},"description":"Team filter; team leads are fixed to their assigned team"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallFilterOptionsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/tag-options":{"get":{"tags":["calls"],"summary":"Get Tag Options","description":"Get the detected call tags available as filter options.\n\nServed apart from ``/filter-options`` because it reads every visible\ncall's tags, so it never holds up the options pages wait on. Options\nfollow the same agent/team/admin visibility scope as the call list.","operationId":"calls-get_tag_options","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Team filter; team leads are fixed to their assigned team","title":"Team Id"},"description":"Team filter; team leads are fixed to their assigned team"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FilterOption"},"title":"Response Calls-Get Tag Options"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}":{"get":{"tags":["calls"],"summary":"Get Call Detail","description":"Get full call details including transcript and analyses.\n\nAgents can view their own calls, team leads can view calls snapshotted to\ntheir team, and admins can view all calls.","operationId":"calls-get_call_detail","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/star":{"patch":{"tags":["calls"],"summary":"Update Call Star","description":"Save or remove a visible call from the review list.","operationId":"calls-update_call_star","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallStarUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallStarResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/replay":{"get":{"tags":["calls"],"summary":"Get Call Replay Data","description":"Get replay data for a completed call.\n\nReturns timestamped session events for synchronized replay of the call session.\nReplay follows the same agent/team/admin read scope as call detail.","operationId":"calls-get_call_replay_data","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}},{"name":"mode","in":"query","required":false,"schema":{"$ref":"#/components/schemas/ReplayMode","default":"playback"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallReplayResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/suggested-response-prompt":{"get":{"tags":["calls"],"summary":"Get Suggested Response Prompt","description":"Rendered prompt + output for the suggested response at a transcript turn.\n\nReconstructed from the Langfuse generation trace for prompt tuning (compare\nwhat we suggested, and the context we fed in, against the agent's real\nreply). Owner-or-admin only, same as replay.","operationId":"calls-get_suggested_response_prompt","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}},{"name":"sequence","in":"query","required":true,"schema":{"type":"integer","title":"Sequence"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuggestedResponsePromptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/datetime":{"patch":{"tags":["calls"],"summary":"Update Call Datetime","description":"Update call start and end date/time (Admin only).\n\nArgs:\n    call_id: ID of the call to update\n    payload: New start/end date/time values\n\nReturns:\n    Updated call details","operationId":"calls-update_call_datetime","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDateTimeUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/correct-classification":{"patch":{"tags":["calls"],"summary":"Correct Classification","description":"Correct a finalized call's answered_by / conversation_outcome (Admin only).\n\nSupervised review of autonomous campaigns: the classifier's label drives the\nretry ladder and the CRM note, so a reviewer needs to overrule it — and the\ncorrection reverses what the wrong label caused, reopening a campaign\nmembership it had closed. Admin-only and audited (every change writes a\n``call_classification_corrections`` row), because it edits the record a\ncustomer's CRM has already been told about.\n\nArgs:\n    call_id: ID of the call to correct\n    payload: New answered_by and/or conversation_outcome, plus an optional\n        reason recorded on the audit row\n\nReturns:\n    The corrected call, and what the correction changed beyond the two\n    fields (membership reopened, artifacts invalidated)","operationId":"calls-correct_classification","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorrectClassificationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CorrectClassificationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/classification":{"patch":{"tags":["calls"],"summary":"Update Classification","description":"Update call classification (scenario).\n\nAllows changing the scenario assigned to a call and optionally regenerating\ncoaching, summary, and tagging artifacts with the new scenario's prompts.\n\nArgs:\n    call_id: ID of the call to update\n    payload: Classification update request with optional scenario and regenerate flag\n\nReturns:\n    Updated call details","operationId":"calls-update_classification","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateClassificationRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{session_id}/finalize":{"post":{"tags":["calls"],"summary":"Finalize Call","description":"Manually trigger finalization for a call session.","operationId":"calls-finalize_call","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/retry":{"post":{"tags":["calls"],"summary":"Retry Finalization","description":"Retry finalization for a call, re-running AI jobs.","operationId":"calls-retry_finalization","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/audio-url":{"get":{"tags":["calls"],"summary":"Get Audio Url","description":"Get a presigned URL for streaming the call's audio file.\n\nReturns a temporary URL (valid for 1 hour) that can be used to\nstream or download the call recording.","operationId":"calls-get_audio_url","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Calls-Get Audio Url"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/calls/{call_id}/provider-recording-url":{"get":{"tags":["calls"],"summary":"Get Provider Recording Url","description":"Mint a short-lived URL for a recording hosted by the telephony provider.\n\nOnly available for calls whose provider supports minting (TCN today;\n404 for providers that don't, e.g. awsconnect refs deep-link to the\nConnect console instead). The URL expires after ~10 minutes, so it is\nminted per request and must not be cached beyond that. Returns 409\nwhile the provider is still processing the recording (it lands a few\nminutes after hangup).\n\nDeliberately holds no request-scoped DB session: the provider HTTP\nround-trip can hang for minutes, and a request cancelled mid-await with\na checked-out connection is the Sentry \"garbage collector cleaning up\nnon-checked-in connection\" signature.","operationId":"calls-get_provider_recording_url","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProviderRecordingUrlResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/previous-engaged-call":{"get":{"tags":["calls"],"summary":"Get Previous Engaged Call","description":"Latest relevant prior call summary (and recent-attempt count) for the\nlive session's phone number. Always 200; empty response when the anchor\nsession is not a live external call or the number is unknown.","operationId":"calls-get_previous_engaged_call","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/PreviousEngagedCallResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/users":{"get":{"tags":["admin-users"],"summary":"List Admin Users","operationId":"admin-users-list_admin_users","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":320},{"type":"null"}],"title":"Search"}},{"name":"role","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"$ref":"#/components/schemas/UserRole"}},{"type":"null"}],"title":"Role"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"enum":["active","inactive"],"type":"string"}},{"type":"null"}],"title":"Status"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_AdminUserResponse_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["admin-users"],"summary":"Create Admin User","operationId":"admin-users-create_admin_user","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserEmailActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/users/{user_id}":{"patch":{"tags":["admin-users"],"summary":"Update Admin User","operationId":"admin-users-update_admin_user","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["admin-users"],"summary":"Delete Admin User","operationId":"admin-users-delete_admin_user","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/users/{user_id}/resend-welcome":{"post":{"tags":["admin-users"],"summary":"Resend Admin User Welcome","operationId":"admin-users-resend_admin_user_welcome","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserEmailActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/users/{user_id}/send-password-reset":{"post":{"tags":["admin-users"],"summary":"Send Admin User Password Reset","operationId":"admin-users-send_admin_user_password_reset","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUserEmailActionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/teams":{"get":{"tags":["admin-teams"],"summary":"List Teams","operationId":"admin-teams-list_teams","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TeamRead"},"type":"array","title":"Response Admin-Teams-List Teams"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"post":{"tags":["admin-teams"],"summary":"Create Team","operationId":"admin-teams-create_team","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/admin/teams/{team_id}":{"patch":{"tags":["admin-teams"],"summary":"Update Team","operationId":"admin-teams-update_team","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"team_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Team Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/clients":{"get":{"tags":["admin-clients"],"summary":"List Clients","operationId":"admin-clients-list_clients","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ClientRead"},"type":"array","title":"Response Admin-Clients-List Clients"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"post":{"tags":["admin-clients"],"summary":"Create Client","operationId":"admin-clients-create_client","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/admin/clients/{client_id}":{"patch":{"tags":["admin-clients"],"summary":"Update Client","operationId":"admin-clients-update_client","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Client Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/coaching/{session_id}":{"post":{"tags":["coaching"],"summary":"Generate Coaching Feedback","description":"Generate coaching feedback for a completed call session and store it.\n\nCoaching is generated when:\n1. Call was answered by a human (answered_by == 'human')\n2. The scenario has a coaching prompt configured","operationId":"coaching-generate_coaching_feedback","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/coaching/{session_id}/feedback":{"post":{"tags":["coaching"],"summary":"Submit Coaching Feedback","description":"Submit or update user feedback on coaching for a call session.\n\n- Creates new feedback if none exists\n- Updates existing feedback if already submitted\n- Comment is recommended when rating is negative","operationId":"coaching-submit_coaching_feedback","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingUserFeedbackCreate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CoachingUserFeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["coaching"],"summary":"Get Coaching Feedback","description":"Get the current user's coaching feedback status for a session.\n\nReturns whether feedback has been submitted and the details if so.","operationId":"coaching-get_coaching_feedback","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/CoachingUserFeedbackStatus"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/crm/state":{"get":{"tags":["crm"],"summary":"Get Crm State","operationId":"crm-get_crm_state","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/CrmStateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/crm/lookup":{"post":{"tags":["crm"],"summary":"Lookup Crm Account","operationId":"crm-lookup_crm_account","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLookupRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLookupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/crm/link":{"post":{"tags":["crm"],"summary":"Link Crm Account","operationId":"crm-link_crm_account","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLinkRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCallLinkRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/crm/save-note":{"post":{"tags":["crm"],"summary":"Save Crm Note","operationId":"crm-save_crm_note","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/CrmSaveNoteResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/crm/spark/call-outcome":{"get":{"tags":["crm"],"summary":"Get Spark Call Outcome","operationId":"crm-get_spark_call_outcome","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/SparkCallOutcomeState"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["crm"],"summary":"Save Spark Call Outcome","operationId":"crm-save_spark_call_outcome","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SparkCallOutcomeDraft"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SparkCallOutcomeSaveResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/integrations/crm/status":{"get":{"tags":["integrations","crm"],"summary":"Crm Status","operationId":"integrations-crm_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Integrations-Crm Status"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/crm/lookup":{"post":{"tags":["integrations","crm"],"summary":"Lookup Crm Account Sessionless","description":"Read-only account lookup that needs no call session.\n\nBacks pre-call tools (the payment calculator's loan-id lookup) so an agent\ncan pull account context before dialing. It never mutates state.\n\nBecause this path is not tied to a call the agent owns, it is deliberately\nrestricted to *exact record identifiers* (account number / customer id).\nBroad demographic criteria (phone, email, name, DOB) and the creditor-wide\n``client_id`` are rejected here: they turn a targeted pre-call lookup into a\ntool for sweeping the customer book by matching partial PII. Those criteria\nremain available on the session-scoped ``/sessions/{id}/crm/lookup`` route,\nwhich is gated to a call the agent is actually handling. Every call is\naudit-logged with the caller so bulk enumeration is attributable.","operationId":"integrations-lookup_crm_account_sessionless","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLookupRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLookupResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/crm/config":{"get":{"tags":["integrations","crm"],"summary":"Get Crm Config","operationId":"integrations-get_crm_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmIntegrationResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"put":{"tags":["integrations","crm"],"summary":"Upsert Crm Config","operationId":"integrations-upsert_crm_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmIntegrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/crm/test":{"post":{"tags":["integrations","crm"],"summary":"Test Crm Config","operationId":"integrations-test_crm_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/collexus/status":{"get":{"tags":["integrations","collexus"],"summary":"Collexus Exchange Status","description":"What the Integrations card shows: how the exchange is configured, which\ndirections run on a schedule, and the last file in each direction.\n\nRead from settings and the ledgers only — it opens no connection, so it\nsays nothing about whether the server is reachable. That is what the\nconnection check is for.","operationId":"integrations-collexus_exchange_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollexusExchangeStatusResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/collexus/settings":{"put":{"tags":["integrations","collexus"],"summary":"Save Collexus Exchange Settings","description":"Save which scenarios the return file covers and which directions run on\na schedule, and return the card's status as it now stands.\n\nFrom the first save these choices replace the deployment's configured\ndefaults. A scenario must be one of this deployment's AI scenarios, and the\ndaily return file cannot be switched on with none chosen. The connection\nand the account-file freshness gate are not settable here: pausing the\nscheduled import leaves that gate counting.","operationId":"integrations-save_collexus_exchange_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollexusExchangeSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollexusExchangeStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/collexus/sftp/check":{"post":{"tags":["integrations","collexus"],"summary":"Check Collexus Sftp","description":"Probe the Collexus SFTP server and report what came back.\n\nThe creditor's firewall admits only the deployment's NAT egress addresses,\nso this has to run from inside the stack — and the image carries no ssh\nclient, so an admin route is the way to run it. It answers cleanly on a\ndeployment that has no Collexus configuration at all.\n\nWith no `COLLEXUS_SFTP_HOST_KEY` set the check runs in discovery mode: it\nreports the server's fingerprint and the key line to pin, having\nauthenticated nothing and transferred nothing. Once pinned, a host key that\ndoes not match aborts the connection and the check says so.","operationId":"integrations-check_collexus_sftp","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollexusSftpCheckResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/collexus/return-file":{"get":{"tags":["integrations","collexus"],"summary":"Read Collexus Return File","description":"Generate one day's activity return file and report it, without uploading.\n\nHow the agreed format gets checked before anything lands in the creditor's\nfolder: the response carries the complete CSV, its digest and its row\ncount, and the scheduled delivery sweep is not involved. Generating is\nfree of side effects, so this is safe to call repeatedly and on a day that\nhas already been delivered — it says so, and the delivery itself stays\nrefused.\n\nAdmin-only because the file is customer data by nature: references, phone\nnumbers and call summaries, the same exposure as the accounts CSV export.\nIt answers cleanly on a deployment that produces no return file at all,\nreporting the agreed column order either way.","operationId":"integrations-read_collexus_return_file","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"business_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Creditor-local day to cover (see COLLEXUS_RETURN_FILE_TIMEZONE). Defaults to the most recent complete local day — the one a delivery pass right now would be filing.","title":"Business Date"},"description":"Creditor-local day to cover (see COLLEXUS_RETURN_FILE_TIMEZONE). Defaults to the most recent complete local day — the one a delivery pass right now would be filing."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollexusReturnFileResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/integrations/collexus/ingest/run":{"post":{"tags":["integrations","collexus"],"summary":"Run Collexus Ingest","description":"Start one poll of the creditor's folder, importing the newest account file.\n\nOne tick of the scheduled ingest, on request: the same import path, the\nsame ledger, the same refusal to read anything while no host key is\npinned. It works with the import schedule off, and never arms the\naccount-file freshness gate — so the exchange can be proved with a single\nfile without dialling starting to depend on the next one.\n\nIt answers at once and the poll runs in the background: a creditor's whole\nbook takes longer to import than the load balancer keeps a request open.\nThe outcome lands on the run, which ``/status`` reports as ``ingest_run``.","operationId":"integrations-run_collexus_ingest","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollexusIngestRunResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/collexus/return-file/deliver":{"post":{"tags":["integrations","collexus"],"summary":"Deliver Collexus Return File","description":"Upload one day's activity return file to the creditor's folder, once.\n\nThe scheduled delivery on request, for a chosen day and without waiting\nfor the delivery hour. It writes to the creditor's server, and a day is\ndelivered once: asking again for a delivered day sends nothing and says\nso. It needs the scenario scope and a pinned host key, but not the daily\ndelivery switched on.","operationId":"integrations-deliver_collexus_return_file","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"business_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Creditor-local day to deliver (see COLLEXUS_RETURN_FILE_TIMEZONE). Defaults to the most recent complete local day. A day that has not ended is refused.","title":"Business Date"},"description":"Creditor-local day to deliver (see COLLEXUS_RETURN_FILE_TIMEZONE). Defaults to the most recent complete local day. A day that has not ended is refused."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollexusReturnFileDeliveryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/integrations/payments/status":{"get":{"tags":["integrations","payments"],"summary":"Payment Status","operationId":"integrations-payment_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntegrationStatus"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/payments/config":{"get":{"tags":["integrations","payments"],"summary":"Get Payment Config","operationId":"integrations-get_payment_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntegrationResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"put":{"tags":["integrations","payments"],"summary":"Upsert Payment Config","operationId":"integrations-upsert_payment_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntegrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/payments/test":{"post":{"tags":["integrations","payments"],"summary":"Test Payment Config","description":"Prove the credentials authenticate: the submitted form values win, a\nblank api_key falls back to the stored (decrypted) or env one — so the\ntest probes exactly what a save would put into use. One-shot client: an\nuntested credential set must not enter the pooled cache.","operationId":"integrations-test_payment_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentTestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/payment-portal/status":{"get":{"tags":["integrations","payments"],"summary":"Payment Portal Status","operationId":"integrations-payment_portal_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPortalIntegrationStatus"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/payment-portal/config":{"get":{"tags":["integrations","payments"],"summary":"Get Payment Portal Config","operationId":"integrations-get_payment_portal_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPortalIntegrationResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"put":{"tags":["integrations","payments"],"summary":"Upsert Payment Portal Config","operationId":"integrations-upsert_payment_portal_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPortalIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPortalIntegrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/payment-portal/test":{"post":{"tags":["integrations","payments"],"summary":"Test Payment Portal Config","description":"Prove the credentials authenticate: the submitted form values win, a\nblank secret falls back to the stored or env one. One-shot client: an\nuntested credential set must not enter the pooled cache.","operationId":"integrations-test_payment_portal_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPortalIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentPortalTestConnectionResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/sms/status":{"get":{"tags":["integrations","sms"],"summary":"Sms Status","operationId":"integrations-sms_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsIntegrationStatus"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/sms/config":{"get":{"tags":["integrations","sms"],"summary":"Get Sms Config","operationId":"integrations-get_sms_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsIntegrationResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"put":{"tags":["integrations","sms"],"summary":"Upsert Sms Config","operationId":"integrations-upsert_sms_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsIntegrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/sms/test":{"post":{"tags":["integrations","sms"],"summary":"Test Sms Config","description":"Send a real test SMS to the supplied number with the submitted (or\nstored/env) credentials — so the admin sees a text arrive before enabling.\nDry-run is forced off for the test; a demo no-op wouldn't prove anything.","operationId":"integrations-test_sms_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SmsTestResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/summary/{session_id}":{"post":{"tags":["summary"],"summary":"Generate Call Summary","description":"Generate a call summary for a completed call session and store it.","operationId":"summary-generate_call_summary","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SummaryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SummaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["summary"],"summary":"Edit Call Summary","description":"Overwrite the stored call summary with an agent-edited markdown version.","operationId":"summary-edit_call_summary","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditSummaryRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SummaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/summary/{session_id}/mark-copied":{"post":{"tags":["summary"],"summary":"Mark Summary Copied","description":"Record that the agent copied this call's summary to the clipboard.\n\nIdempotent and counted at most once per call: the first copy stamps\n`summary_copied_at`; subsequent copies (the agent pressing Copy again) are\nno-ops that return the original timestamp. This per-call flag powers the\n\"Summary Copied\" adoption metric on the leadership performance dashboard.","operationId":"summary-mark_summary_copied","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/MarkSummaryCopiedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/performance/summary":{"get":{"tags":["performance"],"summary":"Get Performance Summary","description":"Return aggregated performance metrics for the leader dashboard.","operationId":"performance-get_performance_summary","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"date_from","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Start date (inclusive)","title":"Date From"},"description":"Start date (inclusive)"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"End date (inclusive)","title":"Date To"},"description":"End date (inclusive)"},{"name":"scenario","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Scenario filter","title":"Scenario"},"description":"Scenario filter"},{"name":"agent_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Agent filter","title":"Agent Id"},"description":"Agent filter"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by call status (multiple allowed)","title":"Status"},"description":"Filter by call status (multiple allowed)"},{"name":"call_direction","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by call direction (multiple allowed)","title":"Call Direction"},"description":"Filter by call direction (multiple allowed)"},{"name":"call_mode","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by call mode (training, production, or ai_agent)","title":"Call Mode"},"description":"Filter by call mode (training, production, or ai_agent)"},{"name":"filter_user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by agent user IDs (multiple allowed)","title":"Filter User Id"},"description":"Filter by agent user IDs (multiple allowed)"},{"name":"qa_score_bucket","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by QA score bucket: low (<60), medium (60-80), high (>80)","title":"Qa Score Bucket"},"description":"Filter by QA score bucket: low (<60), medium (60-80), high (>80)"},{"name":"telephony_result","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by telephony result (multiple allowed)","title":"Telephony Result"},"description":"Filter by telephony result (multiple allowed)"},{"name":"answered_by","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by answered by (human, voicemail, unclear)","title":"Answered By"},"description":"Filter by answered by (human, voicemail, unclear)"},{"name":"conversation_outcome","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by conversation outcome (engaged, refused, wrong_person, other)","title":"Conversation Outcome"},"description":"Filter by conversation outcome (engaged, refused, wrong_person, other)"},{"name":"workflow_disposition","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by autonomous workflow action (multiple allowed)","title":"Workflow Disposition"},"description":"Filter by autonomous workflow action (multiple allowed)"},{"name":"agent_end_reason","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by normalized autonomous ending reason (multiple allowed)","title":"Agent End Reason"},"description":"Filter by normalized autonomous ending reason (multiple allowed)"},{"name":"call_source","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by call source (multiple allowed)","title":"Call Source"},"description":"Filter by call source (multiple allowed)"},{"name":"tag_key","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by detected tag key (multiple allowed)","title":"Tag Key"},"description":"Filter by detected tag key (multiple allowed)"},{"name":"client","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter by classified client (multiple allowed)","title":"Client"},"description":"Filter by classified client (multiple allowed)"},{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Team filter; team leads are fixed to their assigned team","title":"Team Id"},"description":"Team filter; team leads are fixed to their assigned team"},{"name":"campaign_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Filter to calls this outbound campaign placed (multiple allowed; several campaigns are unioned). Manual dials and callback rows belong to no campaign and are excluded.","title":"Campaign Id"},"description":"Filter to calls this outbound campaign placed (multiple allowed; several campaigns are unioned). Manual dials and callback rows belong to no campaign and are excluded."},{"name":"crm_linked","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter by CRM account-link state","title":"Crm Linked"},"description":"Filter by CRM account-link state"},{"name":"min_score","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":100,"minimum":0},{"type":"null"}],"description":"Minimum QA score (inclusive)","title":"Min Score"},"description":"Minimum QA score (inclusive)"},{"name":"max_score","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":100,"minimum":0},{"type":"null"}],"description":"Maximum QA score (inclusive)","title":"Max Score"},"description":"Maximum QA score (inclusive)"},{"name":"range_days","in":"query","required":false,"schema":{"type":"integer","maximum":90,"minimum":1,"description":"Fallback range (days) when dates not provided","default":7,"title":"Range Days"},"description":"Fallback range (days) when dates not provided"},{"name":"timezone","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"IANA timezone for day bucketing, e.g. 'Australia/Sydney'. Defaults to UTC.","title":"Timezone"},"description":"IANA timezone for day bucketing, e.g. 'Australia/Sydney'. Defaults to UTC."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PerformanceSummaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/qa-insights/overview":{"get":{"tags":["qa-insights"],"summary":"Get Overview","description":"Team view: tiles, portfolio signals, grounded narrative, flagged calls,\nagents grid — daily register is event-led, weekly is rate-led.","operationId":"qa-insights-get_overview","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"period_type","in":"query","required":false,"schema":{"type":"string","description":"day | wtd | week | month","default":"day","title":"Period Type"},"description":"day | wtd | week | month"},{"name":"anchor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Local date to anchor the period (URL-addressable)","title":"Anchor"},"description":"Local date to anchor the period (URL-addressable)"},{"name":"regenerate","in":"query","required":false,"schema":{"type":"boolean","description":"Force narrative regeneration","default":false,"title":"Regenerate"},"description":"Force narrative regeneration"},{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Team filter; team leads are fixed to their assigned team","title":"Team Id"},"description":"Team filter; team leads are fixed to their assigned team"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OverviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/qa-insights/agents/{user_id}":{"get":{"tags":["qa-insights"],"summary":"Get Agent Detail","description":"Agent drill: recent form, aggregate scorecard vs team, tag strengths,\nrecent calls, and the coaching narrative.","operationId":"qa-insights-get_agent_detail","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}},{"name":"period_type","in":"query","required":false,"schema":{"type":"string","default":"week","title":"Period Type"}},{"name":"anchor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Anchor"}},{"name":"regenerate","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Regenerate"}},{"name":"team_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Team filter; team leads are fixed to their assigned team","title":"Team Id"},"description":"Team filter; team leads are fixed to their assigned team"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentDetailResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/qa-scorecard/templates":{"get":{"tags":["qa-scorecard"],"summary":"Get Qa Scorecard Templates","description":"List registered scorecard templates for admin selectors.","operationId":"qa-scorecard-get_qa_scorecard_templates","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaScorecardTemplatesResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/qa-scorecard/{call_id}":{"get":{"tags":["qa-scorecard"],"summary":"Get Qa Scorecard","description":"Return the stored QA scorecard artifact for a call.","operationId":"qa-scorecard-get_qa_scorecard","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaScorecardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["qa-scorecard"],"summary":"Edit Qa Scorecard","description":"Manually correct a stored QA scorecard.","operationId":"qa-scorecard-edit_qa_scorecard","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaScorecardEditRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaScorecardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/qa-scorecard/{call_id}/generate":{"post":{"tags":["qa-scorecard"],"summary":"Generate Qa Scorecard","description":"Generate (or re-generate) a QA scorecard.\n\nGoes through the same single-flight lock as auto-generation, so admins can\nsafely backfill older calls without racing the post-call auto-gen path.","operationId":"qa-scorecard-generate_qa_scorecard","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}},{"name":"template_key","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Override the scorecard template. Defaults to scenario.scorecard_template_key. If the scenario has no template configured and no override is provided, the request is rejected — there is no fallback template.","title":"Template Key"},"description":"Override the scorecard template. Defaults to scenario.scorecard_template_key. If the scenario has no template configured and no override is provided, the request is rejected — there is no fallback template."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QaScorecardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/health":{"get":{"tags":["health"],"summary":"Service health status","description":"Return overall service health with dependency checks.\n\nReturns:\n    - 200: All systems healthy\n    - 503: One or more critical systems unhealthy","operationId":"health-health","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/config":{"get":{"tags":["health"],"summary":"Get feature flags and configuration","description":"Return feature flags and public configuration.","operationId":"health-get_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicAppConfig"}}}}}}},"/pool-status":{"get":{"tags":["health"],"summary":"Database connection pool status","description":"Return database connection pool statistics.\n\nUseful for monitoring connection pool health and detecting leaks.\n\nReturns:\n    - size: Base pool size (configured)\n    - checked_in: Connections available in pool\n    - checked_out: Connections currently in use\n    - overflow: Extra connections beyond base size\n    - max_overflow: Maximum allowed overflow (configured)","operationId":"health-pool_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/scenarios":{"get":{"tags":["scenarios"],"summary":"List Scenarios","description":"List all scenarios with summary information.\n\nWhen the voice-agent feature is off (``VOICE_AGENT_ENABLED`` is false,\nthe default), ``ai_agent`` scenarios are filtered out of the API surface\nentirely. This is defense in depth on top of the seed-time skip: it hides\nthe demo scenarios even in DBs that were seeded before the flag existed,\nso they never reach a client UI or get enumerated.","operationId":"scenarios-list_scenarios","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ScenarioListResponse"},"type":"array","title":"Response Scenarios-List Scenarios"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"post":{"tags":["scenarios"],"summary":"Create Scenario","description":"Create a new scenario.","operationId":"scenarios-create_scenario","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScenarioCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScenarioResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/scenarios/{scenario_id}":{"get":{"tags":["scenarios"],"summary":"Get Scenario","description":"Get a specific scenario by ID.","operationId":"scenarios-get_scenario","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"scenario_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scenario Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScenarioResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["scenarios"],"summary":"Update Scenario","description":"Update an existing scenario.","operationId":"scenarios-update_scenario","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"scenario_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scenario Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScenarioUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ScenarioResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["scenarios"],"summary":"Delete Scenario","description":"Delete a scenario.","operationId":"scenarios-delete_scenario","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"scenario_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Scenario Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/scenarios/tools":{"get":{"tags":["scenarios"],"summary":"List Tools","description":"List all available tools for scenario configuration.","operationId":"scenarios-list_tools","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ToolResponse"},"type":"array","title":"Response Scenarios-List Tools"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/prompts/":{"get":{"tags":["prompts"],"summary":"List Prompts","description":"List all prompts, optionally filtered by type.\n\nArgs:\n    type: Optional filter by prompt type (e.g. 'suggested_responses')","operationId":"prompts-list_prompts","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromptResponse"},"title":"Response Prompts-List Prompts"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["prompts"],"summary":"Create Prompt","description":"Create a new prompt.","operationId":"prompts-create_prompt","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/prompts/{prompt_id}":{"get":{"tags":["prompts"],"summary":"Get Prompt","description":"Get a single prompt by ID.","operationId":"prompts-get_prompt","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Prompt Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["prompts"],"summary":"Update Prompt","description":"Update an existing prompt.","operationId":"prompts-update_prompt","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Prompt Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["prompts"],"summary":"Delete Prompt","description":"Delete a prompt.","operationId":"prompts-delete_prompt","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"prompt_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Prompt Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tools":{"get":{"tags":["tools"],"summary":"List Tools","description":"List all tools (action cards) with summary information.","operationId":"tools-list_tools","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ToolListResponse"},"type":"array","title":"Response Tools-List Tools"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"post":{"tags":["tools"],"summary":"Create Tool","description":"Create a new tool (action card).","operationId":"tools-create_tool","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/tools/catalog":{"get":{"tags":["tools"],"summary":"List Tool Catalog","description":"List action cards for scenario configuration.","operationId":"tools-list_tool_catalog","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"include_inactive","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Inactive"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ToolCatalogResponse"},"title":"Response Tools-List Tool Catalog"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/tools/{tool_id}":{"get":{"tags":["tools"],"summary":"Get Tool","description":"Get a specific tool by ID.","operationId":"tools-get_tool","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"tool_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tool Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["tools"],"summary":"Update Tool","description":"Update an existing tool.","operationId":"tools-update_tool","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"tool_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tool Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ToolResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["tools"],"summary":"Delete Tool","description":"Delete a tool.","operationId":"tools-delete_tool","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"tool_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Tool Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions":{"post":{"tags":["sessions"],"summary":"Create Session","operationId":"sessions-create_session","responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionStartResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/sessions/{session_id}/messages":{"post":{"tags":["sessions"],"summary":"Post Session Message","operationId":"sessions-post_session_message","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SessionMessageCreate"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Sessions-Post Session Message"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/audio-chunk":{"post":{"tags":["sessions"],"summary":"Post Session Audio Chunk","description":"Stream browser-generated audio into an active session's STT handler.\n\nThis route serves training, microphone-test, and uploaded-audio browser\nflows. Production desktop recording uses ``/recording/ws`` instead.","operationId":"sessions-post_session_audio_chunk","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_sessions-post_session_audio_chunk"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/metadata":{"patch":{"tags":["sessions"],"summary":"Update Session Metadata","description":"Update session metadata without creating a transcript entry.","operationId":"sessions-update_session_metadata","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Metadata"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Sessions-Update Session Metadata"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/start-call":{"post":{"tags":["sessions"],"summary":"Start Call","description":"Start a call for this session.\n\nCreates a CallSession record so the call appears in call history immediately.\nUsed by frontend for training calls where ElevenLabs handles audio directly.\n\nArgs:\n    session_id: Session ID (must be created first via POST /sessions)\n    scenario: Optional scenario identifier (e.g., \"debt_collection\")\n    persona_id: Optional training persona practised against (training calls)","operationId":"sessions-start_call","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"scenario","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"}},{"name":"customer_number","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Number"}},{"name":"persona_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Persona Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Sessions-Start Call"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/end-call":{"post":{"tags":["sessions"],"summary":"End Call","description":"End a call and trigger finalization.\n\nFinalizes the CallSession by persisting transcript and generating\nsummary/coaching feedback in the background.\n\nPublishes SSE events to match the 3CX production flow:\n1. Immediately: call_ended (finalized: false) - triggers coaching modal\n2. After finalization: call_ended (finalized: true) - triggers data refresh\n\nArgs:\n    session_id: Session ID","operationId":"sessions-end_call","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"type":"string"},"title":"Response Sessions-End Call"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/stream":{"get":{"tags":["sessions"],"summary":"Session Stream","operationId":"sessions-session_stream","parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"snapshot","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Snapshot"}}],"responses":{"200":{"description":"Successful Response","content":{"text/event-stream":{"itemSchema":{"type":"object","properties":{"data":{"type":"string"},"event":{"type":"string"},"id":{"type":"string"},"retry":{"type":"integer","minimum":0}}}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/sessions/{session_id}/turn-latency":{"post":{"tags":["sessions"],"summary":"Post Turn Latency","description":"Record Leg 4 (SSE delivery) for a turn's VAQI-L sample.\n\nThe frontend posts this once per (session, turn, producer) after the\nfirst streaming envelope for the turn arrives.  The write is an\nupsert — the beacon typically races *ahead* of the orchestrator's\nwrite of legs 1-3 (it fires on first token, the orchestrator writes\nafter the full analyzer pipeline), so we can't require the row to\nalready exist.  Silently no-ops when telemetry is disabled.","operationId":"sessions-post_turn_latency","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TurnLatencyBeacon"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/telephony/{session_id}/end-call":{"post":{"tags":["telephony"],"summary":"End Call","description":"End a call and stop streaming STT.\n\nThis should be called when the telephony system ends the call.\nTriggers call finalization in the background.\n\nPublishes SSE events to match the production flow:\n1. Immediately: call_ended (finalized: false) - triggers coaching modal\n2. After finalization: call_ended (finalized: true) - triggers data refresh","operationId":"telephony-end_call","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"type":"string"},"title":"Response Telephony-End Call"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/telephony/{session_id}/start-streaming":{"post":{"tags":["telephony"],"summary":"Start Streaming","description":"Start audio streaming for a call.\n\nInitializes the streaming transcription handler for receiving audio chunks.\nThe CallSession should already be created via POST /sessions/{id}/start-call.\n\nThis is used for production mock mode (audio file playback), microphone\ntesting, and training mode (where only the AI persona's audio is streamed).\nReal telephony integrations (e.g., 3CX) call start_streaming_handler directly.\n\nArgs:\n    session_id: Session ID for this call\n    scenario: Optional scenario identifier (for orchestrator context)\n    channels: Number of audio channels (1=mono, 2=stereo for speaker diarization).\n              Default is 1 (mono). Use 2 only if audio has separate speaker channels.\n    speaker: Optional fixed speaker label for a single (mono) stream. When\n             set to \"customer\" or \"agent\", every transcribed turn is\n             attributed to that speaker. Used by training mode, which\n             streams only the AI persona's audio as the \"customer\". Only\n             valid for mono (channels=1).","operationId":"telephony-start_streaming","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"scenario","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"}},{"name":"channels","in":"query","required":false,"schema":{"type":"integer","default":1,"title":"Channels"}},{"name":"speaker","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Speaker"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Telephony-Start Streaming"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/telephony/{session_id}/stop-streaming":{"post":{"tags":["telephony"],"summary":"Stop Streaming","description":"Stop an active streaming handler WITHOUT finalizing the call.\n\nReleases STT provider resources (websockets) when a streaming session is\nabandoned before the call is ended/finalized. The training flow uses this\nwhen its ElevenLabs connection fails, drops abnormally, or reports an\noutput format we can't transcribe: the backend handler was already created\nby start-streaming, but no audio will flow and end-call may never run, so\nthe handler would otherwise linger. The CallSession is left untouched — a\nlater end-call still finalizes normally (and is a no-op for the stream).","operationId":"telephony-stop_streaming","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"type":"string"},"title":"Response Telephony-Stop Streaming"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/telephony/{session_id}/scenario":{"patch":{"tags":["telephony"],"summary":"Update Scenario","description":"Update the scenario for an active streaming session.\n\nThis allows changing the scenario mid-call, which will affect\nsubsequent transcript messages sent to the orchestrator.\n\nArgs:\n    session_id: Session ID for this call\n    scenario: New scenario identifier","operationId":"telephony-update_scenario","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}},{"name":"scenario","in":"query","required":true,"schema":{"type":"string","title":"Scenario"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":{"type":"string"},"title":"Response Telephony-Update Scenario"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/integrations/telephony/status":{"get":{"tags":["integrations","telephony"],"summary":"Telephony Status","description":"Report whether a telephony provider is configured.","operationId":"integrations-telephony_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Integrations-Telephony Status"}}}}}}},"/integrations/telephony/config":{"get":{"tags":["integrations","telephony"],"summary":"Get Telephony Config","operationId":"integrations-get_telephony_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TelephonyIntegrationResponse"},{"type":"null"}],"title":"Response Integrations-Get Telephony Config"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"put":{"tags":["integrations","telephony"],"summary":"Upsert Telephony Config","operationId":"integrations-upsert_telephony_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelephonyIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelephonyIntegrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/test":{"post":{"tags":["integrations","telephony"],"summary":"Test Telephony Config","operationId":"integrations-test_telephony_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TelephonyTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Integrations-Test Telephony Config"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/threecx/test-call":{"post":{"tags":["integrations","telephony"],"summary":"Place Threecx Test Call","description":"Dial through the saved Route Point and play a bundled static message.\n\nThis is deliberately a transport diagnostic, not an AI call: it does not\nresolve a scenario, create a call session, or invoke STT/LLM/TTS services.","operationId":"integrations-place_threecx_test_call","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreeCXTestCallRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ThreeCXTestCallResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/events/stream":{"get":{"tags":["integrations","telephony"],"summary":"Telephony Event Stream","description":"SSE stream for telephony call events.\n\nUsed by both desktop and webapp to receive real-time call notifications.\nNote: Desktop status tracking is handled separately via the heartbeat endpoint.\n\nIMPORTANT: This endpoint uses current_active_user_no_session to avoid holding\na database connection open for the lifetime of the SSE stream. This prevents\nconnection pool exhaustion when many clients are connected.\n\nKeep-alive pings are handled automatically by FastAPI's EventSourceResponse (every 15s).","operationId":"integrations-telephony_event_stream","responses":{"200":{"description":"Successful Response","content":{"text/event-stream":{"itemSchema":{"type":"object","properties":{"data":{"type":"string"},"event":{"type":"string"},"id":{"type":"string"},"retry":{"type":"integer","minimum":0}}}}}}}}},"/integrations/telephony/awsconnect/status":{"get":{"tags":["integrations","telephony"],"summary":"Awsconnect Status","description":"Report whether AWS Connect is configured and enabled.","operationId":"integrations-awsconnect_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Integrations-Awsconnect Status"}}}}}}},"/integrations/telephony/awsconnect/config":{"get":{"tags":["integrations","telephony"],"summary":"Get Awsconnect Config","description":"Get current AWS Connect configuration.","operationId":"integrations-get_awsconnect_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AWSConnectIntegrationResponse"},{"type":"null"}],"title":"Response Integrations-Get Awsconnect Config"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"put":{"tags":["integrations","telephony"],"summary":"Upsert Awsconnect Config","description":"Create or update AWS Connect configuration.\n\nRequires at least one agent mapping to be enabled.","operationId":"integrations-upsert_awsconnect_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AWSConnectIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AWSConnectIntegrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/awsconnect/test":{"post":{"tags":["integrations","telephony"],"summary":"Test Awsconnect Config","description":"Test AWS Connect configuration.\n\nTests:\n1. AWS credentials are valid (via STS GetCallerIdentity)\n2. KVS permissions work (via ListStreams - tests kinesisvideo access)\n3. Agent discovery works (optional - via connect:ListUsers)\n\nThe core integration requires KVS read permissions. Connect API permissions\nare only needed for agent discovery (optional feature).","operationId":"integrations-test_awsconnect_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AWSConnectTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Integrations-Test Awsconnect Config"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/awsconnect/agents":{"post":{"tags":["integrations","telephony"],"summary":"List Agents","description":"List agents from AWS Connect instance.\n\nReturns agent usernames, ARNs, and display names for mapping to Whispa users.","operationId":"integrations-list_agents","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AWSConnectAgentListRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AWSConnectAgent"},"type":"array","title":"Response Integrations-List Agents"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/tcn/status":{"get":{"tags":["integrations","telephony"],"summary":"Tcn Status","description":"Report whether TCN is configured, enabled, and currently connected.","operationId":"integrations-tcn_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Integrations-Tcn Status"}}}}}}},"/integrations/telephony/tcn/config":{"get":{"tags":["integrations","telephony"],"summary":"Get Tcn Config","description":"Get current TCN configuration.","operationId":"integrations-get_tcn_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TCNIntegrationResponse"},{"type":"null"}],"title":"Response Integrations-Get Tcn Config"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"put":{"tags":["integrations","telephony"],"summary":"Upsert Tcn Config","description":"Create or update TCN configuration.","operationId":"integrations-upsert_tcn_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TCNIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TCNIntegrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/tcn/test":{"post":{"tags":["integrations","telephony"],"summary":"Test Tcn Config","description":"Test TCN PAT by opening the manager state stream and reading one frame.","operationId":"integrations-test_tcn_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TCNTestRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Integrations-Test Tcn Config"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/tcn/agents":{"post":{"tags":["integrations","telephony"],"summary":"List Tcn Agents","description":"List agents from the TCN org for mapping to Whispa users.\n\nUses the legacy org user-agents endpoint, which works with the manager PAT.\nReturns ``tcn_user_id`` + ``name`` + ``email`` so the UI can pre-fill the\nmapping and auto-suggest links by matching email to a Whispa account.","operationId":"integrations-list_tcn_agents","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TCNAgentListRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TCNAgent"},"type":"array","title":"Response Integrations-List Tcn Agents"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/integrations/telephony/twilio/status":{"get":{"tags":["integrations","telephony"],"summary":"Twilio Voice Status","description":"Report whether Twilio Voice is configured and can place calls.","operationId":"integrations-twilio_voice_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Integrations-Twilio Voice Status"}}}}}}},"/integrations/telephony/twilio/config":{"get":{"tags":["integrations","telephony"],"summary":"Get Twilio Voice Config","description":"Get current Twilio Voice configuration.","operationId":"integrations-get_twilio_voice_config","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/TwilioVoiceIntegrationResponse"},{"type":"null"}],"title":"Response Integrations-Get Twilio Voice Config"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"put":{"tags":["integrations","telephony"],"summary":"Upsert Twilio Voice Config","description":"Create or update Twilio Voice configuration.","operationId":"integrations-upsert_twilio_voice_config","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwilioVoiceIntegrationConfig"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwilioVoiceIntegrationResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/uploaded-calls/upload":{"post":{"tags":["uploaded-calls"],"summary":"Upload Call Recording","description":"Upload and process a call recording (Admin only).\n\nAccepts MP3 or WAV audio files (max 100MB). Transcription uses the\nconfigured TELEPHONY_TRANSCRIPTION_PROVIDER vendor's batch API (ElevenLabs\nScribe v1, Deepgram Nova-3, or AssemblyAI). Summary and coaching feedback\nare generated automatically.\n\nArgs:\n    audio_file: Audio file (MP3 or WAV)\n    assigned_user_id: Optional UUID of user to assign call to\n    scenario_name: Optional scenario name to use for classification\n    call_date: Optional ISO datetime string for when call was conducted\n\nReturns:\n    UploadCallResponse with session_id and transcript info","operationId":"uploaded-calls-upload_call_recording","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_uploaded-calls-upload_call_recording"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadCallResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/feedback":{"post":{"tags":["feedback"],"summary":"Submit Feedback","description":"Submit feedback with optional screenshot and call reference.\n\nArgs:\n    feedback_type: Type of feedback (bug_report, suggestion, other)\n    description: Detailed description of the feedback (min 10 chars)\n    screenshot: Optional screenshot image (PNG, JPEG, WebP, max 5MB)\n    call_id: Optional call ID to associate feedback with\n\nReturns:\n    FeedbackResponse indicating success","operationId":"feedback-submit_feedback","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_feedback-submit_feedback"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FeedbackResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/egress/calls":{"get":{"tags":["egress"],"summary":"List Calls","description":"Completed calls, newest first by (started_at, id), optionally human-only.\n\nKeep all filters unchanged when following next_cursor. Save checkpoint\nafter storing the selected backfill to discover subsequent changes.\nThis is a live listing, not a frozen historical snapshot.","operationId":"egress-list_calls","parameters":[{"name":"answered_by","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/AnsweredBy"},{"type":"null"}],"title":"Answered By"}},{"name":"call_mode","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CallMode"},{"type":"null"}],"title":"Call Mode"}},{"name":"call_direction","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CallDirection"},{"type":"null"}],"title":"Call Direction"}},{"name":"account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only calls linked to this Whispa account","title":"Account Id"},"description":"Only calls linked to this Whispa account"},{"name":"started_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only calls that started at or after this instant","title":"Started After"},"description":"Only calls that started at or after this instant"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":100,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressDiscoveryPage"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/changes":{"get":{"tags":["egress"],"summary":"List Call Changes","description":"Resumable latest-state feed of completed calls, in revision order.\n\nWithout a cursor, backfills all matching calls. Drain next_cursor pages,\ndurably queue results, then save checkpoint for the next poll. Keep the\nfilters unchanged. In-flight writers are deferred, never skipped. Repeated\nwrites coalesce; this is not an audit log. External Langfuse changes and\ndeletions/filter exits are not emitted. Fetch bundles to assess readiness.","operationId":"egress-list_call_changes","parameters":[{"name":"answered_by","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/AnsweredBy"},{"type":"null"}],"title":"Answered By"}},{"name":"call_mode","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CallMode"},{"type":"null"}],"title":"Call Mode"}},{"name":"call_direction","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/CallDirection"},{"type":"null"}],"title":"Call Direction"}},{"name":"account_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only calls linked to this Whispa account","title":"Account Id"},"description":"Only calls linked to this Whispa account"},{"name":"started_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"Only calls that started at or after this instant","title":"Started After"},"description":"Only calls that started at or after this instant"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":100,"title":"Limit"}},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Cursor"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressDiscoveryPage"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}":{"get":{"tags":["egress"],"summary":"Get Call Metadata","description":"Allowlisted metadata for a single call.","operationId":"egress-get_call_metadata","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressCallMetadata"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/users/{user_id}/recent-calls":{"get":{"tags":["egress"],"summary":"Get User Recent Calls","description":"A user's most recent calls (metadata only), newest first.\n\nLets the agent locate the right call when feedback arrives without a\ncall_id.","operationId":"egress-get_user_recent_calls","parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":50,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/EgressCallMetadata"},"title":"Response Egress-Get User Recent Calls"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/transcript":{"get":{"tags":["egress"],"summary":"Get Call Transcript","description":"The call's transcript chunks with scrubbed text.","operationId":"egress-get_call_transcript","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressTranscriptResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/summary":{"get":{"tags":["egress"],"summary":"Get Call Summary","description":"The call's structured and/or markdown summary, scrubbed.","operationId":"egress-get_call_summary","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressSummaryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/tool-calls":{"get":{"tags":["egress"],"summary":"Get Call Tool Calls","description":"Terminal autonomous-agent tool calls with scrubbed arguments/results.","operationId":"egress-get_call_tool_calls","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressToolCallsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/latency":{"get":{"tags":["egress"],"summary":"Get Call Latency","description":"The call's latency rollup and its per-turn autonomous-voice rows.\n\nThe rollup is written when the call finalizes; the rows exist as soon as\neach turn is timed, so a call still in progress returns turns and no\nsummary. Everything here is numeric or a status label.","operationId":"egress-get_call_latency","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressLatencyResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/idv":{"get":{"tags":["egress"],"summary":"Get Call Idv","description":"How identity verification went, answer by answer, without any value.\n\nWritten when an AI-agent call finalizes with IDV_RECORD_ENABLED on; null\nfor other calls and for calls finalized before it was on.","operationId":"egress-get_call_idv","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressIdvResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/outcome":{"get":{"tags":["egress"],"summary":"Get Call Outcome","description":"Structured post-call outcome and deterministic autonomous facts.","operationId":"egress-get_call_outcome","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressOutcomeResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/coaching":{"get":{"tags":["egress"],"summary":"Get Call Coaching","description":"Structured post-call coaching with all model-written text scrubbed.","operationId":"egress-get_call_coaching","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressCoachingResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/scorecard":{"get":{"tags":["egress"],"summary":"Get Call Scorecard","description":"The call's QA scorecard — per-item scores with all free text scrubbed.\n\n404s when the call has no scorecard (not every scenario runs one), distinct\nfrom the call-not-found 404 by its detail message.","operationId":"egress-get_call_scorecard","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressScorecardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/traces":{"get":{"tags":["egress"],"summary":"Get Call Traces","description":"The call's Langfuse traces, proxied server-side and scrubbed.","operationId":"egress-get_call_traces","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressTracesResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/egress/calls/{call_id}/bundle":{"get":{"tags":["egress"],"summary":"Get Call Bundle","description":"One-shot, partial-tolerant context for automated call analysis.\n\nEvery text-bearing section uses the same allowlist + scrub serializer as\nits individual endpoint. Missing, malformed, upstream-failed, or\nscrub-failed sections are withheld and named in ``omitted``; one optional\nartifact can therefore never hide the rest of a call from the analyzer.","operationId":"egress-get_call_bundle","parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EgressCallBundle"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/custom-action-cards/runtime":{"get":{"tags":["custom-action-cards"],"summary":"List Runtime Custom Action Cards","description":"List active custom cards for runtime rendering.","operationId":"custom-action-cards-list_runtime_custom_action_cards","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CustomActionCardRuntimeResponse"},"type":"array","title":"Response Custom-Action-Cards-List Runtime Custom Action Cards"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/custom-action-cards/admin":{"get":{"tags":["custom-action-cards"],"summary":"List Custom Action Cards Admin","description":"List all custom cards for admin management.","operationId":"custom-action-cards-list_custom_action_cards_admin","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CustomActionCardResponse"},"type":"array","title":"Response Custom-Action-Cards-List Custom Action Cards Admin"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/custom-action-cards/generate":{"post":{"tags":["custom-action-cards"],"summary":"Generate Custom Action Card Source","description":"Generate custom action card source code from schema and UI prompt.","operationId":"custom-action-cards-generate_custom_action_card_source","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardGenerateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardGenerateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/custom-action-cards/generate-contract":{"post":{"tags":["custom-action-cards"],"summary":"Generate Custom Action Card Contract","description":"Generate tool contract (name/description/schema/ui prompt) from intent.","operationId":"custom-action-cards-generate_custom_action_card_contract","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardContractGenerateRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardContractGenerateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/custom-action-cards":{"post":{"tags":["custom-action-cards"],"summary":"Create Custom Action Card","description":"Create a custom action card (admin only).","operationId":"custom-action-cards-create_custom_action_card","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/custom-action-cards/{card_id}":{"get":{"tags":["custom-action-cards"],"summary":"Get Custom Action Card","description":"Get one custom action card for admin editing.","operationId":"custom-action-cards-get_custom_action_card","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Card Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["custom-action-cards"],"summary":"Update Custom Action Card","description":"Update an existing custom action card (admin only).","operationId":"custom-action-cards-update_custom_action_card","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Card Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomActionCardResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["custom-action-cards"],"summary":"Delete Custom Action Card","description":"Delete a custom action card (admin only).","operationId":"custom-action-cards-delete_custom_action_card","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"card_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Card Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/training-personas":{"get":{"tags":["training-personas"],"summary":"List Training Personas","description":"List active training personas for browsing (all users).\n\nUses the slim list schema: the behavioural script (backstory /\nprompt_override / resolved_prompt) is excluded so trainees can't read how\nthe simulated customer will behave.","operationId":"training-personas-list_training_personas","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"scenario_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scenario Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrainingPersonaListResponse"},"title":"Response Training-Personas-List Training Personas"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["training-personas"],"summary":"Create Training Persona","description":"Create a training persona (admin only).","operationId":"training-personas-create_training_persona","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingPersonaCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingPersonaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/training-personas/admin":{"get":{"tags":["training-personas"],"summary":"List Training Personas Admin","description":"List all training personas (incl. inactive) for admin management.","operationId":"training-personas-list_training_personas_admin","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"scenario_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scenario Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TrainingPersonaResponse"},"title":"Response Training-Personas-List Training Personas Admin"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/training-personas/{persona_id}":{"get":{"tags":["training-personas"],"summary":"Get Training Persona","description":"Get one training persona (any active user — needed to start a call).","operationId":"training-personas-get_training_persona","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"persona_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Persona Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingPersonaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["training-personas"],"summary":"Update Training Persona","description":"Update an existing training persona (admin only).","operationId":"training-personas-update_training_persona","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"persona_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Persona Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingPersonaUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingPersonaResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["training-personas"],"summary":"Delete Training Persona","description":"Delete a training persona (admin only).","operationId":"training-personas-delete_training_persona","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"persona_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Persona Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/training-agent/status":{"get":{"tags":["training-agent"],"summary":"Get Training Agent Status","description":"Cheap config check (no ElevenLabs call) so the UI can hint when the\ndeployment is missing ELEVENLABS_API_KEY instead of failing at call start.","operationId":"training-agent-get_training_agent_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingAgentStatus"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/training-agent/signed-url":{"get":{"tags":["training-agent"],"summary":"Get Training Agent Signed Url","description":"Mint a signed URL for a training call.\n\nThe agent is provisioned automatically on first use, so a fresh\ndeployment only needs ELEVENLABS_API_KEY configured.","operationId":"training-agent-get_training_agent_signed_url","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingAgentConnection"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/chat/{session_id}/history":{"get":{"tags":["chat"],"summary":"Get Chat History","description":"Return the chat history for a session (cached or rebuilt from DB).","operationId":"chat-get_chat_history","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/ChatHistoryResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/live-monitor/calls":{"get":{"tags":["live-monitor"],"summary":"List Active Calls","description":"List all currently active calls.","operationId":"live-monitor-list_active_calls","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActiveCallsResponse"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/live-monitor/sessions/{session_id}/snapshot":{"get":{"tags":["live-monitor"],"summary":"Get Session Snapshot","description":"Get a full snapshot of an active session for supervisor bootstrap.","operationId":"live-monitor-get_session_snapshot","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/SessionSnapshotResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/live-monitor/sessions/{session_id}/status":{"get":{"tags":["live-monitor"],"summary":"Get Session Monitor Status","description":"Refresh supervisor metadata and late CRM links without a full snapshot.","operationId":"live-monitor-get_session_monitor_status","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/SessionMonitorStatusResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/live-monitor/sessions/{session_id}/audio":{"get":{"tags":["live-monitor"],"summary":"Stream Session Audio","description":"Live audio of an in-progress call, as a chunked binary stream.\n\nRaw interleaved stereo PCM (s16le, customer left / agent right; sample\nrate and format in the ``X-Audio-*`` headers). AI calls tee out of the\n3CX transport at the points where audio actually crosses the wire;\ncopilot calls tee the desktop capture feed at the streaming handler. The\nresponse ends when the call does. 404 when the session has no live audio\nfeed (ended, or a copilot call whose desktop isn't streaming audio).","operationId":"live-monitor-stream_session_audio","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":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/ai-calls/voices":{"get":{"tags":["ai-calls"],"summary":"List Voice Catalog","description":"The configured TTS voices a scenario or single dial can use.\n\nCartesia is proxied live and cached briefly; Deepgram exposes Whispa's\nauditioned supported subset. One configured provider failing does not hide\nthe other. Open to any signed-in user because voice metadata is not\nprivileged; rendering a preview stays admin because it costs credits.","operationId":"ai-calls-list_voice_catalog","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"language","in":"query","required":false,"schema":{"type":"string","maxLength":16,"description":"ISO 639-1 code or language-locale pair. The default keeps each provider to Australian English; pass 'en' to widen it.","default":"en-AU","title":"Language"},"description":"ISO 639-1 code or language-locale pair. The default keeps each provider to Australian English; pass 'en' to widen it."},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(masculine|feminine|gender_neutral)$"},{"type":"null"}],"description":"Optional provider-neutral gender filter.","title":"Gender"},"description":"Optional provider-neutral gender filter."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceCatalogResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/ai-calls/voices/{voice_id}/preview":{"get":{"tags":["ai-calls"],"summary":"Preview Voice","description":"Render a short sample of ``voice_id`` at the telephony sample rate.\n\n8 kHz, not studio quality — the pipeline renders straight to 8 kHz for the\n3CX stream, and band-limiting is exactly where voices stop sounding alike.","operationId":"ai-calls-preview_voice","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"voice_id","in":"path","required":true,"schema":{"type":"string","title":"Voice Id"}},{"name":"scenario","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"description":"ai_agent scenario whose opening line the preview should speak — the truest audition, since it is the exact wording that scenario greets with, placeholders rendered as a real dial renders them. Falls back to the generic sample if it cannot be resolved.","title":"Scenario"},"description":"ai_agent scenario whose opening line the preview should speak — the truest audition, since it is the exact wording that scenario greets with, placeholders rendered as a real dial renders them. Falls back to the generic sample if it cannot be resolved."},{"name":"text","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Explicit line to speak instead of the scenario's greeting — a candidate opening line. Still a `$placeholder` template: combined with `scenario` it renders against that scenario's brand context, so a draft opener auditions as a dial would speak it. Truncated to 400 characters — a longer line is still auditioned, just not to the end.","title":"Text"},"description":"Explicit line to speak instead of the scenario's greeting — a candidate opening line. Still a `$placeholder` template: combined with `scenario` it renders against that scenario's brand context, so a draft opener auditions as a dial would speak it. Truncated to 400 characters — a longer line is still auditioned, just not to the end."},{"name":"model","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"description":"Cartesia model to audition. Omit to use the scenario's configured model, then the runtime default.","title":"Model"},"description":"Cartesia model to audition. Omit to use the scenario's configured model, then the runtime default."}],"responses":{"200":{"description":"8 kHz mono WAV — the telephony band the caller hears.","content":{"audio/wav":{}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/ai-calls":{"post":{"tags":["ai-calls"],"summary":"Place Call","description":"Place an outbound AI-collector call to ``phone_number``.\n\nAdmin-only: placing outbound PSTN calls is a privileged, billable action.\nReturns the ``session_id`` you should subscribe to via\n``GET /sessions/{session_id}/stream`` for live transcripts and action cards.","operationId":"ai-calls-place_call","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceAiCallRequest"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlaceAiCallResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/ai-calls/{session_id}":{"delete":{"tags":["ai-calls"],"summary":"Hangup","description":"Hang up an in-progress AI call.\n\nReuses the standard live-call ownership gate so admins/supervisors can end\na stuck demo call on someone else's behalf, mirroring ``/sessions/{id}/end-call``.","operationId":"ai-calls-hangup","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"$ref":"#/components/schemas/HangupAiCallResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns":{"get":{"tags":["campaigns"],"summary":"List Campaigns","description":"List campaigns with per-status progress counts (admin only).\nArchived campaigns are hidden unless ``include_archived`` is set.","operationId":"campaigns-list_campaigns","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"include_archived","in":"query","required":false,"schema":{"type":"boolean","description":"Include archived campaigns in the list.","default":false,"title":"Include Archived"},"description":"Include archived campaigns in the list."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CampaignRead"},"title":"Response Campaigns-List Campaigns"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["campaigns"],"summary":"Create Campaign","description":"Create a draft campaign for an ai_agent scenario (admin only).","operationId":"campaigns-create_campaign","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignCreate"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/pause-all":{"post":{"tags":["campaigns"],"summary":"Pause All Campaigns","description":"Pause every active campaign at once and return the ones that were\npaused. Queued rows stay put and calls already in flight finish; each\ncampaign is resumed by activating it again (admin only).","operationId":"campaigns-pause_all_campaigns","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CampaignRead"},"type":"array","title":"Response Campaigns-Pause All Campaigns"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/campaigns/do-not-call":{"get":{"tags":["campaigns"],"summary":"List Do Not Call","description":"List do-not-call entries (admin only).","operationId":"campaigns-list_do_not_call","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/DoNotCallRead"},"type":"array","title":"Response Campaigns-List Do Not Call"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"post":{"tags":["campaigns"],"summary":"Create Do Not Call","description":"Add a do-not-call entry: a number and/or an account (admin only).","operationId":"campaigns-create_do_not_call","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DoNotCallCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DoNotCallRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/campaigns/do-not-call/{entry_id}":{"delete":{"tags":["campaigns"],"summary":"Delete Do Not Call","description":"Lift a do-not-call entry (admin only). Deletion is deliberate: DNC\nblocks are permanent while the row exists.","operationId":"campaigns-delete_do_not_call","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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"}}}}}}},"/campaigns/reviews":{"get":{"tags":["campaigns"],"summary":"List Reviews","description":"Accounts waiting on an operator decision across every campaign, longest\nwait first (admin only). Decide each through the membership status\nendpoint, passing the item's ``review_call_session_id``.","operationId":"campaigns-list_reviews","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"reason","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"enum":["inbound_callback","do_not_contact_request","wrong_person","refused","inbound_engaged"],"type":"string"}},{"type":"null"}],"description":"Review reasons to include (repeatable). Omit for all.","title":"Reason"},"description":"Review reasons to include (repeatable). Omit for all."},{"name":"campaign_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only accounts under review in this campaign.","title":"Campaign Id"},"description":"Only accounts under review in this campaign."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Free-text search (case-insensitive) across display name, account number, external id and phone.","title":"Q"},"description":"Free-text search (case-insensitive) across display name, account number, external id and phone."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_ReviewQueueItem_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/callbacks":{"get":{"tags":["campaigns"],"summary":"List Callback Requests","description":"List human-owned callback requests in scheduled-time order (admin only).","operationId":"campaigns-list_callback_requests","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"include_closed","in":"query","required":false,"schema":{"type":"boolean","description":"Include completed and cancelled callback requests.","default":false,"title":"Include Closed"},"description":"Include completed and cancelled callback requests."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CallbackRequestRead"},"title":"Response Campaigns-List Callback Requests"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/callbacks/{callback_id}":{"patch":{"tags":["campaigns"],"summary":"Update Callback Request","description":"Complete or cancel a human callback and release its autonomous hold.","operationId":"campaigns-update_callback_request","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"callback_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Callback Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackRequestUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallbackRequestRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/accounts/{account_id}":{"get":{"tags":["campaigns"],"summary":"List Account Campaigns","description":"Every campaign an account is currently enrolled in (admin only).","operationId":"campaigns-list_account_campaigns","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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":{"type":"array","items":{"$ref":"#/components/schemas/AccountCampaignMembershipRead"},"title":"Response Campaigns-List Account Campaigns"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}":{"get":{"tags":["campaigns"],"summary":"Get Campaign","description":"Campaign detail: progress counts + per-account status (admin only).","operationId":"campaigns-get_campaign","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CampaignDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"patch":{"tags":["campaigns"],"summary":"Update Campaign","description":"Update a campaign's configuration: name, supervision, parallel-call\nlimit, voice, and calling-window overrides. Partial — only the fields\npresent in the body are applied.\n\nThis does not change the campaign lifecycle: a paused campaign stays paused,\nwhile an active campaign applies the new settings on the next scheduler\ntick (campaign config is read at dispatch time, so nothing is re-enqueued).","operationId":"campaigns-update_campaign","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CampaignUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["campaigns"],"summary":"Delete Campaign","description":"Hard-delete a campaign that never placed a call — memberships and\nqueue rows go with it. Campaigns with call history must be archived\ninstead (409) (admin only).","operationId":"campaigns-delete_campaign","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/summary":{"get":{"tags":["campaigns"],"summary":"Get Campaign Summary","description":"Campaign progress, live calls and next-up queue without account rows.","operationId":"campaigns-get_campaign_summary","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CampaignSummary"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/accounts":{"get":{"tags":["campaigns"],"summary":"List Campaign Accounts","description":"Page through campaign accounts in stable name/id order (admin only).","operationId":"campaigns-list_campaign_accounts","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Free-text search (case-insensitive) across display name, account number, external id and phone.","title":"Q"},"description":"Free-text search (case-insensitive) across display name, account number, external id and phone."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Size"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_CampaignAccountRead_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"post":{"tags":["campaigns"],"summary":"Add Campaign Accounts","description":"Add provider accounts (by external id) to a campaign (admin only).\n\nAccounts are cached into the working set on the way in; on an active\ncampaign the new accounts are scheduled immediately (gate at enqueue).","operationId":"campaigns-add_campaign_accounts","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/AddCampaignAccountsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCampaignAccountsResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/accounts/preview":{"post":{"tags":["campaigns"],"summary":"Preview Campaign Accounts","description":"Summarize a filtered accounts selection without changing membership.","operationId":"campaigns-preview_campaign_accounts","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CampaignAccountsPreviewRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAccountsPreviewResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/accounts/{campaign_account_id}/claim":{"post":{"tags":["campaigns"],"summary":"Transfer Campaign Account Authority","description":"Explicitly move an account's autonomous dial authority here.","operationId":"campaigns-transfer_campaign_account_authority","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"campaign_account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Account Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAccountTransferRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignDetail"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/accounts/{campaign_account_id}":{"delete":{"tags":["campaigns"],"summary":"Remove Campaign Account","description":"Remove an account from a campaign and cancel its queued calls.","operationId":"campaigns-remove_campaign_account","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"campaign_account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Account Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/accounts/{campaign_account_id}/status":{"post":{"tags":["campaigns"],"summary":"Update Campaign Account Status","description":"Apply an operator decision to a membership: resolve, remove, exhaust,\nescalate, block with do-not-contact, or resume dialling — how a review\nconcludes.","operationId":"campaigns-update_campaign_account_status","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"campaign_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Id"}},{"name":"campaign_account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Campaign Account Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignAccountStatusUpdate"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/activate":{"post":{"tags":["campaigns"],"summary":"Activate Campaign","description":"Activate a draft/paused campaign: every account is gate-checked and\nscheduled into its next allowed slot (admin only).","operationId":"campaigns-activate_campaign","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CampaignActivateResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/pause":{"post":{"tags":["campaigns"],"summary":"Pause Campaign","description":"Pause an active campaign. Queued rows stay put; the scheduler skips\nthem until the campaign is activated again (admin only).","operationId":"campaigns-pause_campaign","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CampaignRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/archive":{"post":{"tags":["campaigns"],"summary":"Archive Campaign","description":"Archive a campaign: hidden from the default list, activation and new\naccounts refused until unarchived. An active campaign is paused on the\nway out, so its queued calls stop dialing (admin only).","operationId":"campaigns-archive_campaign","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CampaignRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/campaigns/{campaign_id}/unarchive":{"post":{"tags":["campaigns"],"summary":"Unarchive Campaign","description":"Bring an archived campaign back, in its pre-archive lifecycle status\n(admin only).","operationId":"campaigns-unarchive_campaign","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CampaignRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/inbound-routes":{"get":{"tags":["inbound-routes"],"summary":"List Inbound Routes","operationId":"inbound-routes-list_inbound_routes","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/InboundRouteRead"},"type":"array","title":"Response Inbound-Routes-List Inbound Routes"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"post":{"tags":["inbound-routes"],"summary":"Create Inbound Route","operationId":"inbound-routes-create_inbound_route","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundRouteCreate"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundRouteRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/inbound-routes/{route_id}":{"get":{"tags":["inbound-routes"],"summary":"Get Inbound Route","operationId":"inbound-routes-get_inbound_route","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"route_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Route Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundRouteRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"put":{"tags":["inbound-routes"],"summary":"Update Inbound Route","operationId":"inbound-routes-update_inbound_route","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"route_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Route Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundRouteUpdate"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InboundRouteRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["inbound-routes"],"summary":"Delete Inbound Route","operationId":"inbound-routes-delete_inbound_route","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"route_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Route Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/search":{"get":{"tags":["accounts"],"summary":"Search Accounts","description":"Paginated, filterable working set of the active CRM provider (admin\nonly). Backs the Accounts table and the campaign add-accounts picker.","operationId":"accounts-search_accounts","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"sort_by","in":"query","required":false,"schema":{"enum":["display_name","account_number","phone","account_status","outstanding_amount","arrears_amount","last_activity_at","synced_at","created_at"],"type":"string","description":"Column to sort by: display_name, account_number, phone, account_status, outstanding_amount, arrears_amount, last_activity_at, synced_at, created_at.","default":"display_name","title":"Sort By"},"description":"Column to sort by: display_name, account_number, phone, account_status, outstanding_amount, arrears_amount, last_activity_at, synced_at, created_at."},{"name":"sort_order","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","description":"Sort direction: asc or desc.","default":"asc","title":"Sort Order"},"description":"Sort direction: asc or desc."},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"size","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Size"}},{"name":"demo_market","in":"query","required":false,"schema":{"anyOf":[{"enum":["au","us"],"type":"string"},{"type":"null"}],"title":"Demo Market"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Free-text search (case-insensitive) across display name, account number, email, external id and phone.","title":"Q"},"description":"Free-text search (case-insensitive) across display name, account number, email, external id and phone."},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Provider status values to include (case-insensitive, repeatable). Omit for every status.","title":"Status"},"description":"Provider status values to include (case-insensitive, repeatable). Omit for every status."},{"name":"campaign_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only accounts with a membership in this campaign.","title":"Campaign Id"},"description":"Only accounts with a membership in this campaign."},{"name":"campaign_assignment","in":"query","required":false,"schema":{"anyOf":[{"enum":["assigned","unassigned","multiple","review"],"type":"string"},{"type":"null"}],"description":"Filter by current campaign assignment count, or 'review' for accounts waiting on an operator decision.","title":"Campaign Assignment"},"description":"Filter by current campaign assignment count, or 'review' for accounts waiting on an operator decision."},{"name":"timezone_status","in":"query","required":false,"schema":{"anyOf":[{"enum":["unknown","manual"],"type":"string"},{"type":"null"}],"description":"'unknown': no timezone, so the gate will not call the account. 'manual': an operator set the timezone.","title":"Timezone Status"},"description":"'unknown': no timezone, so the gate will not call the account. 'manual': an operator set the timezone."},{"name":"called","in":"query","required":false,"schema":{"anyOf":[{"enum":["account","customer","never"],"type":"string"},{"type":"null"}],"description":"'account': a call is linked to this account. 'customer': a call is linked to this account or another account of the same customer. 'never': neither.","title":"Called"},"description":"'account': a call is linked to this account. 'customer': a call is linked to this account or another account of the same customer. 'never': neither."},{"name":"min_balance","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive lower bound on outstanding amount.","title":"Min Balance"},"description":"Inclusive lower bound on outstanding amount."},{"name":"max_balance","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive upper bound on outstanding amount.","title":"Max Balance"},"description":"Inclusive upper bound on outstanding amount."},{"name":"min_arrears","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive lower bound on arrears amount.","title":"Min Arrears"},"description":"Inclusive lower bound on arrears amount."},{"name":"max_arrears","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive upper bound on arrears amount.","title":"Max Arrears"},"description":"Inclusive upper bound on arrears amount."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Page_AccountSearchRead_"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/facets":{"get":{"tags":["accounts"],"summary":"Account Facets","description":"Filter vocabulary for the accounts table (admin only): the provider\nstatus values actually present with their counts, and the outstanding /\narrears bounds. Computed over the whole visible working set, so narrowing\nthe filter never removes options from the menu.","operationId":"accounts-account_facets","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"demo_market","in":"query","required":false,"schema":{"anyOf":[{"enum":["au","us"],"type":"string"},{"type":"null"}],"title":"Demo Market"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountFacetsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/collections-summary":{"get":{"tags":["accounts"],"summary":"Collections Summary","description":"Money outcomes of the filtered working set (admin only): original /\noutstanding / collected totals and a per-collection-stage breakdown.\n\nTakes the same filter params as ``/search`` and evaluates the same\npredicate, so the summary cards always describe exactly the rows in the\ntable beneath them — including a single campaign via ``campaign_id``.","operationId":"accounts-collections_summary","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"demo_market","in":"query","required":false,"schema":{"anyOf":[{"enum":["au","us"],"type":"string"},{"type":"null"}],"title":"Demo Market"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Free-text search (case-insensitive) across display name, account number, email, external id and phone.","title":"Q"},"description":"Free-text search (case-insensitive) across display name, account number, email, external id and phone."},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Provider status values to include (case-insensitive, repeatable). Omit for every status.","title":"Status"},"description":"Provider status values to include (case-insensitive, repeatable). Omit for every status."},{"name":"campaign_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only accounts with a membership in this campaign.","title":"Campaign Id"},"description":"Only accounts with a membership in this campaign."},{"name":"campaign_assignment","in":"query","required":false,"schema":{"anyOf":[{"enum":["assigned","unassigned","multiple","review"],"type":"string"},{"type":"null"}],"description":"Filter by current campaign assignment count, or 'review' for accounts waiting on an operator decision.","title":"Campaign Assignment"},"description":"Filter by current campaign assignment count, or 'review' for accounts waiting on an operator decision."},{"name":"timezone_status","in":"query","required":false,"schema":{"anyOf":[{"enum":["unknown","manual"],"type":"string"},{"type":"null"}],"description":"'unknown': no timezone, so the gate will not call the account. 'manual': an operator set the timezone.","title":"Timezone Status"},"description":"'unknown': no timezone, so the gate will not call the account. 'manual': an operator set the timezone."},{"name":"called","in":"query","required":false,"schema":{"anyOf":[{"enum":["account","customer","never"],"type":"string"},{"type":"null"}],"description":"'account': a call is linked to this account. 'customer': a call is linked to this account or another account of the same customer. 'never': neither.","title":"Called"},"description":"'account': a call is linked to this account. 'customer': a call is linked to this account or another account of the same customer. 'never': neither."},{"name":"min_balance","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive lower bound on outstanding amount.","title":"Min Balance"},"description":"Inclusive lower bound on outstanding amount."},{"name":"max_balance","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive upper bound on outstanding amount.","title":"Max Balance"},"description":"Inclusive upper bound on outstanding amount."},{"name":"min_arrears","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive lower bound on arrears amount.","title":"Min Arrears"},"description":"Inclusive lower bound on arrears amount."},{"name":"max_arrears","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive upper bound on arrears amount.","title":"Max Arrears"},"description":"Inclusive upper bound on arrears amount."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionsSummaryRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/export":{"get":{"tags":["accounts"],"summary":"Export Accounts","description":"The current accounts filter as a CSV download (admin only).\n\nTakes the same filter params as ``/search`` and evaluates the same\npredicate, so an export always matches the table it was taken from.\n``external_id`` is the first column, which is what the add-accounts and\nsync-by-ids paste boxes read — an export round-trips without editing.","operationId":"accounts-export_accounts","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"sort_by","in":"query","required":false,"schema":{"enum":["display_name","account_number","phone","account_status","outstanding_amount","arrears_amount","last_activity_at","synced_at","created_at"],"type":"string","default":"display_name","title":"Sort By"}},{"name":"sort_order","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","default":"asc","title":"Sort Order"}},{"name":"demo_market","in":"query","required":false,"schema":{"anyOf":[{"enum":["au","us"],"type":"string"},{"type":"null"}],"title":"Demo Market"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"description":"Free-text search (case-insensitive) across display name, account number, email, external id and phone.","title":"Q"},"description":"Free-text search (case-insensitive) across display name, account number, email, external id and phone."},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"description":"Provider status values to include (case-insensitive, repeatable). Omit for every status.","title":"Status"},"description":"Provider status values to include (case-insensitive, repeatable). Omit for every status."},{"name":"campaign_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only accounts with a membership in this campaign.","title":"Campaign Id"},"description":"Only accounts with a membership in this campaign."},{"name":"campaign_assignment","in":"query","required":false,"schema":{"anyOf":[{"enum":["assigned","unassigned","multiple","review"],"type":"string"},{"type":"null"}],"description":"Filter by current campaign assignment count, or 'review' for accounts waiting on an operator decision.","title":"Campaign Assignment"},"description":"Filter by current campaign assignment count, or 'review' for accounts waiting on an operator decision."},{"name":"timezone_status","in":"query","required":false,"schema":{"anyOf":[{"enum":["unknown","manual"],"type":"string"},{"type":"null"}],"description":"'unknown': no timezone, so the gate will not call the account. 'manual': an operator set the timezone.","title":"Timezone Status"},"description":"'unknown': no timezone, so the gate will not call the account. 'manual': an operator set the timezone."},{"name":"called","in":"query","required":false,"schema":{"anyOf":[{"enum":["account","customer","never"],"type":"string"},{"type":"null"}],"description":"'account': a call is linked to this account. 'customer': a call is linked to this account or another account of the same customer. 'never': neither.","title":"Called"},"description":"'account': a call is linked to this account. 'customer': a call is linked to this account or another account of the same customer. 'never': neither."},{"name":"min_balance","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive lower bound on outstanding amount.","title":"Min Balance"},"description":"Inclusive lower bound on outstanding amount."},{"name":"max_balance","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive upper bound on outstanding amount.","title":"Max Balance"},"description":"Inclusive upper bound on outstanding amount."},{"name":"min_arrears","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive lower bound on arrears amount.","title":"Min Arrears"},"description":"Inclusive lower bound on arrears amount."},{"name":"max_arrears","in":"query","required":false,"schema":{"anyOf":[{"type":"number","minimum":0},{"type":"null"}],"description":"Inclusive upper bound on arrears amount.","title":"Max Arrears"},"description":"Inclusive upper bound on arrears amount."}],"responses":{"200":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/sync":{"post":{"tags":["accounts"],"summary":"Sync Accounts","description":"Pull provider accounts into the working set (admin only).\n\n``existing`` refreshes only the provider-owned accounts already visible in\nthe working set and runs in the background — poll\n``GET /accounts/sync/status``. ``ids`` imports explicit row ids / account\nnumbers (for example a CSV batch) inline and returns the final counts.","operationId":"accounts-sync_accounts","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountSyncRequest"}}},"required":true},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountSyncRunRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/accounts/sync/status":{"get":{"tags":["accounts"],"summary":"Sync Status","description":"The most recent sync run for the active provider, or null if none has\never run (admin only).","operationId":"accounts-sync_status","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/AccountSyncRunRead"},{"type":"null"}],"title":"Response Accounts-Sync Status"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/accounts/import/csv":{"post":{"tags":["accounts"],"summary":"Import Accounts Csv","description":"Import full account rows when provider-side sync is unavailable.\n\nCanonical identity/debt fields feed the normal Accounts and campaign\nsurfaces; every original column is retained on the account for audit and\ndisplay. The whole file is validated before the atomic upsert begins.","operationId":"accounts-import_accounts_csv","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_accounts-import_accounts_csv"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CsvAccountImportResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/accounts/bulk-remove":{"post":{"tags":["accounts"],"summary":"Remove Synced Accounts","description":"Remove the selected accounts from the local working set (admin only).\n\nThe upstream CRM records are untouched. Campaign membership and pending work\nare removed, while hidden tombstones preserve Whispa-only compliance and\ncall-history state. A later provider sync can re-add the accounts.\n\nRemoval is per-account and partial success is reported, not raised: any\naccount that is already dialling — or is no longer on this surface — comes\nback in ``skipped`` while the rest of the batch is removed. A 409 means an\naccount sync is running and nothing was touched.","operationId":"accounts-remove_synced_accounts","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveAccountsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveAccountsResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/accounts/timezone":{"post":{"tags":["accounts"],"summary":"Set Accounts Timezone","description":"Set or clear the operator-owned timezone on accounts (admin only).\n\nThe compliance gate will not call an account whose timezone is unknown;\nsetting one records who vouched for it and when, and returns campaign\nmemberships closed for that reason to their campaigns. Accounts not on the\nactive surface come back in ``not_found``.","operationId":"accounts-set_accounts_timezone","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountTimezoneUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountTimezoneUpdateResult"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/accounts/{account_id}/release-hold":{"post":{"tags":["accounts"],"summary":"Release Account Hold","description":"Clear the hold that stops every automatic call to an account (admin only).\n\nRecords who cleared it, when, and what the hold was. Campaign memberships\nthe hold closed stay as they are; resume them from the campaign or the\nreview queue. A creditor file feed's hold cannot be cleared here (409).","operationId":"accounts-release_account_hold","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CachedAccountRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/{account_id}":{"get":{"tags":["accounts"],"summary":"Get Account","description":"One working-set account by cache row id (admin only).","operationId":"accounts-get_account","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/CachedAccountRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/{account_id}/related":{"get":{"tags":["accounts"],"summary":"List Related Accounts","description":"The customer's other accounts, and accounts sharing one of this\naccount's numbers or its address that may be theirs (admin only).\n\nSame customer means the same provider customer id, or the same name and\ndate of birth. Removed accounts are included and carry ``removed_at``.\nFor a person to read before deciding; nothing here changes dialling.","operationId":"accounts-list_related_accounts","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"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/RelatedAccountsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/{account_id}/calls":{"get":{"tags":["accounts"],"summary":"List Account Calls","description":"This account's call activity across every campaign and manual dial,\nmost-recent-first (admin only).","operationId":"accounts-list_account_calls","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Max recent calls to return.","default":50,"title":"Limit"},"description":"Max recent calls to return."},{"name":"include_phone_matches","in":"query","required":false,"schema":{"type":"boolean","description":"Also return calls that carry no CRM link at all but whose canonical number is one of this account's, tagged match_source='phone'. Off by default: the campaign surface reads this endpoint as the dials behind an attempts counter, and an unlinked inbound call is not a dial attempt.","default":false,"title":"Include Phone Matches"},"description":"Also return calls that carry no CRM link at all but whose canonical number is one of this account's, tagged match_source='phone'. Off by default: the campaign surface reads this endpoint as the dials behind an attempts counter, and an unlinked inbound call is not a dial attempt."},{"name":"include_summaries","in":"query","required":false,"schema":{"type":"boolean","description":"Also return each call's written summary (the review screen).","default":false,"title":"Include Summaries"},"description":"Also return each call's written summary (the review screen)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AccountCallListItem"},"title":"Response Accounts-List Account Calls"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/accounts/{account_id}/notes":{"get":{"tags":["accounts"],"summary":"List Account Notes","description":"Existing provider notes for this account, fetched live and returned\nmost-recent-first (admin only). The envelope distinguishes an empty\nsupported history from a provider that cannot read note history, and says\nwhen older notes exist beyond the requested bound.","operationId":"accounts-list_account_notes","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"account_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Account Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"description":"Max recent notes to return.","default":100,"title":"Limit"},"description":"Max recent notes to return."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountNotesRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/user-settings":{"get":{"tags":["user-settings"],"summary":"Get User Settings","operationId":"user-settings-get_user_settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsRead"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"patch":{"tags":["user-settings"],"summary":"Update User Settings","operationId":"user-settings-update_user_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserSettingsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/admin/recording-retention":{"get":{"tags":["recording-retention"],"summary":"Get Retention Settings","operationId":"recording-retention-get_retention_settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionSettingsRead"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"patch":{"tags":["recording-retention"],"summary":"Update Retention Settings","operationId":"recording-retention-update_retention_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionSettingsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/admin/recording-retention/run-sweep":{"post":{"tags":["recording-retention"],"summary":"Run Retention Sweep","operationId":"recording-retention-run_retention_sweep","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PurgeResult"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/admin/calls/{call_id}":{"delete":{"tags":["recording-retention"],"summary":"Delete Call","operationId":"recording-retention-delete_call","security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}],"parameters":[{"name":"call_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Call Id"}},{"name":"force","in":"query","required":false,"schema":{"type":"boolean","description":"Override the live-call guard to delete an ongoing call the admin knows is stuck, without waiting for it to age past the staleness window. Recorded distinctly in the deletion audit log.","default":false,"title":"Force"},"description":"Override the live-call guard to delete an ongoing call the admin knows is stuck, without waiting for it to age past the staleness window. Recorded distinctly in the deletion audit log."}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/admin/organization-settings":{"get":{"tags":["organization-settings"],"summary":"Get Organization Settings","operationId":"organization-settings-get_organization_settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationSettingsRead"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]},"patch":{"tags":["organization-settings"],"summary":"Update Organization Settings","operationId":"organization-settings-update_organization_settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationSettingsUpdate"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationSettingsRead"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}},"security":[{"OAuth2PasswordBearer":[]},{"APIKeyCookie":[]}]}},"/auth/csrf-token":{"get":{"tags":["auth"],"summary":"Get Csrf Token","description":"Get a CSRF token for cookie-authenticated requests.\n\nThis endpoint sets a CSRF token in an HttpOnly cookie and returns the\nsame token in the JSON body. Clients store the body token (e.g., in\nmemory or localStorage) and send it via the X-CSRF-Token header on all\nstate-changing requests. The browser sends the cookie automatically;\nthe server validates header == cookie (double-submit pattern).\n\nDesktop apps using Bearer authentication do not need CSRF tokens.","operationId":"auth-get_csrf_token","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/integrations/telephony/awsconnect/call-started":{"post":{"tags":["awsconnect"],"summary":"Call Started","description":"Webhook called by Lambda when an AWS Connect call starts.\n\nThe Lambda function sends this when:\n- A call connects to an agent\n- KVS streaming is started for the contact\n\nThis endpoint:\n1. Creates a Whispa session for the call (if agent is mapped)\n2. Starts consuming the KVS stream\n3. Pipes audio to the transcription pipeline\n\nReturns:\n- CallStartedResponse with status=\"started\" and session_id if call is captured\n- CallStartedResponse with status=\"ignored\" and reason if agent is not mapped","operationId":"awsconnect-call_started","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallStartedRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallStartedResponse"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/integrations/telephony/awsconnect/call-ended":{"post":{"tags":["awsconnect"],"summary":"Call Ended","description":"Webhook called by Lambda when an AWS Connect call ends.\n\nOptional - the KVS stream ending also triggers call cleanup.\nThis provides an explicit signal if needed.","operationId":"awsconnect-call_ended","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CallEndedRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/integrations/telephony/awsconnect/health":{"get":{"tags":["awsconnect"],"summary":"Health","description":"Health check endpoint for AWS Connect integration.","operationId":"awsconnect-health","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/integrations/telephony/awsconnect/eventbridge":{"post":{"tags":["awsconnect"],"summary":"Eventbridge Event","description":"Receive raw AWS EventBridge events and project call/participant state.","operationId":"awsconnect-eventbridge_event","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}}},"components":{"schemas":{"AWSConnectAgent":{"properties":{"id":{"type":"string","title":"Id","description":"Agent ID in AWS Connect"},"username":{"type":"string","title":"Username","description":"Agent username"},"arn":{"type":"string","title":"Arn","description":"Agent ARN"},"first_name":{"type":"string","title":"First Name","description":"Agent first name","default":""},"last_name":{"type":"string","title":"Last Name","description":"Agent last name","default":""},"email":{"type":"string","title":"Email","description":"Agent email","default":""},"display_name":{"type":"string","title":"Display Name","description":"Display name for UI"}},"type":"object","required":["id","username","arn","display_name"],"title":"AWSConnectAgent","description":"An agent from AWS Connect instance (for agent discovery)."},"AWSConnectAgentListRequest":{"properties":{"aws_region":{"type":"string","title":"Aws Region","description":"AWS Region"},"instance_id":{"type":"string","title":"Instance Id","description":"AWS Connect Instance ID"},"aws_access_key_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Aws Access Key Id"},"aws_secret_access_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Aws Secret Access Key"}},"type":"object","required":["aws_region","instance_id"],"title":"AWSConnectAgentListRequest","description":"Request to list agents from AWS Connect instance."},"AWSConnectIntegrationConfig":{"properties":{"provider":{"type":"string","const":"awsconnect","title":"Provider","default":"awsconnect"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"$ref":"#/components/schemas/AWSConnectUIConfig"}},"type":"object","required":["config"],"title":"AWSConnectIntegrationConfig","description":"Request model for AWS Connect integration config."},"AWSConnectIntegrationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","const":"awsconnect","title":"Provider","default":"awsconnect"},"enabled":{"type":"boolean","title":"Enabled"},"config":{"$ref":"#/components/schemas/AWSConnectUIConfig"}},"type":"object","required":["id","enabled","config"],"title":"AWSConnectIntegrationResponse","description":"Response model for AWS Connect integration config."},"AWSConnectTestRequest":{"properties":{"provider":{"type":"string","const":"awsconnect","title":"Provider","default":"awsconnect"},"config":{"$ref":"#/components/schemas/AWSConnectUIConfig"}},"type":"object","required":["config"],"title":"AWSConnectTestRequest","description":"Request to test AWS Connect configuration."},"AWSConnectUIConfig":{"properties":{"aws_region":{"type":"string","title":"Aws Region","description":"AWS Region (e.g., ap-southeast-2)"},"instance_id":{"type":"string","title":"Instance Id","description":"AWS Connect Instance ID"},"instance_alias":{"anyOf":[{"type":"string","pattern":"^[a-z0-9][a-z0-9.-]*$"},{"type":"null"}],"title":"Instance Alias","description":"AWS Connect instance alias — the subdomain of the access URL https://<alias>.my.connect.aws. Used to deep-link call recordings."},"agent_user_map":{"additionalProperties":{"type":"string","format":"uuid"},"type":"object","title":"Agent User Map","description":"Maps AWS Connect agent usernames to Whispa user IDs"}},"type":"object","required":["aws_region","instance_id"],"title":"AWSConnectUIConfig","description":"Configuration for AWS Connect integration (UI-configurable).\n\nUnlike ThreeCXConfig, there is NO default_user_id - if an agent is not\nexplicitly mapped, their calls will NOT be captured."},"AccountCallListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"match_source":{"type":"string","enum":["linked","phone"],"title":"Match Source","description":"'linked' when someone explicitly attached this call to the account; 'phone' when it carries no CRM decision at all and was matched on customer_number_e164. A phone match is display-only evidence of contact with the number — never account attribution.","default":"linked"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"call_direction":{"anyOf":[{"$ref":"#/components/schemas/CallDirection"},{"type":"null"}]},"call_mode":{"anyOf":[{"$ref":"#/components/schemas/CallMode"},{"type":"null"}]},"summary_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary Text"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"qa_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Qa Score","description":"Overall QA scorecard score. Mirrors analyzer_artifacts['qa_scorecard']['overall_score']."},"status":{"$ref":"#/components/schemas/CallStatus","default":"completed"},"telephony_result":{"anyOf":[{"$ref":"#/components/schemas/TelephonyResult"},{"type":"null"}]},"answered_by":{"anyOf":[{"$ref":"#/components/schemas/AnsweredBy"},{"type":"null"}]},"conversation_outcome":{"anyOf":[{"$ref":"#/components/schemas/ConversationOutcome"},{"type":"null"}]},"workflow_disposition":{"anyOf":[{"$ref":"#/components/schemas/WorkflowDisposition"},{"type":"null"}]},"agent_end_reason":{"anyOf":[{"$ref":"#/components/schemas/AgentEndReason"},{"type":"null"}]},"commitment_shape":{"anyOf":[{"$ref":"#/components/schemas/CommitmentShape"},{"type":"null"}],"description":"The post-call commitment classification (call_outcomes), when one exists for the call."},"counted_as":{"anyOf":[{"$ref":"#/components/schemas/CallCountedAs"},{"type":"null"}],"description":"What the call counts as for the contact-frequency caps (contact, attempt, ...) and the stored fact behind it."}},"type":"object","required":["id","started_at"],"title":"AccountCallListItem","description":"Lightweight summary of a call session on a CRM account's activity list.\n\nBacks the account detail page's \"Call activity\" section. A thin subset of\n``src.calls.schemas.CallListItem`` — just the fields the table renders —\nproduced from ``crm_call_links`` and, when the caller opts in, from calls\nmatched on the canonical phone number (see ``CrmService.list_account_calls``)."},"AccountCampaignFacet":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"status":{"type":"string","title":"Status"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["id","name","status","count"],"title":"AccountCampaignFacet"},"AccountCampaignMembershipRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"campaign_name":{"type":"string","title":"Campaign Name"},"campaign_status":{"type":"string","title":"Campaign Status"},"account_status":{"type":"string","title":"Account Status"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"}},"type":"object","required":["id","campaign_id","campaign_name","campaign_status","account_status"],"title":"AccountCampaignMembershipRead","description":"One campaign an account is currently enrolled in.\n\nAccount detail needs the membership id to remove the account without first\nloading every campaign's full account table."},"AccountContextRead":{"properties":{"product_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Product Name"},"account_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Status"},"account_status_disposition":{"anyOf":[{"$ref":"#/components/schemas/AccountStatusDisposition"},{"type":"null"}]},"collection_stage":{"anyOf":[{"$ref":"#/components/schemas/CollectionStage"},{"type":"null"}]},"arrears_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrears Amount"},"arrears_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Arrears Days"},"outstanding_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Outstanding Amount"},"original_balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Original Balance"},"amount_paid":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount Paid"},"last_payment_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Last Payment Date"},"principal_outstanding":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Principal Outstanding"},"referred_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Referred Date"},"interest_overdue":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Interest Overdue"},"interest_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Interest Rate"},"late_fees":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Late Fees"},"dishonour_fees":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dishonour Fees"},"settled_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Settled Date"},"cycle_day":{"anyOf":[{"type":"integer","maximum":31.0,"minimum":1.0},{"type":"null"}],"title":"Cycle Day"},"repayment_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Repayment Amount"},"repayment_frequency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Repayment Frequency"},"next_installment_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Next Installment Amount"},"next_installment_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Next Installment Date"},"has_hardship":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Hardship"},"hardship_requested":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Hardship Requested"},"hardship_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hardship Status"},"hardship_notice_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Hardship Notice Date"},"active_arrangement_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Arrangement Summary"},"active_arrangement_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Active Arrangement Status"},"active_arrangement_next_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Active Arrangement Next Amount"},"active_arrangement_next_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Active Arrangement Next Date"},"collection_statuses":{"items":{"type":"string"},"type":"array","title":"Collection Statuses"},"risk_segmentation":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Risk Segmentation"},"num_active_loans":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Active Loans"},"num_broken_arrangements_last_6_months":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Broken Arrangements Last 6 Months"},"num_dishonours_last_6_months":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Dishonours Last 6 Months"},"num_contacts_last_30_days":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Num Contacts Last 30 Days"},"third_party_authority":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Third Party Authority"},"is_staff_account":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Staff Account"},"is_outsourced":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Outsourced"},"outsource_partner":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outsource Partner"},"is_written_off":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Written Off"},"joint_parties":{"items":{"$ref":"#/components/schemas/JointPartyRead"},"type":"array","title":"Joint Parties"},"recent_transactions":{"items":{"$ref":"#/components/schemas/LedgerEntryRead"},"type":"array","title":"Recent Transactions"},"recent_contacts":{"items":{"$ref":"#/components/schemas/ContactEventRead"},"type":"array","title":"Recent Contacts"},"recent_successful_contact_dates":{"items":{"type":"string","format":"date"},"type":"array","title":"Recent Successful Contact Dates","description":"Provider-classified successful contacts for outbound frequency caps; duplicate dates represent separate contacts."},"days_past_section_88":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days Past Section 88"},"days_past_information_request":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days Past Information Request"},"days_past_six_q":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Days Past Six Q"}},"type":"object","title":"AccountContextRead","description":"Wire shape for domain-shared account context (debt-collection state).\n\nMirrors `src.crm.base.AccountContext`. Every field is optional because\nproviders expose different subsets, and within a single provider some\nfields are only present when the underlying record has them set."},"AccountFacetsRead":{"properties":{"statuses":{"items":{"$ref":"#/components/schemas/AccountStatusFacet"},"type":"array","title":"Statuses"},"campaigns":{"items":{"$ref":"#/components/schemas/AccountCampaignFacet"},"type":"array","title":"Campaigns"},"balance_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance Min"},"balance_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance Max"},"arrears_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrears Min"},"arrears_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrears Max"},"total":{"type":"integer","title":"Total","default":0},"timezone_unknown":{"type":"integer","title":"Timezone Unknown","default":0},"timezone_manual":{"type":"integer","title":"Timezone Manual","default":0}},"type":"object","title":"AccountFacetsRead","description":"Filter vocabulary for the accounts table, computed over the working set.\n\n``status`` is a free-text provider snapshot, so the values on offer can\nonly come from the data — there is no enum to render from. Counts are\nunfiltered totals for the active provider, which is what makes them useful\nfor deciding what to filter to next."},"AccountFilter":{"properties":{"demo_market":{"anyOf":[{"type":"string","enum":["au","us"]},{"type":"null"}],"title":"Demo Market"},"q":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Q","description":"Free-text search (case-insensitive) across display name, account number, email, external id and phone."},"status":{"items":{"type":"string"},"type":"array","maxItems":50,"title":"Status","description":"Provider status snapshot values to include (case-insensitive). Empty = every status."},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id","description":"Only accounts with a non-removed membership in this campaign. Includes terminal membership history."},"campaign_assignment":{"anyOf":[{"type":"string","enum":["assigned","unassigned","multiple","review"]},{"type":"null"}],"title":"Campaign Assignment","description":"Filter by current non-terminal campaign assignments. 'multiple' means two or more overlapping assignments; 'review' means an assignment is waiting on an operator decision."},"timezone_status":{"anyOf":[{"type":"string","enum":["unknown","manual"]},{"type":"null"}],"title":"Timezone Status","description":"'unknown': no timezone could be established, so the compliance gate will not call the account. 'manual': an operator set the timezone by hand."},"called":{"anyOf":[{"type":"string","enum":["account","customer","never"]},{"type":"null"}],"title":"Called","description":"Filter by linked calls. 'account': a call is linked to this account. 'customer': a call is linked to this account or to another account of the same customer. 'never': neither."},"min_balance":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Min Balance","description":"Inclusive lower bound on outstanding amount."},"max_balance":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Max Balance","description":"Inclusive upper bound on outstanding amount."},"min_arrears":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Min Arrears","description":"Inclusive lower bound on arrears amount."},"max_arrears":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Max Arrears","description":"Inclusive upper bound on arrears amount."}},"type":"object","title":"AccountFilter","description":"The accounts working-set predicate, defined once.\n\nRead as query params by ``/accounts/search`` and ``/accounts/export``, and\nposted verbatim by the campaign add-by-filter variant. One model means the\nrows an operator sees, exports and adds can never be three different sets.\n\nAmount bounds are inclusive and match the columns the table renders:\n``balance`` is outstanding, ``arrears_amount`` is arrears. Accounts with a\nNULL amount are excluded by any bound on it — \"over $500\" cannot honestly\ninclude an account whose balance nobody knows."},"AccountNoteRead":{"properties":{"id":{"type":"string","title":"Id"},"text":{"type":"string","title":"Text"},"occurred_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Occurred At"},"author":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},"type":"object","required":["id","text"],"title":"AccountNoteRead","description":"A provider account note, returned most-recent-first."},"AccountNotesRead":{"properties":{"supported":{"type":"boolean","title":"Supported"},"items":{"items":{"$ref":"#/components/schemas/AccountNoteRead"},"type":"array","title":"Items"},"has_more":{"type":"boolean","title":"Has More","default":false},"limit":{"type":"integer","title":"Limit"}},"type":"object","required":["supported","limit"],"title":"AccountNotesRead","description":"Bounded live note history plus capability/truncation metadata."},"AccountSearchRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"external_id":{"type":"string","title":"External Id"},"display_name":{"type":"string","title":"Display Name"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"dob":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Dob"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"phones":{"items":{"type":"string"},"type":"array","title":"Phones"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"manual_timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manual Timezone"},"manual_timezone_set_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Manual Timezone Set By"},"manual_timezone_set_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manual Timezone Set By Email"},"manual_timezone_set_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Manual Timezone Set At"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance"},"arrears_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrears Amount"},"original_balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Original Balance"},"amount_paid":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount Paid"},"collection_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collection Stage"},"context":{"anyOf":[{"$ref":"#/components/schemas/AccountContextRead"},{"type":"null"}]},"data_source":{"type":"string","enum":["crm","csv"],"title":"Data Source","default":"crm"},"source_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Filename"},"source_data":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Source Data"},"suppression_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suppression Reason"},"suppressed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Suppressed At"},"suppression_released_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suppression Released Reason"},"suppression_released_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Suppression Released By"},"suppression_released_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suppression Released By Email"},"suppression_released_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Suppression Released At"},"synced_at":{"type":"string","format":"date-time","title":"Synced At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"last_activity_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Activity At"},"customer_last_activity_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Customer Last Activity At"},"can_call_now":{"type":"boolean","title":"Can Call Now"},"next_callable_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Callable At"},"callability_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callability Reason"},"callability_detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callability Detail"},"campaign_memberships":{"items":{"$ref":"#/components/schemas/AccountCampaignMembershipRead"},"type":"array","title":"Campaign Memberships"},"suppression_releasable":{"type":"boolean","title":"Suppression Releasable","description":"Whether an operator may clear the hold: a creditor file's is the\nfile's to lift.","readOnly":true}},"type":"object","required":["id","provider","external_id","display_name","synced_at","created_at","updated_at","can_call_now","suppression_releasable"],"title":"AccountSearchRead","description":"Accounts-table row with Whispa activity and callability state.\n\n``last_activity_at`` is the latest linked call (inbound or outbound).\nCallability is evaluated from the same compliance gate used immediately\nbefore an autonomous dial, against the account snapshot and actual recent\ncall history."},"AccountStatusDisposition":{"type":"string","enum":["workable","not_workable","resolved","unknown"],"title":"AccountStatusDisposition","description":"Provider-neutral meaning of a CRM's native account status.\n\nProviders keep their raw status in ``AccountContext.account_status`` for\ndisplay and audit, then map it onto this small contract for autonomous\noutbound policy. Adding another CRM means adding its native-code mapping\nin that provider; the compliance gate never needs vendor status strings."},"AccountStatusFacet":{"properties":{"value":{"type":"string","title":"Value"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["value","count"],"title":"AccountStatusFacet"},"AccountSyncRequest":{"properties":{"mode":{"type":"string","enum":["existing","ids"],"title":"Mode"},"external_ids":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":500},{"type":"null"}],"title":"External Ids","description":"Account refs for mode=ids — provider row ids or account numbers, both resolve."}},"type":"object","required":["mode"],"title":"AccountSyncRequest","description":"Refresh the existing working set or import an explicit ref list."},"AccountSyncRunRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"mode":{"type":"string","title":"Mode"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"status":{"type":"string","title":"Status"},"synced":{"type":"integer","title":"Synced"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total"},"processed":{"type":"integer","title":"Processed","default":0},"stalled":{"type":"boolean","title":"Stalled","default":false},"not_found":{"items":{"type":"string"},"type":"array","title":"Not Found"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"}},"type":"object","required":["id","provider","mode","status","synced","started_at"],"title":"AccountSyncRunRead"},"AccountTimezoneUpdate":{"properties":{"account_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"minItems":1,"title":"Account Ids"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone","description":"IANA timezone, e.g. 'Australia/Perth'. null clears the operator-set value so the account falls back to its CRM-derived timezone, if any."}},"type":"object","required":["account_ids","timezone"],"title":"AccountTimezoneUpdate","description":"Set (or clear) the operator-owned timezone on selected accounts."},"AccountTimezoneUpdateResult":{"properties":{"updated":{"type":"integer","title":"Updated"},"reopened_memberships":{"type":"integer","title":"Reopened Memberships"},"not_found":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Not Found"}},"type":"object","required":["updated","reopened_memberships"],"title":"AccountTimezoneUpdateResult","description":"How many accounts changed, and how many campaign memberships the gate\nhad closed for an unknown timezone went back into their campaigns."},"ActiveCallSummary":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"agent_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Email"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"transcript_count":{"type":"integer","title":"Transcript Count","default":0},"call_direction":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Call Direction"},"customer_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Number"},"customer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Name"}},"type":"object","required":["session_id","started_at"],"title":"ActiveCallSummary","description":"Summary of a single active call for the supervisor list view."},"ActiveCallsResponse":{"properties":{"calls":{"items":{"$ref":"#/components/schemas/ActiveCallSummary"},"type":"array","title":"Calls"},"total":{"type":"integer","title":"Total"}},"type":"object","required":["calls","total"],"title":"ActiveCallsResponse","description":"Response for the active calls list endpoint."},"AddCampaignAccountsRequest":{"properties":{"external_ids":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":500},{"type":"null"}],"title":"External Ids"},"filter":{"anyOf":[{"$ref":"#/components/schemas/AccountFilter"},{"type":"null"}]},"exclude_account_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"title":"Exclude Account Ids"},"skip_assigned_elsewhere":{"type":"boolean","title":"Skip Assigned Elsewhere","default":false}},"type":"object","title":"AddCampaignAccountsRequest","description":"Add accounts to a campaign by explicit ref list, or by filter.\n\nThe two variants are mutually exclusive. ``external_ids`` is the by-ref\npath: provider row ids or account numbers, resolved one at a time and\ncached on the way in, so a pasted batch list works even for accounts the\nworking set has never seen. ``filter`` is the \"add everything I'm looking\nat\" path: the operator's accounts-table filter is re-evaluated\nserver-side over the working set, which is the only way a selection of\nthousands can be added in one request (and the only way the set added\nmatches the set the operator was shown)."},"AddCampaignAccountsResponse":{"properties":{"added":{"type":"integer","title":"Added"},"already_present":{"type":"integer","title":"Already Present"},"assigned_elsewhere":{"type":"integer","title":"Assigned Elsewhere","default":0},"waiting":{"type":"integer","title":"Waiting","default":0},"not_found":{"items":{"type":"string"},"type":"array","title":"Not Found"}},"type":"object","required":["added","already_present"],"title":"AddCampaignAccountsResponse"},"AdminUserCreate":{"properties":{"email":{"type":"string","format":"email","title":"Email"},"role":{"$ref":"#/components/schemas/UserRole","default":"user"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"},"first_name":{"type":"string","title":"First Name"},"last_name":{"type":"string","title":"Last Name"},"default_scenario_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Default Scenario Id"},"copilot_enabled":{"type":"boolean","title":"Copilot Enabled","default":false}},"additionalProperties":false,"type":"object","required":["email","first_name","last_name"],"title":"AdminUserCreate"},"AdminUserEmailActionResponse":{"properties":{"user":{"$ref":"#/components/schemas/AdminUserResponse"},"email_sent":{"type":"boolean","title":"Email Sent"},"email_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email Error"}},"type":"object","required":["user","email_sent"],"title":"AdminUserEmailActionResponse"},"AdminUserResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","format":"email","title":"Email"},"role":{"$ref":"#/components/schemas/UserRole"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"},"team_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Name"},"is_active":{"type":"boolean","title":"Is Active"},"is_verified":{"type":"boolean","title":"Is Verified"},"last_login":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Login"},"first_name":{"type":"string","title":"First Name"},"last_name":{"type":"string","title":"Last Name"},"invited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Invited At"},"welcome_email_sent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Welcome Email Sent At"},"welcome_email_last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Welcome Email Last Error"},"invite_accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Invite Accepted At"},"default_scenario_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Default Scenario Id"},"default_scenario_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Scenario Display Name"},"copilot_enabled":{"type":"boolean","title":"Copilot Enabled","default":false}},"type":"object","required":["id","email","role","is_active","is_verified","last_login","first_name","last_name","invited_at","welcome_email_sent_at","welcome_email_last_error","invite_accepted_at"],"title":"AdminUserResponse"},"AdminUserUpdate":{"properties":{"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"role":{"anyOf":[{"$ref":"#/components/schemas/UserRole"},{"type":"null"}]},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"},"default_scenario_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Default Scenario Id"},"copilot_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Copilot Enabled"}},"additionalProperties":false,"type":"object","title":"AdminUserUpdate"},"AgentDetailResponse":{"properties":{"user_id":{"type":"string","title":"User Id"},"name":{"type":"string","title":"Name"},"period":{"$ref":"#/components/schemas/PeriodInfo"},"view":{"type":"string","enum":["daily","weekly"],"title":"View"},"engaged_calls":{"type":"integer","title":"Engaged Calls"},"total_calls":{"type":"integer","title":"Total Calls"},"sufficient":{"type":"boolean","title":"Sufficient"},"narrative":{"$ref":"#/components/schemas/NarrativeOut"},"tiles":{"items":{"$ref":"#/components/schemas/Tile"},"type":"array","title":"Tiles"},"scorecard_coverage":{"$ref":"#/components/schemas/ScorecardCoverage"},"scorecard_overall":{"anyOf":[{"$ref":"#/components/schemas/ScorecardSectionAgg"},{"type":"null"}]},"scorecard":{"items":{"$ref":"#/components/schemas/ScorecardSectionAgg"},"type":"array","title":"Scorecard"},"tag_strengths":{"items":{"$ref":"#/components/schemas/TagStrength"},"type":"array","title":"Tag Strengths"},"recent_calls":{"items":{"$ref":"#/components/schemas/RecentCall"},"type":"array","title":"Recent Calls"}},"type":"object","required":["user_id","name","period","view","engaged_calls","total_calls","sufficient","narrative","tiles","scorecard_coverage","scorecard","tag_strengths","recent_calls"],"title":"AgentDetailResponse"},"AgentEndReason":{"type":"string","enum":["conversation_complete","existing_arrangement_claimed","customer_requested_human","identity_verification_failed","customer_declined_to_engage","customer_unavailable","wrong_person","do_not_contact","hardship_detected","dispute_raised","escalation","voicemail","no_answer","caller_hung_up","caller_abandoned","answer_failed","answer_timeout","dial_failed","transfer_failed","screening_timeout","idle_timeout","max_duration","api_hangup","error","other"],"title":"AgentEndReason","description":"Normalized reason an autonomous call ended.\n\nThe raw runtime string remains in ``analyzer_artifacts`` for diagnostics.\nThis enum is the stable operational projection: semantic reasons exposed\nto the voice model plus bounded technical termination categories. Novel\nruntime endings degrade to ``OTHER`` instead of failing finalization."},"AgentPerformance":{"properties":{"agent":{"type":"string","title":"Agent"},"agent_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent User Id"},"call_count":{"type":"integer","title":"Call Count"},"qa_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qa Score"},"qa_score_trend":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qa Score Trend"},"alert":{"type":"boolean","title":"Alert","default":false},"total_call_seconds":{"type":"integer","title":"Total Call Seconds","default":0},"avg_call_duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Call Duration Seconds"},"avg_calls_per_day":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Calls Per Day"},"dashboard_open_percentage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dashboard Open Percentage","description":"This agent's dashboard-open rate (0-100), each call's percentage weighted by its duration. Calls with no subscriber count as 0%; denominator is every call with line-open time."},"idv_verified_count":{"type":"integer","title":"Idv Verified Count","description":"This agent's engaged IDV-required calls verified via IDV.","default":0},"idv_required_count":{"type":"integer","title":"Idv Required Count","description":"This agent's engaged IDV-required calls. Denominator for idv_verified_rate.","default":0},"idv_verified_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Idv Verified Rate","description":"Share of this agent's engaged IDV-required calls that were verified (0-100). None when the agent had no engaged IDV-required calls."},"engaged_call_count":{"type":"integer","title":"Engaged Call Count","description":"This agent's human-answered engaged calls. Denominator for commitment_rate.","default":0},"commitment_classified_count":{"type":"integer","title":"Commitment Classified Count","description":"Engaged calls for this agent that have a structured commitment outcome. Used to distinguish unavailable classification from zero commitments.","default":0},"commitment_count":{"type":"integer","title":"Commitment Count","description":"This agent's new-money commitments: new arrangements, immediate payments, and settlements.","default":0},"commitment_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Commitment Rate","description":"New-money commitments divided by all human-answered engaged calls for this agent (0-100). None when there are no engaged calls or no commitment classifications in the window."},"dollars_committed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dollars Committed","description":"Total recorded commitment amount for this agent's new-money commitments. This is promised money, not confirmed collections. None when commitment classification is unavailable."}},"type":"object","required":["agent","call_count"],"title":"AgentPerformance","description":"Leaderboard entry for an agent."},"AgentRow":{"properties":{"user_id":{"type":"string","title":"User Id"},"name":{"type":"string","title":"Name"},"engaged_calls":{"type":"integer","title":"Engaged Calls"},"avg_qa":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Qa"},"idv_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Idv Rate"},"empathy":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Empathy"},"empathy_status":{"type":"string","enum":["good","warn","crit","neutral"],"title":"Empathy Status","default":"neutral"},"commitment_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Commitment Rate"},"dollars_committed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dollars Committed"},"idv_status":{"type":"string","enum":["good","warn","crit","neutral"],"title":"Idv Status","default":"neutral"},"commitment_status":{"type":"string","enum":["good","warn","crit","neutral"],"title":"Commitment Status","default":"neutral"},"qa_status":{"type":"string","enum":["good","warn","crit","neutral"],"title":"Qa Status","default":"neutral"},"sufficient":{"type":"boolean","title":"Sufficient","default":true},"flags":{"items":{"type":"string"},"type":"array","title":"Flags","default":[]}},"type":"object","required":["user_id","name","engaged_calls"],"title":"AgentRow"},"AiCallDemoContext":{"properties":{"customer_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Customer Name"},"customer_dob":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Customer Dob"},"customer_address":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Customer Address"},"customer_email":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Customer Email"},"customer_ssn_last4":{"anyOf":[{"type":"string","maxLength":4},{"type":"null"}],"title":"Customer Ssn Last4"},"customer_postal_code":{"anyOf":[{"type":"string","maxLength":10},{"type":"null"}],"title":"Customer Postal Code"},"loan_id":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Loan Id"},"loan_product":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Loan Product"},"loan_balance":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Loan Balance"},"loan_interest_rate":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Loan Interest Rate"},"original_balance":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Original Balance"},"referred_date":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Referred Date"},"amount_overdue":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Amount Overdue"},"days_overdue":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Days Overdue"},"agent_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Agent Name"},"company_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Company Name"},"arrangement_amount":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Arrangement Amount"},"arrangement_frequency":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Arrangement Frequency"},"arrangement_remaining":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Arrangement Remaining"},"missed_amount":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Missed Amount"},"missed_date":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Missed Date"},"payment_method":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Payment Method"}},"type":"object","title":"AiCallDemoContext","description":"Per-call account context for the AI collector.\n\nEvery value is substituted into the scenario's ``voice_agent_config``\nsystem prompt / greeting (``$customer_name`` etc., see\n``service._apply_demo_context``) and the names are seeded as STT keyterms.\nAll fields are optional — anything omitted falls back to the built-in\nfictional demo account so a call works with no context at all.\n\nValues are spoken by the agent and matched against the customer's spoken\nanswers, so write them the way they should be said/heard (e.g. a date as\n\"12 March 1990\", an amount as \"$320\")."},"AnsweredBy":{"type":"string","enum":["human","voicemail","unclear"],"title":"AnsweredBy","description":"Who answered the call (AI-classified from transcript).\n\nThis is the first stage of call classification - determining\nwhether a human or voicemail answered the call."},"AutonomousVoiceCompletion":{"properties":{"total":{"type":"integer","title":"Total"},"complete":{"type":"integer","title":"Complete"},"incomplete":{"type":"integer","title":"Incomplete"},"completion_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Completion Rate","description":"Percentage of sampled turns whose status is complete"},"status_counts":{"additionalProperties":{"type":"integer"},"type":"object","title":"Status Counts","description":"Counts by persisted completion status, including unknown"}},"type":"object","required":["total","complete","incomplete","completion_rate","status_counts"],"title":"AutonomousVoiceCompletion","description":"How many transcribed caller turns were answered.\n\n``status_counts`` also lists the pauses that produced no transcript, which\nthe totals leave out."},"AutonomousVoiceLatencyAggregate":{"properties":{"calls_with_samples":{"type":"integer","title":"Calls With Samples"},"response_total":{"$ref":"#/components/schemas/LatencyPercentiles"},"by_kind":{"$ref":"#/components/schemas/src__performance__schemas__AutonomousVoiceLatencyByKind"},"target_ms":{"type":"integer","title":"Target Ms","description":"Response time a reply is expected to beat"},"over_target_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Over Target Rate","description":"Percentage of timed replies slower than target_ms"},"legs":{"$ref":"#/components/schemas/src__performance__schemas__AutonomousVoiceLatencyLegs"},"first_speech":{"$ref":"#/components/schemas/LatencyPercentiles","description":"Call connected to the agent's first audio, one per call"},"tool_handler":{"$ref":"#/components/schemas/LatencyPercentiles","description":"Tool handlers' own share of the tool stage"},"llm_thinking":{"$ref":"#/components/schemas/LatencyPercentiles","description":"Model output before its first answer token"},"llm_tokens_per_second":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Llm Tokens Per Second","description":"Completion tokens over the time spent writing them"},"unanswered_wait":{"$ref":"#/components/schemas/LatencyPercentiles","description":"Speech end to the caller speaking again, on turns with no reply"},"barge_in_stop":{"$ref":"#/components/schemas/LatencyPercentiles","description":"Caller speech onset to queued agent speech being discarded"},"turns":{"$ref":"#/components/schemas/AutonomousVoiceCompletion"},"trend":{"items":{"$ref":"#/components/schemas/AutonomousVoiceLatencyTrendPoint"},"type":"array","title":"Trend"}},"type":"object","required":["calls_with_samples","response_total","by_kind","target_ms","over_target_rate","legs","first_speech","tool_handler","llm_thinking","llm_tokens_per_second","unanswered_wait","barge_in_stop","turns","trend"],"title":"AutonomousVoiceLatencyAggregate","description":"Raw-sample aggregate for calls matching the Performance filters."},"AutonomousVoiceLatencySummary":{"properties":{"response_total":{"$ref":"#/components/schemas/LatencyLegSummary"},"legs":{"$ref":"#/components/schemas/src__calls__schemas__AutonomousVoiceLatencyLegs"},"turns":{"$ref":"#/components/schemas/AutonomousVoiceTurnCounts"},"by_kind":{"anyOf":[{"$ref":"#/components/schemas/src__calls__schemas__AutonomousVoiceLatencyByKind"},{"type":"null"}]},"over_target":{"anyOf":[{"$ref":"#/components/schemas/AutonomousVoiceOverTarget"},{"type":"null"}]},"first_speech_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"First Speech Ms"},"tool_handler":{"anyOf":[{"$ref":"#/components/schemas/LatencyLegSummary"},{"type":"null"}]},"llm_thinking":{"anyOf":[{"$ref":"#/components/schemas/LatencyLegSummary"},{"type":"null"}]},"llm_tokens_per_second":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Llm Tokens Per Second"},"unanswered_wait":{"anyOf":[{"$ref":"#/components/schemas/LatencyLegSummary"},{"type":"null"}]},"barge_in_stop":{"anyOf":[{"$ref":"#/components/schemas/LatencyLegSummary"},{"type":"null"}]}},"type":"object","required":["response_total","legs","turns"],"title":"AutonomousVoiceLatencySummary"},"AutonomousVoiceLatencyTrendPoint":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"p50_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"P50 Ms"},"p95_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"P95 Ms"},"worst_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Worst Ms"},"n":{"type":"integer","title":"N"},"completion_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Completion Rate"},"over_target_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Over Target Rate"}},"type":"object","required":["date","p50_ms","p95_ms","worst_ms","n","completion_rate","over_target_rate"],"title":"AutonomousVoiceLatencyTrendPoint","description":"Daily end-to-end autonomous response latency distribution."},"AutonomousVoiceOverTarget":{"properties":{"target_ms":{"type":"integer","title":"Target Ms"},"replies":{"type":"integer","title":"Replies"},"over":{"type":"integer","title":"Over"}},"type":"object","required":["target_ms","replies","over"],"title":"AutonomousVoiceOverTarget"},"AutonomousVoiceTurnCounts":{"properties":{"total":{"type":"integer","title":"Total"},"complete":{"type":"integer","title":"Complete"},"incomplete":{"type":"integer","title":"Incomplete"}},"type":"object","required":["total","complete","incomplete"],"title":"AutonomousVoiceTurnCounts"},"BearerLoginResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"},"refresh_token":{"type":"string","title":"Refresh Token"},"expires_in":{"type":"integer","title":"Expires In"}},"type":"object","required":["access_token","refresh_token","expires_in"],"title":"BearerLoginResponse","description":"Response for bearer login (desktop/API clients)."},"BearerLogoutRequest":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"BearerLogoutRequest","description":"Request body for desktop/API logout."},"BearerRefreshRequest":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"BearerRefreshRequest","description":"Request body for bearer token refresh."},"BearerRefreshResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type","default":"bearer"},"expires_in":{"type":"integer","title":"Expires In"}},"type":"object","required":["access_token","expires_in"],"title":"BearerRefreshResponse","description":"Response for bearer token refresh."},"BearerResponse":{"properties":{"access_token":{"type":"string","title":"Access Token"},"token_type":{"type":"string","title":"Token Type"}},"type":"object","required":["access_token","token_type"],"title":"BearerResponse"},"Body_accounts-import_accounts_csv":{"properties":{"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File","description":"UTF-8 CSV export, up to 10 MB."}},"type":"object","required":["file"],"title":"Body_accounts-import_accounts_csv"},"Body_auth-bearer_login":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"^password$"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","format":"password","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"format":"password","title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_auth-bearer_login"},"Body_auth-reset_forgot_password":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"Body_auth-reset:forgot_password"},"Body_auth-reset_reset_password":{"properties":{"token":{"type":"string","title":"Token"},"password":{"type":"string","title":"Password"}},"type":"object","required":["token","password"],"title":"Body_auth-reset:reset_password"},"Body_auth-verify_request-token":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"Body_auth-verify:request-token"},"Body_auth-verify_verify":{"properties":{"token":{"type":"string","title":"Token"}},"type":"object","required":["token"],"title":"Body_auth-verify:verify"},"Body_feedback-submit_feedback":{"properties":{"feedback_type":{"$ref":"#/components/schemas/FeedbackType","description":"Type of feedback"},"description":{"type":"string","minLength":10,"title":"Description","description":"Feedback description"},"screenshot":{"anyOf":[{"type":"string","contentMediaType":"application/octet-stream"},{"type":"null"}],"title":"Screenshot","description":"Optional screenshot"},"call_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Call Id","description":"Optional call ID to link feedback to"}},"type":"object","required":["feedback_type","description"],"title":"Body_feedback-submit_feedback"},"Body_sessions-post_session_audio_chunk":{"properties":{"audio_chunk":{"type":"string","contentMediaType":"application/octet-stream","title":"Audio Chunk"}},"type":"object","required":["audio_chunk"],"title":"Body_sessions-post_session_audio_chunk"},"Body_uploaded-calls-upload_call_recording":{"properties":{"audio_file":{"type":"string","contentMediaType":"application/octet-stream","title":"Audio File","description":"Audio file (MP3 or WAV)"},"assigned_user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Assigned User Id"},"scenario_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario Name"},"call_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Call Date"}},"type":"object","required":["audio_file"],"title":"Body_uploaded-calls-upload_call_recording"},"CachedAccountRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"external_id":{"type":"string","title":"External Id"},"display_name":{"type":"string","title":"Display Name"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"dob":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Dob"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"phones":{"items":{"type":"string"},"type":"array","title":"Phones"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"manual_timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manual Timezone"},"manual_timezone_set_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Manual Timezone Set By"},"manual_timezone_set_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Manual Timezone Set By Email"},"manual_timezone_set_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Manual Timezone Set At"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance"},"arrears_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrears Amount"},"original_balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Original Balance"},"amount_paid":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount Paid"},"collection_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collection Stage"},"context":{"anyOf":[{"$ref":"#/components/schemas/AccountContextRead"},{"type":"null"}]},"data_source":{"type":"string","enum":["crm","csv"],"title":"Data Source","default":"crm"},"source_filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Filename"},"source_data":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Source Data"},"suppression_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suppression Reason"},"suppressed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Suppressed At"},"suppression_released_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suppression Released Reason"},"suppression_released_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Suppression Released By"},"suppression_released_by_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suppression Released By Email"},"suppression_released_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Suppression Released At"},"synced_at":{"type":"string","format":"date-time","title":"Synced At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"suppression_releasable":{"type":"boolean","title":"Suppression Releasable","description":"Whether an operator may clear the hold: a creditor file's is the\nfile's to lift.","readOnly":true}},"type":"object","required":["id","provider","external_id","display_name","synced_at","created_at","updated_at","suppression_releasable"],"title":"CachedAccountRead","description":"One working-set row (``crm_accounts``): the accounts surface's unit.\n\nA snapshot of the provider's account as of ``synced_at`` plus the\nwhispa-only suppression state — the provider's CRM stays the system of\nrecord for every debt fact."},"CallCountedAs":{"properties":{"classification":{"$ref":"#/components/schemas/ContactClassification"},"basis":{"type":"string","title":"Basis","description":"The stored fact behind the classification, in a few words."}},"type":"object","required":["classification","basis"],"title":"CallCountedAs","description":"A call's classification and the stored fact it rests on."},"CallDateTimeUpdate":{"properties":{"started_at":{"type":"string","format":"date-time","title":"Started At","description":"New start date/time for the call"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At","description":"New end date/time for the call (optional)"}},"type":"object","required":["started_at"],"title":"CallDateTimeUpdate","description":"Request to update call start and end date/time."},"CallDetailResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id","description":"Team snapshot for this call"},"user_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Email","description":"Email of the agent who took the call"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name","description":"Display name of the agent who took the call"},"call_mode":{"anyOf":[{"$ref":"#/components/schemas/CallMode"},{"type":"null"}],"description":"Call mode: training or production"},"call_source":{"$ref":"#/components/schemas/CallSource","description":"Call source: live or uploaded","default":"live"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Id"},"extension":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Extension","description":"Phone extension that handled the call"},"called_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Called Number","description":"Inbound destination number reported by the provider, when available"},"telephony_call_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Telephony Call Id","description":"External telephony system call ID"},"provider_call_ref":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Provider Call Ref","description":"Provider-native call reference (e.g. TCN call_sid/call_type, AWS Connect contact_id) when the provider hosts the call recording. Only some providers support minting a link via /calls/{call_id}/provider-recording-url (TCN today; the endpoint returns 404 for others). For awsconnect this is the stored reference plus instance_alias resolved from the current Connect integration config, which together address the Connect console's contact page — so the alias is whatever is configured now, not whatever was configured when the call happened"},"suspensions":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Suspensions","description":"Park windows during the call (TCN payment-line transfers): [{suspended_at, resumed_at}] ISO timestamps; resumed_at is null when the call never resumed (grace expired)"},"timeline":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Timeline","description":"Typed call lifecycle events in order: {type, at, detail?, source}. Types: ringing, connected, hold_start, hold_end, consult_start, consult_end, call_suspended, call_resumed, call_ended. Rendered as transcript markers and fed to the summary/coaching/QA prompts"},"customer_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Number","description":"Phone number of the caller/customer"},"customer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Name","description":"Name of the caller/customer if available"},"ring_duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Ring Duration Seconds","description":"Time spent ringing before call was answered (seconds)"},"call_direction":{"anyOf":[{"$ref":"#/components/schemas/CallDirection"},{"type":"null"}],"description":"Direction of the call (incoming, outgoing, internal)"},"audio_chunks_received":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Audio Chunks Received","description":"Number of audio chunks received (0 = no audio captured)"},"audio_file_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audio File Path","description":"S3 path to the call recording, when one is archived"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"is_starred":{"type":"boolean","title":"Is Starred","description":"Whether this call has been saved for later review","default":false},"transcript":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Transcript","description":"Transcript entries (populated from call_transcript_chunks table)"},"tool_events":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Tool Events","description":"Terminal tool-call events from the autonomous voice agent (persisted tool_call session events), in call order. Payload shape matches the SSE tool_call channel; interleaved into the transcript view behind a toggle."},"summary_markdown":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary Markdown"},"summary":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Summary","description":"Structured call summary (new format)"},"coaching":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Coaching"},"qa_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Qa Score","description":"Overall QA scorecard score (mirror of analyzer_artifacts['qa_scorecard']['overall_score'])."},"tags":{"anyOf":[{"$ref":"#/components/schemas/CallTagsPayload"},{"type":"null"}],"description":"Detected call tags with supporting evidence"},"call_outcome":{"anyOf":[{"$ref":"#/components/schemas/CallOutcome"},{"type":"null"}],"description":"Extracted payment-commitment outcome (collections scenarios)"},"client":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client","description":"End-client the call collected for, classified against the scenario's configured client list ('Other' for an explicitly named unconfigured creditor; 'Unclear' for insufficient or ambiguous context; null when no classification result was produced). Full result with disposition, confidence, and evidence in analyzer_artifacts['client_classification']."},"client_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Client Id","description":"Stable client identity for the display-name snapshot"},"client_summary":{"anyOf":[{"$ref":"#/components/schemas/ClientSummary"},{"type":"null"}],"description":"Current read-safe metadata for the stable client identity. The call's client string remains its historical display-name snapshot."},"crm_link":{"anyOf":[{"$ref":"#/components/schemas/CrmCallLinkRead"},{"type":"null"}],"description":"Persisted CRM account decision and account metadata for this call."},"tts_voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tts Voice Id","description":"Provider-qualified voice the autonomous agent spoke with, stamped at dispatch from the resolved fallback chain — not re-derived from the scenario, which may have been re-voiced since. Null on human calls. Resolve the display name against the voice catalog (GET /ai-calls/voices)."},"tts_model_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tts Model Id","description":"Provider-qualified TTS model the autonomous agent used, stamped at dispatch rather than re-derived from mutable scenario config."},"analyzer_artifacts":{"additionalProperties":true,"type":"object","title":"Analyzer Artifacts"},"post_call_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Post Call Notes"},"status":{"$ref":"#/components/schemas/CallStatus","description":"Call lifecycle status (ongoing/completed/failed)","default":"completed"},"telephony_result":{"anyOf":[{"$ref":"#/components/schemas/TelephonyResult"},{"type":"null"}],"description":"Telephony-level result (connected, busy, no_answer, rejected, failed)"},"answered_by":{"anyOf":[{"$ref":"#/components/schemas/AnsweredBy"},{"type":"null"}],"description":"AI-classified: who answered the call (human, voicemail, unclear)"},"conversation_outcome":{"anyOf":[{"$ref":"#/components/schemas/ConversationOutcome"},{"type":"null"}],"description":"AI-classified: conversation outcome (engaged, refused, wrong_person, other)"},"workflow_disposition":{"anyOf":[{"$ref":"#/components/schemas/WorkflowDisposition"},{"type":"null"}],"description":"Deterministic autonomous workflow action; explicit none for finalized AI calls and null when not applicable"},"agent_end_reason":{"anyOf":[{"$ref":"#/components/schemas/AgentEndReason"},{"type":"null"}],"description":"Normalized reason the autonomous call ended"},"classification_final":{"type":"boolean","title":"Classification Final","description":"Whether the call's terminal classification has been published (outcome_ready_at is set). The exact precondition for correcting answered_by / conversation_outcome — a call can be 'completed' while post-call facts are still finalizing, so clients must gate the correction UI on this rather than on status.","default":false},"counted_as":{"anyOf":[{"$ref":"#/components/schemas/CallCountedAs"},{"type":"null"}],"description":"What the call counts as for the contact-frequency caps (contact, attempt, ...) and the stored fact behind it. The same reading the pre-dial gate and the retry ladder use."},"detected_scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Scenario","description":"AI-detected scenario from transcript content"},"idv_outcome":{"anyOf":[{"$ref":"#/components/schemas/IdvOutcome"},{"type":"null"}],"description":"Tracked identity-verification outcome (verified/partial/incomplete). NULL means no persisted verdict; consult idv_required and call status. This is analyzer tracking state, NOT the adherence grade."},"idv_source":{"anyOf":[{"$ref":"#/components/schemas/IdvSource"},{"type":"null"}],"description":"Whether idv_outcome came from the live analyzer or the post-call judge"},"idv_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Idv Required","description":"Whether the call's resolved scenario requires identity verification. NULL when the scenario record is unavailable."},"recording_disclosed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Recording Disclosed","description":"True when the IDV tracker positively captured the recording disclosure; otherwise NULL."},"scenario_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scenario Id","description":"FK to configured scenario"},"was_transferred":{"type":"boolean","title":"Was Transferred","description":"Whether this call was transferred to/from another call","default":false},"transferred_from_call_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Transferred From Call Id","description":"If transferred, the call session this was transferred FROM"},"transferred_to_call_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Transferred To Call Id","description":"If transferred, the call session this was transferred TO"},"dashboard_open_percentage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dashboard Open Percentage","description":"Percentage of call duration with dashboard open (0-100)"},"latency_summary_json":{"anyOf":[{"$ref":"#/components/schemas/CallLatencySummary"},{"type":"null"}],"description":"Admin-only per-call latency rollups computed at finalize. The top-level vaqi_l/legs describe suggested responses; autonomous_voice contains the spoken response waterfall."},"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","scenario","agent_id","started_at","ended_at","duration_seconds","summary_markdown","coaching","analyzer_artifacts","post_call_notes","created_at","updated_at"],"title":"CallDetailResponse","description":"Full call details including transcript and analyses."},"CallDirection":{"type":"string","enum":["incoming","outgoing","internal"],"title":"CallDirection","description":"Direction of the call.\n\n- INCOMING: Customer called agent\n- OUTGOING: Agent called customer\n- INTERNAL: Extension-to-extension call"},"CallEndedRequest":{"properties":{"contact_id":{"type":"string","title":"Contact Id","description":"AWS Connect Contact ID"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Reason for call end"}},"type":"object","required":["contact_id"],"title":"CallEndedRequest","description":"Webhook payload from Lambda when a call ends.\n\nOptional - the KVS stream ending can also signal call end."},"CallFilterOptionsResponse":{"properties":{"scenarios":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Scenarios","description":"Available scenario options"},"agents":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Agents","description":"Available agent options (user emails)"},"statuses":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Statuses","description":"Available status options"},"modes":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Modes","description":"Available call mode options"},"sources":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Sources","description":"Available call source options"},"directions":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Directions","description":"Available call direction options"},"feedback_ratings":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Feedback Ratings","description":"Available coaching feedback rating options (positive, negative)"},"telephony_results":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Telephony Results","description":"Available telephony result options (connected, busy, no_answer, rejected, failed)"},"answered_by_options":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Answered By Options","description":"Available answered_by options (human, voicemail, unclear)"},"conversation_outcomes":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Conversation Outcomes","description":"Available conversation outcome options (engaged, refused, wrong_person, other)"},"idv_statuses":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Idv Statuses","description":"Available IDV status options (verified, partial, incomplete, not_required)"},"workflow_dispositions":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Workflow Dispositions","description":"Available autonomous workflow disposition options"},"agent_end_reasons":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Agent End Reasons","description":"Available normalized autonomous call-ending reasons"},"transfer_options":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Transfer Options","description":"Available transfer filter options (transfer_in, transfer_out)"},"dashboard_options":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Dashboard Options","description":"Available dashboard presence filter options (dashboard_open)"},"crm_link_options":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Crm Link Options","description":"Available CRM account-link filter options"},"client_options":{"items":{"$ref":"#/components/schemas/FilterOption"},"type":"array","title":"Client Options","description":"Available classified client options"},"client_classification_enabled":{"type":"boolean","title":"Client Classification Enabled","description":"Whether any active scenario supports client classification","default":false}},"type":"object","title":"CallFilterOptionsResponse","description":"Available filter options for call history."},"CallLatencySummary":{"properties":{"vaqi_l":{"$ref":"#/components/schemas/LatencyLegSummary"},"legs":{"$ref":"#/components/schemas/SuggestedResponseLatencyLegs"},"autonomous_voice":{"anyOf":[{"$ref":"#/components/schemas/AutonomousVoiceLatencySummary"},{"type":"null"}]}},"type":"object","required":["vaqi_l","legs"],"title":"CallLatencySummary","description":"Typed admin-only latency payload stored on a completed call."},"CallListItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id","description":"Team snapshot for this call"},"user_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Email","description":"Email of the agent who took the call"},"user_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Display Name","description":"Display name of the agent who took the call"},"call_mode":{"anyOf":[{"$ref":"#/components/schemas/CallMode"},{"type":"null"}],"description":"Call mode: training or production"},"call_source":{"$ref":"#/components/schemas/CallSource","description":"Call source: live or uploaded","default":"live"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"qa_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Qa Score","description":"Overall QA scorecard score. Mirrors analyzer_artifacts['qa_scorecard']['overall_score']."},"status":{"$ref":"#/components/schemas/CallStatus","description":"Call lifecycle status (ongoing/completed/failed)","default":"completed"},"is_starred":{"type":"boolean","title":"Is Starred","description":"Whether this call has been saved for later review","default":false},"call_direction":{"anyOf":[{"$ref":"#/components/schemas/CallDirection"},{"type":"null"}],"description":"Direction of the call (incoming, outgoing, internal)"},"telephony_result":{"anyOf":[{"$ref":"#/components/schemas/TelephonyResult"},{"type":"null"}],"description":"Telephony-level result (connected, busy, no_answer, rejected, failed)"},"answered_by":{"anyOf":[{"$ref":"#/components/schemas/AnsweredBy"},{"type":"null"}],"description":"AI-classified: who answered the call (human, voicemail, unclear)"},"conversation_outcome":{"anyOf":[{"$ref":"#/components/schemas/ConversationOutcome"},{"type":"null"}],"description":"AI-classified: conversation outcome (engaged, refused, wrong_person, other)"},"workflow_disposition":{"anyOf":[{"$ref":"#/components/schemas/WorkflowDisposition"},{"type":"null"}],"description":"Deterministic autonomous workflow action; explicit none for finalized AI calls and null when not applicable"},"agent_end_reason":{"anyOf":[{"$ref":"#/components/schemas/AgentEndReason"},{"type":"null"}],"description":"Normalized reason the autonomous call ended"},"detected_scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Scenario","description":"AI-detected scenario from transcript content"},"idv_outcome":{"anyOf":[{"$ref":"#/components/schemas/IdvOutcome"},{"type":"null"}],"description":"Tracked identity-verification outcome (verified/partial/incomplete). NULL means no persisted verdict; consult idv_required and call status to distinguish not-applicable, pending, and unavailable states. This is analyzer tracking state, NOT the adherence grade — the leadership IDV rate reads the reviewed QA scorecard instead."},"idv_source":{"anyOf":[{"$ref":"#/components/schemas/IdvSource"},{"type":"null"}],"description":"Whether idv_outcome came from the live analyzer or the post-call judge"},"idv_required":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Idv Required","description":"Whether the call's resolved scenario requires identity verification. NULL when the scenario record is unavailable, so clients must not guess that a missing outcome means IDV was not required."},"recording_disclosed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Recording Disclosed","description":"True when the IDV tracker positively captured the recording disclosure. Never False — an absent disclosure may simply have been missed, so the negative is not asserted."},"scenario_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scenario Id","description":"FK to configured scenario"},"was_transferred":{"type":"boolean","title":"Was Transferred","description":"Whether this call was transferred to/from another call","default":false},"transferred_from_call_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Transferred From Call Id","description":"If transferred, the call session this was transferred FROM"},"transferred_to_call_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Transferred To Call Id","description":"If transferred, the call session this was transferred TO"},"customer_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Number","description":"Phone number of the caller/customer"},"coaching_feedback_rating":{"anyOf":[{"$ref":"#/components/schemas/CoachingFeedbackRating"},{"type":"null"}],"description":"User feedback rating on coaching (positive or negative)"},"coaching_feedback_comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Coaching Feedback Comment","description":"Optional user comment attached to coaching feedback"},"tags":{"anyOf":[{"$ref":"#/components/schemas/CallTagsListPayload"},{"type":"null"}],"description":"Detected call tag keys"},"call_outcome":{"anyOf":[{"$ref":"#/components/schemas/CallOutcome"},{"type":"null"}],"description":"Extracted payment-commitment outcome (collections scenarios)"},"client":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client","description":"End-client the call collected for, classified against the scenario's configured client list ('Other' for an explicitly named unconfigured creditor; 'Unclear' for insufficient or ambiguous context; null when no classification result was produced)"},"client_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Client Id","description":"Stable client identity for the display-name snapshot"},"crm_link":{"anyOf":[{"$ref":"#/components/schemas/CrmCallLinkRead"},{"type":"null"}],"description":"Persisted CRM account decision for this call. A decision of 'linked' is an actual account link; 'none_of_these' records that the user completed the lookup without selecting an account."},"tts_voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tts Voice Id","description":"Provider-qualified voice the autonomous agent spoke with, stamped at dispatch. Null on human calls. Resolve the display name against the voice catalog (GET /ai-calls/voices)."},"tts_model_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tts Model Id","description":"Provider-qualified TTS model the autonomous agent used, stamped at dispatch. Null on human calls and older autonomous calls."}},"type":"object","required":["id","user_id","scenario","agent_id","started_at","ended_at","duration_seconds"],"title":"CallListItem","description":"Lightweight call information for list views."},"CallMode":{"type":"string","enum":["training","production","ai_agent"],"title":"CallMode","description":"Call mode enumeration."},"CallOutcome":{"properties":{"commitment_shape":{"$ref":"#/components/schemas/CommitmentShape","description":"Which commitment outcome occurred on this call"},"commitment_horizon":{"anyOf":[{"$ref":"#/components/schemas/CommitmentHorizon"},{"type":"null"}],"description":"When the money is expected; null for non-monetary shapes"},"is_new_commitment":{"type":"boolean","title":"Is New Commitment","description":"True when this call produced new money intent. False for arrangement_repair and all non-monetary shapes."},"installment_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Installment Amount","description":"Per-payment amount in major currency units (e.g. 40.00 for $40). For one-off commitments, equals the one-off amount. Null when no amount is stated."},"first_payment_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"First Payment Amount","description":"Down payment / first payment amount taken on the call, SEPARATE from the rest of the money agreed on the same call. Example: '$1000 today, then $100 every fortnight' → first_payment_amount=1000, installment_amount=100. Also covers a split lump sum ('half now, half next week' → first_payment = today's half, installment = the remaining one_off payment). Null when the call has no immediate payment component. For a standalone immediate payment (with nothing to follow), use shape=immediate_payment and installment_amount — do NOT use this field."},"payment_frequency":{"anyOf":[{"$ref":"#/components/schemas/PaymentFrequency"},{"type":"null"}],"description":"Cadence of payments. Always `one_off` for immediate_payment. For settlement, `one_off` unless the settled amount is paid over a stated schedule. Null when no schedule is stated or not applicable."},"installment_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Installment Count","description":"Exact number of installment_amount payments (NOT counting any first_payment_amount), ONLY when explicitly stated in the transcript. Null for vague durations ('a few months', 'ongoing')."},"explicit_total_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Explicit Total Amount","description":"Total commitment value in major currency units, ONLY when the transcript states the total directly. DO NOT compute totals from installment × count — the backend handles that derivation."},"confidence":{"type":"number","title":"Confidence","description":"Classifier's self-reported confidence in this extraction"},"evidence_quote":{"type":"string","minLength":1,"title":"Evidence Quote","description":"Short transcript excerpt that supports the classification"},"total_commitment_amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Total Commitment Amount","description":"Total commitment in major currency units. Either copied from `explicit_total_amount` when present, or derived as `installment_amount × installment_count` when both are known. Null when neither is available (open-ended plan, truncated transcript, or non-monetary shape)."},"total_commitment_source":{"$ref":"#/components/schemas/TotalCommitmentSource","default":"not_available"}},"type":"object","required":["commitment_shape","is_new_commitment","confidence","evidence_quote"],"title":"CallOutcome","description":"Canonical call-outcome record, adding service-derived total fields."},"CallReplayResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"has_audio":{"type":"boolean","title":"Has Audio","description":"Whether audio is available for playback"},"has_provider_recording":{"type":"boolean","title":"Has Provider Recording","description":"Whether the telephony provider hosts a recording playable through /calls/{call_id}/provider-recording-url (TCN). Replay falls back to it when has_audio is false; it is on the provider's timeline.","default":false},"audio_file_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audio File Path","description":"S3 path to audio file if available"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"crm_link":{"anyOf":[{"$ref":"#/components/schemas/CrmCallLinkRead"},{"type":"null"}],"description":"Authorized linked-account identity used to render replayed IDV cards"},"is_transcript_fallback":{"type":"boolean","title":"Is Transcript Fallback","description":"True when replay only includes transcript events (no persisted analysis)","default":false},"events":{"items":{"$ref":"#/components/schemas/ReplayEvent"},"type":"array","title":"Events","description":"Session events with timing for replay"}},"type":"object","required":["id","started_at","duration_seconds","has_audio","scenario","events"],"title":"CallReplayResponse","description":"Complete replay data for a call session."},"CallSource":{"type":"string","enum":["live","uploaded"],"title":"CallSource","description":"Call source enumeration."},"CallStarResponse":{"properties":{"is_starred":{"type":"boolean","title":"Is Starred"}},"type":"object","required":["is_starred"],"title":"CallStarResponse","description":"The updated review state for a call."},"CallStarUpdate":{"properties":{"is_starred":{"type":"boolean","title":"Is Starred"}},"type":"object","required":["is_starred"],"title":"CallStarUpdate","description":"Set whether a call is saved for later review."},"CallStartedRequest":{"properties":{"contact_id":{"type":"string","title":"Contact Id","description":"AWS Connect Contact ID"},"stream_arn":{"type":"string","title":"Stream Arn","description":"KVS Stream ARN for this call"},"agent_arn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Arn","description":"Agent ARN (for user mapping)"},"customer_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Number","description":"Customer's phone number"},"instance_arn":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instance Arn","description":"AWS Connect Instance ARN"},"queue_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Queue Name","description":"Queue name the call came through"},"agent_username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Username","description":"Agent username in AWS Connect"},"initiation_method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Initiation Method","description":"Call initiation method: INBOUND, OUTBOUND, TRANSFER, CALLBACK, API, etc."}},"type":"object","required":["contact_id","stream_arn"],"title":"CallStartedRequest","description":"Webhook payload from Lambda when a call starts.\n\nThe Lambda function in the customer's AWS account sends this payload\nwhen a call connects and KVS streaming begins."},"CallStartedResponse":{"properties":{"session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Session Id","description":"Session ID (None if call was ignored)"},"status":{"type":"string","title":"Status","description":"started, ignored, or error","default":"started"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Reason if status is ignored"}},"type":"object","title":"CallStartedResponse","description":"Response to call-started webhook."},"CallStatistics":{"properties":{"total_calls":{"type":"integer","title":"Total Calls"},"calls_connected":{"type":"integer","title":"Calls Connected"},"calls_busy":{"type":"integer","title":"Calls Busy"},"calls_no_answer":{"type":"integer","title":"Calls No Answer"},"calls_rejected":{"type":"integer","title":"Calls Rejected"},"calls_failed":{"type":"integer","title":"Calls Failed"},"calls_answered_human":{"type":"integer","title":"Calls Answered Human"},"calls_answered_voicemail":{"type":"integer","title":"Calls Answered Voicemail"},"calls_answered_unclear":{"type":"integer","title":"Calls Answered Unclear"},"outcome_engaged":{"type":"integer","title":"Outcome Engaged"},"outcome_refused":{"type":"integer","title":"Outcome Refused"},"outcome_wrong_person":{"type":"integer","title":"Outcome Wrong Person"},"outcome_other":{"type":"integer","title":"Outcome Other"},"summaries_copied":{"type":"integer","title":"Summaries Copied","description":"Number of human-answered calls whose summary was copied to the clipboard at least once (counted once per call). Restricted to human-answered calls so it divides cleanly by calls_answered_human for the dashboard 'Summary Copied' rate.","default":0},"crm_linked_calls":{"type":"integer","title":"Crm Linked Calls","description":"Number of calls with an actual CRM account link (crm_call_links.decision='linked'). None-of-these decisions are excluded.","default":0},"total_call_seconds":{"type":"integer","title":"Total Call Seconds","default":0},"avg_call_duration_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Call Duration Seconds"},"avg_calls_per_day":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Calls Per Day"},"avg_dashboard_open_percentage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Dashboard Open Percentage","description":"Team-wide dashboard-open rate (0-100), each call's percentage weighted by its duration. Calls with no subscriber count as 0%; denominator is every call with line-open time."},"idv_verified_count":{"type":"integer","title":"Idv Verified Count","description":"Engaged IDV-required calls where the live tracker recorded verification completed (idv_outcome=verified).","default":0},"idv_required_count":{"type":"integer","title":"Idv Required Count","description":"Engaged calls with a RECORDED idv_outcome (verified, skipped or incomplete). Non-engaged calls (wrong-person, refused, voicemail) are excluded, as are calls with a NULL outcome — usually no IDV step in the scenario, but also calls the tracker never judged. Denominator for idv_verified_rate.","default":0},"idv_verified_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Idv Verified Rate","description":"Share of engaged IDV-required calls that were verified (0-100). None when no engaged IDV-required calls fall in the window."},"inbound_callback_calls":{"type":"integer","title":"Inbound Callback Calls","description":"Inbound calls in the window attributed to a campaign dial (campaign_callback_links, last-touch by phone number; see outbound.inbound_callbacks). Scoped by the campaign filter when one is active; independent of the per-user call scoping above.","default":0},"inbound_callback_numbers":{"type":"integer","title":"Inbound Callback Numbers","description":"Unique caller numbers among inbound_callback_calls — the numerator for a future callback rate (per unique number attempted, not per dial, so retries don't distort it).","default":0}},"type":"object","required":["total_calls","calls_connected","calls_busy","calls_no_answer","calls_rejected","calls_failed","calls_answered_human","calls_answered_voicemail","calls_answered_unclear","outcome_engaged","outcome_refused","outcome_wrong_person","outcome_other"],"title":"CallStatistics","description":"Scenario-agnostic call statistics for the overview cards."},"CallStatus":{"type":"string","enum":["ongoing","completed","unanswered","error"],"title":"CallStatus","description":"Call lifecycle state.\n\n- ONGOING: Call is currently in progress\n- COMPLETED: Call finished (regardless of whether it was answered)\n- ERROR: Technical error/exception during call processing\n- UNANSWERED: DEPRECATED - Use status=COMPLETED + telephony_result=NO_ANSWER instead.\n              Kept for backwards compatibility with existing database records."},"CallTagItem":{"properties":{"key":{"type":"string","title":"Key","description":"Machine-safe tag identifier"},"evidence":{"items":{"type":"string"},"type":"array","title":"Evidence","description":"Short transcript snippets supporting the detected tag"}},"type":"object","required":["key"],"title":"CallTagItem","description":"A single detected call tag with supporting transcript evidence."},"CallTagListItem":{"properties":{"key":{"type":"string","title":"Key","description":"Machine-safe tag identifier"}},"type":"object","required":["key"],"title":"CallTagListItem","description":"A lightweight detected call tag for list views."},"CallTagsListPayload":{"properties":{"tags":{"items":{"$ref":"#/components/schemas/CallTagListItem"},"type":"array","title":"Tags","description":"Detected tag keys for this call"}},"type":"object","title":"CallTagsListPayload","description":"Lightweight detected tags persisted on a call for list views."},"CallTagsPayload":{"properties":{"tags":{"items":{"$ref":"#/components/schemas/CallTagItem"},"type":"array","title":"Tags","description":"Detected tags for this call"}},"type":"object","title":"CallTagsPayload","description":"Structured detected tags persisted on a call."},"CallTimeTrendPoint":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"total_seconds":{"type":"integer","title":"Total Seconds"},"call_count":{"type":"integer","title":"Call Count"},"avg_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Avg Seconds"},"dashboard_open_percentage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dashboard Open Percentage","description":"Dashboard-open rate (0-100) for this day, each call's percentage weighted by its duration. Calls with no subscriber count as 0%; denominator is every call with line-open time."},"summaries_copied_percentage":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Summaries Copied Percentage","description":"Share of human-answered calls whose summary was copied at least once (0-100) for this day. None when there were no human-answered calls."}},"type":"object","required":["date","total_seconds","call_count"],"title":"CallTimeTrendPoint","description":"Per-day call-time and Whispa usage metrics."},"CallbackRequestRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"source_session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Source Session Id"},"account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Account Id"},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id"},"campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Name"},"customer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Name"},"phone_number":{"type":"string","title":"Phone Number"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"requested_for":{"type":"string","format":"date-time","title":"Requested For"},"timezone":{"type":"string","title":"Timezone"},"status":{"type":"string","title":"Status"},"source":{"type":"string","title":"Source"},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Confirmed At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","phone_number","requested_for","timezone","status","source","created_at","updated_at"],"title":"CallbackRequestRead","description":"Human callback queue row shown to campaign operators."},"CallbackRequestUpdate":{"properties":{"status":{"type":"string","enum":["completed","cancelled"],"title":"Status"}},"type":"object","required":["status"],"title":"CallbackRequestUpdate"},"CampaignAccountRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"account_id":{"type":"string","format":"uuid","title":"Account Id"},"external_id":{"type":"string","title":"External Id"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"display_name":{"type":"string","title":"Display Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"account_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Status"},"status":{"type":"string","title":"Status"},"attempts":{"type":"integer","title":"Attempts"},"last_outcome":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Outcome"},"review_call_session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Review Call Session Id"},"review_reason":{"anyOf":[{"type":"string","enum":["inbound_callback","do_not_contact_request","wrong_person","refused","inbound_engaged"]},{"type":"null"}],"title":"Review Reason"},"next_call_due_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Call Due At"},"owner_campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Owner Campaign Id"},"owner_campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Owner Campaign Name"}},"type":"object","required":["id","account_id","external_id","display_name","status","attempts"],"title":"CampaignAccountRead"},"CampaignAccountStatusUpdate":{"properties":{"action":{"type":"string","enum":["resolved","removed","exhausted","escalated","resume","do_not_contact"],"title":"Action"},"note":{"anyOf":[{"type":"string","maxLength":150},{"type":"null"}],"title":"Note"},"expected_review_call_session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Expected Review Call Session Id"}},"type":"object","required":["action"],"title":"CampaignAccountStatusUpdate","description":"Operator decision on a membership — the review flow's resolution, and\nthe general manual override.\n\nActions, not raw statuses: ``resume`` computes the right live status and\nre-queues a dial, which a bare status write could not express. ``resolved``\ncloses the account's sibling memberships too (a settled debt must not be\nre-dialled by another campaign); ``escalated`` additionally suppresses the\naccount — both mirror the outcome ladder's semantics for the same facts.\n``do_not_contact`` confirms a customer's no-contact request: a permanent\ndo-not-call entry for the number and account, removed from every campaign."},"CampaignAccountTransferRequest":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":3,"title":"Reason"}},"type":"object","required":["reason"],"title":"CampaignAccountTransferRequest"},"CampaignAccountsPreviewRequest":{"properties":{"filter":{"$ref":"#/components/schemas/AccountFilter"},"exclude_account_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"title":"Exclude Account Ids"}},"type":"object","required":["filter"],"title":"CampaignAccountsPreviewRequest","description":"Preview an accounts-table select-all before creating memberships."},"CampaignAccountsPreviewResponse":{"properties":{"selected":{"type":"integer","title":"Selected"},"would_add":{"type":"integer","title":"Would Add"},"already_present":{"type":"integer","title":"Already Present"},"assigned_elsewhere":{"type":"integer","title":"Assigned Elsewhere"}},"type":"object","required":["selected","would_add","already_present","assigned_elsewhere"],"title":"CampaignAccountsPreviewResponse"},"CampaignActivateResponse":{"properties":{"status":{"type":"string","title":"Status"},"scheduled":{"type":"integer","title":"Scheduled"},"blocked":{"type":"integer","title":"Blocked"},"waiting":{"type":"integer","title":"Waiting","default":0}},"type":"object","required":["status","scheduled","blocked"],"title":"CampaignActivateResponse"},"CampaignCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"scenario":{"type":"string","maxLength":100,"minLength":1,"title":"Scenario","description":"ai_agent scenario name"},"policy_overrides":{"additionalProperties":true,"type":"object","title":"Policy Overrides"},"supervised":{"type":"boolean","title":"Supervised","description":"Supervised (dialer) mode: one call in flight at a time, and the campaign holds after every call until the operator resumes.","default":false},"max_concurrent_calls":{"type":"integer","maximum":20.0,"minimum":1.0,"title":"Max Concurrent Calls","description":"How many of this campaign's calls may be in flight at once. The runtime's global capacity cap (AI_CALL_MAX_CONCURRENT) still applies underneath, and supervised mode pins the effective value to 1.","default":1},"voice_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Voice Id","description":"Provider-qualified TTS voice id for this campaign's dials, overriding the scenario's own voice. Null/empty = speak with the scenario's voice."},"cartesia_model":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Cartesia Model","description":"Cartesia TTS model id for this campaign's dials, overriding the scenario's own model. Null/empty = synthesize with the scenario's model."},"opening_line":{"anyOf":[{"type":"string","maxLength":600},{"type":"null"}],"title":"Opening Line","description":"Opening line for this campaign's dials, overriding the scenario's own. A $placeholder template — $agent_name, $company_name, $customer_name and $customer_first_name are substituted per call; any other placeholder stays literal, because the opener is spoken before identity is verified. Null/empty = speak the scenario's opening line."}},"type":"object","required":["name","scenario"],"title":"CampaignCreate"},"CampaignDetail":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"scenario":{"type":"string","title":"Scenario"},"provider":{"type":"string","title":"Provider"},"status":{"type":"string","title":"Status"},"supervised":{"type":"boolean","title":"Supervised","default":false},"max_concurrent_calls":{"type":"integer","title":"Max Concurrent Calls","default":1},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice Id"},"cartesia_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cartesia Model"},"opening_line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Opening Line"},"policy_overrides":{"additionalProperties":true,"type":"object","title":"Policy Overrides"},"progress":{"$ref":"#/components/schemas/CampaignProgress"},"outcomes":{"$ref":"#/components/schemas/CampaignOutcomes"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"can_delete":{"type":"boolean","title":"Can Delete"},"live_calls":{"items":{"$ref":"#/components/schemas/CampaignLiveCall"},"type":"array","title":"Live Calls"},"queue_preview":{"$ref":"#/components/schemas/CampaignQueuePreview"},"accounts":{"items":{"$ref":"#/components/schemas/CampaignAccountRead"},"type":"array","title":"Accounts"}},"type":"object","required":["id","name","scenario","provider","status","progress","created_at","updated_at","can_delete"],"title":"CampaignDetail","description":"Full detail retained for existing API consumers and mutation responses."},"CampaignLiveCall":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id"},"account_name":{"type":"string","title":"Account Name"}},"type":"object","required":["session_id","account_name"],"title":"CampaignLiveCall","description":"One campaign call with an attached live-monitor session."},"CampaignOutcomes":{"properties":{"attempts":{"type":"integer","title":"Attempts","default":0},"reached":{"type":"integer","title":"Reached","default":0},"voicemail":{"type":"integer","title":"Voicemail","default":0},"unclassified":{"type":"integer","title":"Unclassified","default":0},"no_answer":{"type":"integer","title":"No Answer","default":0},"commitments":{"type":"integer","title":"Commitments","default":0},"connect_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Connect Rate"},"commitment_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Commitment Rate"}},"type":"object","title":"CampaignOutcomes","description":"Per-attempt dial outcomes for the campaign, derived at read time.\n\nCounted from the campaign's queue rows joined to the calls they placed, so\nthis is \"what the dialler actually did\" — distinct from\n:class:`CampaignProgress`, which counts where each ACCOUNT currently sits.\nAn account with four attempts contributes four rows here and one there.\n\n``reached`` / ``voicemail`` / ``unclassified`` / ``no_answer`` partition\n``attempts``, so the four always sum. Rates are None (not 0.0) when their\ndenominator is zero: \"no data yet\" and \"zero percent\" must not render the\nsame."},"CampaignProgress":{"properties":{"total":{"type":"integer","title":"Total","default":0},"waiting":{"type":"integer","title":"Waiting","default":0},"pending":{"type":"integer","title":"Pending","default":0},"in_progress":{"type":"integer","title":"In Progress","default":0},"callback":{"type":"integer","title":"Callback","default":0},"review":{"type":"integer","title":"Review","default":0},"exhausted":{"type":"integer","title":"Exhausted","default":0},"resolved":{"type":"integer","title":"Resolved","default":0},"escalated":{"type":"integer","title":"Escalated","default":0},"removed":{"type":"integer","title":"Removed","default":0}},"type":"object","title":"CampaignProgress","description":"Per-status account counts for the campaign list/detail header."},"CampaignQueuePreview":{"properties":{"total":{"type":"integer","title":"Total","default":0},"calls":{"items":{"$ref":"#/components/schemas/CampaignQueuedCall"},"type":"array","title":"Calls"}},"type":"object","title":"CampaignQueuePreview","description":"The first page of pending dials plus the full queue size."},"CampaignQueuedCall":{"properties":{"scheduled_call_id":{"type":"string","format":"uuid","title":"Scheduled Call Id"},"account_id":{"type":"string","format":"uuid","title":"Account Id"},"display_name":{"type":"string","title":"Display Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"due_at":{"type":"string","format":"date-time","title":"Due At"},"reason":{"type":"string","title":"Reason"},"attempt_no":{"type":"integer","title":"Attempt No"},"blocked_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blocked Reason"}},"type":"object","required":["scheduled_call_id","account_id","display_name","due_at","reason","attempt_no"],"title":"CampaignQueuedCall","description":"One pending autonomous dial in the scheduler's deterministic order."},"CampaignRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"scenario":{"type":"string","title":"Scenario"},"provider":{"type":"string","title":"Provider"},"status":{"type":"string","title":"Status"},"supervised":{"type":"boolean","title":"Supervised","default":false},"max_concurrent_calls":{"type":"integer","title":"Max Concurrent Calls","default":1},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice Id"},"cartesia_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cartesia Model"},"opening_line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Opening Line"},"policy_overrides":{"additionalProperties":true,"type":"object","title":"Policy Overrides"},"progress":{"$ref":"#/components/schemas/CampaignProgress"},"outcomes":{"$ref":"#/components/schemas/CampaignOutcomes"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","scenario","provider","status","progress","created_at","updated_at"],"title":"CampaignRead"},"CampaignSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"scenario":{"type":"string","title":"Scenario"},"provider":{"type":"string","title":"Provider"},"status":{"type":"string","title":"Status"},"supervised":{"type":"boolean","title":"Supervised","default":false},"max_concurrent_calls":{"type":"integer","title":"Max Concurrent Calls","default":1},"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice Id"},"cartesia_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cartesia Model"},"opening_line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Opening Line"},"policy_overrides":{"additionalProperties":true,"type":"object","title":"Policy Overrides"},"progress":{"$ref":"#/components/schemas/CampaignProgress"},"outcomes":{"$ref":"#/components/schemas/CampaignOutcomes"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"can_delete":{"type":"boolean","title":"Can Delete"},"live_calls":{"items":{"$ref":"#/components/schemas/CampaignLiveCall"},"type":"array","title":"Live Calls"},"queue_preview":{"$ref":"#/components/schemas/CampaignQueuePreview"}},"type":"object","required":["id","name","scenario","provider","status","progress","created_at","updated_at","can_delete"],"title":"CampaignSummary","description":"Frequently refreshed campaign state, independent of account pagination."},"CampaignUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"supervised":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Supervised","description":"Supervised (dialer) mode: one call in flight at a time, and the campaign holds after every call until the operator resumes."},"max_concurrent_calls":{"anyOf":[{"type":"integer","maximum":20.0,"minimum":1.0},{"type":"null"}],"title":"Max Concurrent Calls","description":"How many of this campaign's calls may be in flight at once. The runtime's global capacity cap (AI_CALL_MAX_CONCURRENT) still applies underneath, and supervised mode pins the effective value to 1."},"voice_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Voice Id","description":"Provider-qualified TTS voice id for this campaign's dials, overriding the scenario's own voice. Null/empty = speak with the scenario's voice."},"cartesia_model":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Cartesia Model","description":"Cartesia TTS model id for this campaign's dials, overriding the scenario's own model. Null/empty = synthesize with the scenario's model."},"opening_line":{"anyOf":[{"type":"string","maxLength":600},{"type":"null"}],"title":"Opening Line","description":"Opening line for this campaign's dials, overriding the scenario's own. A $placeholder template — $agent_name, $company_name, $customer_name and $customer_first_name are substituted per call; any other placeholder stays literal, because the opener is spoken before identity is verified. Null/empty = speak the scenario's opening line."},"policy_overrides":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Policy Overrides"}},"type":"object","title":"CampaignUpdate","description":"Partial update of a campaign's configuration.\n\nEvery field is optional and only the ones the caller actually SENT are\napplied — the service reads ``model_fields_set``, not the values, so\n``{\"voice_id\": null}`` clears the campaign's voice while omitting the key\nleaves it alone. The same distinction applies to ``cartesia_model``. Two\ndifferent intentions that a plain \"is it None?\" check could not tell apart.\n\nThe lifecycle (draft/active/paused/completed) is deliberately absent: it\nmoves through the activate/pause endpoints, which have their own rules.\n``scenario`` is absent too — a campaign's outcomes are reported against the\nscenario it ran, so swapping it mid-flight would make the performance\ndashboard attribute one scenario's calls to another."},"ChatHistoryResponse":{"properties":{"session_id":{"type":"string","title":"Session Id"},"messages":{"items":{"$ref":"#/components/schemas/ChatMessage"},"type":"array","title":"Messages"}},"type":"object","required":["session_id","messages"],"title":"ChatHistoryResponse"},"ChatMessage":{"properties":{"role":{"type":"string","enum":["user","assistant"],"title":"Role"},"content":{"type":"string","title":"Content"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["role","content","created_at"],"title":"ChatMessage"},"ClientCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"aliases":{"items":{"type":"string"},"type":"array","maxItems":50,"title":"Aliases"},"former_names":{"items":{"type":"string"},"type":"array","maxItems":50,"title":"Former Names"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Description"},"guidelines":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Guidelines"},"scenario_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100,"title":"Scenario Ids"}},"type":"object","required":["name"],"title":"ClientCreate"},"ClientRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"aliases":{"items":{"type":"string"},"type":"array","title":"Aliases"},"former_names":{"items":{"type":"string"},"type":"array","title":"Former Names"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"guidelines":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Guidelines"},"is_active":{"type":"boolean","title":"Is Active"},"scenarios":{"items":{"$ref":"#/components/schemas/ClientScenarioRead"},"type":"array","title":"Scenarios"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","is_active","created_at","updated_at"],"title":"ClientRead"},"ClientScenarioRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"}},"type":"object","required":["id","name","display_name"],"title":"ClientScenarioRead"},"ClientSummary":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"has_guidelines":{"type":"boolean","title":"Has Guidelines","default":false}},"type":"object","required":["id","name"],"title":"ClientSummary","description":"Read-safe client context embedded in call detail responses."},"ClientUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"aliases":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":50},{"type":"null"}],"title":"Aliases"},"former_names":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":50},{"type":"null"}],"title":"Former Names"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Description"},"guidelines":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}],"title":"Guidelines"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"scenario_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":100},{"type":"null"}],"title":"Scenario Ids"}},"type":"object","title":"ClientUpdate"},"CoachingFeedback":{"properties":{"dimension_1":{"$ref":"#/components/schemas/FeedbackDimension","description":"First evaluation dimension feedback"},"dimension_2":{"$ref":"#/components/schemas/FeedbackDimension","description":"Second evaluation dimension feedback"},"dimension_3":{"$ref":"#/components/schemas/FeedbackDimension","description":"Third evaluation dimension feedback"}},"type":"object","required":["dimension_1","dimension_2","dimension_3"],"title":"CoachingFeedback","description":"Structured coaching feedback with three evaluation dimensions."},"CoachingFeedbackRating":{"type":"string","enum":["positive","negative"],"title":"CoachingFeedbackRating","description":"User rating for AI-generated coaching feedback."},"CoachingRequest":{"properties":{"transcript":{"items":{"$ref":"#/components/schemas/TranscriptEntry"},"type":"array","title":"Transcript","description":"Conversation transcript"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario","description":"Optional fallback when the call has no persisted scenario"}},"type":"object","required":["transcript"],"title":"CoachingRequest","description":"Request to generate coaching feedback."},"CoachingResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether feedback generation succeeded"},"session_id":{"type":"string","title":"Session Id","description":"Session ID"},"feedback":{"anyOf":[{"$ref":"#/components/schemas/CoachingFeedback"},{"type":"null"}],"description":"The generated coaching feedback (None if not applicable)"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason","description":"Reason when coaching is not applicable"}},"type":"object","required":["success","session_id"],"title":"CoachingResponse","description":"Response containing coaching feedback."},"CoachingUserFeedbackCreate":{"properties":{"rating":{"$ref":"#/components/schemas/CoachingFeedbackRating","description":"Thumbs up (positive) or thumbs down (negative)"},"comment":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Comment","description":"Optional comment to provide additional context"}},"type":"object","required":["rating"],"title":"CoachingUserFeedbackCreate","description":"Request to create/update user feedback on coaching."},"CoachingUserFeedbackResponse":{"properties":{"id":{"type":"string","title":"Id","description":"Feedback ID"},"call_session_id":{"type":"string","title":"Call Session Id","description":"Call session ID"},"rating":{"$ref":"#/components/schemas/CoachingFeedbackRating","description":"User's rating"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment","description":"Optional comment"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"When feedback was created"},"updated_at":{"type":"string","format":"date-time","title":"Updated At","description":"When feedback was last updated"}},"type":"object","required":["id","call_session_id","rating","created_at","updated_at"],"title":"CoachingUserFeedbackResponse","description":"Response containing user's coaching feedback."},"CoachingUserFeedbackStatus":{"properties":{"has_feedback":{"type":"boolean","title":"Has Feedback","description":"Whether user has submitted feedback for this session"},"feedback":{"anyOf":[{"$ref":"#/components/schemas/CoachingUserFeedbackResponse"},{"type":"null"}],"description":"The feedback details if submitted"}},"type":"object","required":["has_feedback"],"title":"CoachingUserFeedbackStatus","description":"Status of coaching feedback for a session."},"CollectionStage":{"type":"string","enum":["open","arrangement","broken_arrangement","paid","settled","excluded","unknown"],"title":"CollectionStage","description":"Provider-neutral collections-funnel position of a CRM's native status.\n\nOrthogonal to :class:`AccountStatusDisposition`, which answers \"may the\nautonomous scheduler dial this account\". The stage answers \"where does\nthis debt sit in the collections funnel\" for reporting: an arrangement in\nplace and a broken arrangement are both not-workable, but they are\nopposite outcomes on a performance dashboard.\n\n``EXCLUDED`` marks accounts whose balance can move without money being\ncollected (disputed, deceased, bankrupt, statute-barred), so recovery\nmetrics can leave them out rather than count adjustments as payments."},"CollectionStageBreakdown":{"properties":{"stage":{"type":"string","title":"Stage"},"accounts":{"type":"integer","title":"Accounts"},"outstanding_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Outstanding Total","description":"Sum of outstanding balances in this stage."},"amount_paid_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount Paid Total","description":"Sum of amounts collected to date in this stage."}},"type":"object","required":["stage","accounts"],"title":"CollectionStageBreakdown","description":"One collections-funnel stage of the filtered working set.\n\n``stage`` is a :class:`src.crm.base.CollectionStage` value; rows the\nprovider never classified (CSV imports, pre-migration cache rows) are\nfolded into ``unknown``. Money totals are ``None`` — not ``0`` — when no\naccount in the stage carries the amount, so \"nothing synced yet\" and\n\"zero dollars\" cannot render the same."},"CollectionsSummaryRead":{"properties":{"total_accounts":{"type":"integer","title":"Total Accounts"},"original_balance_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Original Balance Total","description":"Sum of balances as originally listed, across the filter."},"outstanding_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Outstanding Total","description":"Sum of current outstanding balances, across the filter."},"amount_paid_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount Paid Total","description":"Sum of amounts collected to date, across the filter — actual money received, including partial payments under arrangements."},"arrangement_accounts":{"type":"integer","title":"Arrangement Accounts","description":"Accounts with a payment arrangement in place."},"arrangement_outstanding_total":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrangement Outstanding Total","description":"Outstanding balance on arrangement-stage accounts: the money debtors have committed to pay but have not paid yet."},"resolved_accounts":{"type":"integer","title":"Resolved Accounts","description":"Accounts paid in full or settled (stages paid + settled)."},"stages":{"items":{"$ref":"#/components/schemas/CollectionStageBreakdown"},"type":"array","title":"Stages"}},"type":"object","required":["total_accounts","arrangement_accounts","resolved_accounts"],"title":"CollectionsSummaryRead","description":"Money outcomes of the filtered working set, aggregated per stage.\n\nEvaluates the same :class:`AccountFilter` predicate as ``/accounts/search``\n— the summary always describes exactly the rows the table shows. Amounts\ncome from the provider's own figures (Collect's paid-to-date), not from\noriginal-minus-outstanding arithmetic, which would misread interest\naccrual and write-off adjustments as payments."},"CollexusDeliveredFileRead":{"properties":{"business_date":{"type":"string","format":"date","title":"Business Date"},"filename":{"type":"string","title":"Filename"},"row_count":{"type":"integer","title":"Row Count"},"adopted":{"type":"boolean","title":"Adopted"},"delivered_at":{"type":"string","format":"date-time","title":"Delivered At"}},"type":"object","required":["business_date","filename","row_count","adopted","delivered_at"],"title":"CollexusDeliveredFileRead"},"CollexusExchangeSettingsUpdate":{"properties":{"return_file_scenarios":{"items":{"type":"string"},"type":"array","title":"Return File Scenarios"},"ingest_scheduled":{"type":"boolean","title":"Ingest Scheduled","default":false},"return_file_scheduled":{"type":"boolean","title":"Return File Scheduled","default":false}},"type":"object","title":"CollexusExchangeSettingsUpdate","description":"An admin's choices for the exchange, saved together."},"CollexusExchangeStatusResponse":{"properties":{"available":{"type":"boolean","title":"Available"},"configured":{"type":"boolean","title":"Configured","default":false},"missing_settings":{"items":{"type":"string"},"type":"array","title":"Missing Settings"},"mode":{"anyOf":[{"type":"string","enum":["pinned","discovery"]},{"type":"null"}],"title":"Mode"},"host":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Host"},"port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Port"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"inbound_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inbound Path"},"outbound_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outbound Path"},"settings_saved":{"type":"boolean","title":"Settings Saved","default":false},"ingest_scheduled":{"type":"boolean","title":"Ingest Scheduled","default":false},"return_file_scheduled":{"type":"boolean","title":"Return File Scheduled","default":false},"return_file_scenarios":{"items":{"type":"string"},"type":"array","title":"Return File Scenarios"},"scenario_options":{"items":{"$ref":"#/components/schemas/CollexusScenarioOption"},"type":"array","title":"Scenario Options"},"return_file_timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Return File Timezone"},"return_file_deliver_after_hour":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Return File Deliver After Hour"},"freshness_gate_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Freshness Gate Minutes"},"last_file":{"anyOf":[{"$ref":"#/components/schemas/CollexusIngestedFileRead"},{"type":"null"}]},"last_import":{"anyOf":[{"$ref":"#/components/schemas/CollexusIngestedFileRead"},{"type":"null"}]},"ingest_run":{"anyOf":[{"$ref":"#/components/schemas/CollexusIngestRunRead"},{"type":"null"}]},"last_delivery":{"anyOf":[{"$ref":"#/components/schemas/CollexusDeliveredFileRead"},{"type":"null"}]}},"type":"object","required":["available"],"title":"CollexusExchangeStatusResponse","description":"What the Integrations card shows. Read from settings and the two\nledgers only: it opens no connection, so it is cheap to poll."},"CollexusIngestRunRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","enum":["running","imported","nothing_new","failed","busy"],"title":"Status"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"listed":{"type":"integer","title":"Listed","default":0},"imported":{"type":"integer","title":"Imported","default":0},"superseded":{"type":"integer","title":"Superseded","default":0},"failed":{"type":"integer","title":"Failed","default":0},"accounts":{"type":"integer","title":"Accounts","default":0},"unrecognised_statuses":{"items":{"$ref":"#/components/schemas/CollexusUnrecognisedStatus"},"type":"array","title":"Unrecognised Statuses"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"finished_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Finished At"}},"type":"object","required":["id","status","started_at"],"title":"CollexusIngestRunRead","description":"One import an admin asked for, as it stands now."},"CollexusIngestRunResponse":{"properties":{"status":{"type":"string","enum":["started","busy","not_configured","untrusted"],"title":"Status"},"detail":{"type":"string","title":"Detail"},"run":{"anyOf":[{"$ref":"#/components/schemas/CollexusIngestRunRead"},{"type":"null"}]}},"type":"object","required":["status","detail"],"title":"CollexusIngestRunResponse","description":"The answer to \"import the latest file now\": started, or why not.\n\nIt comes back at once. The import's outcome is on ``run``, and on the\nexchange status, once the poll finishes."},"CollexusIngestedFileRead":{"properties":{"filename":{"type":"string","title":"Filename"},"status":{"type":"string","title":"Status"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"accounts_imported":{"type":"integer","title":"Accounts Imported","default":0},"remote_modified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Remote Modified At"},"consumed_at":{"type":"string","format":"date-time","title":"Consumed At"}},"type":"object","required":["filename","status","consumed_at"],"title":"CollexusIngestedFileRead"},"CollexusRemoteFileRead":{"properties":{"filename":{"type":"string","title":"Filename"},"size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Size"},"modified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Modified At"}},"type":"object","required":["filename"],"title":"CollexusRemoteFileRead"},"CollexusReturnFileDeliveryResponse":{"properties":{"status":{"type":"string","enum":["uploaded","already_delivered","confirmed","adopted","not_configured","untrusted","day_not_complete","busy","failed"],"title":"Status"},"detail":{"type":"string","title":"Detail"},"business_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Business Date"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"remote_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Remote Path"},"row_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Row Count"},"byte_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Byte Size"},"content_sha256":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Sha256"},"delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Delivered At"}},"type":"object","required":["status","detail"],"title":"CollexusReturnFileDeliveryResponse","description":"One requested delivery, and what the ledger now says about that day."},"CollexusReturnFileResponse":{"properties":{"status":{"type":"string","enum":["ok","not_configured"],"title":"Status"},"detail":{"type":"string","title":"Detail"},"business_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Business Date"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"scenarios":{"items":{"type":"string"},"type":"array","title":"Scenarios"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename"},"remote_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Remote Path"},"row_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Row Count"},"byte_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Byte Size"},"content_sha256":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Content Sha256"},"columns":{"items":{"type":"string"},"type":"array","title":"Columns"},"delivered_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Delivered At"},"delivered_sha256":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Delivered Sha256"},"csv_text":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Csv Text"}},"type":"object","required":["status","detail"],"title":"CollexusReturnFileResponse","description":"One generated activity return file, reported without being uploaded.\n\n``csv_text`` is the complete file exactly as it would be delivered, so the\nagreed format can be checked before anything reaches the creditor's folder.\nIt therefore carries customer phone numbers, references and call summaries\n— the same admin-only exposure as ``GET /accounts/export``, and the reason\nthis route is gated to admins."},"CollexusScenarioOption":{"properties":{"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"}},"type":"object","required":["name","display_name"],"title":"CollexusScenarioOption"},"CollexusSftpCheckResponse":{"properties":{"status":{"type":"string","enum":["ok","discovery","not_configured","failed"],"title":"Status"},"detail":{"type":"string","title":"Detail"},"mode":{"anyOf":[{"type":"string","enum":["pinned","discovery"]},{"type":"null"}],"title":"Mode"},"host":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Host"},"port":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Port"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"missing_settings":{"items":{"type":"string"},"type":"array","title":"Missing Settings"},"reachable":{"type":"boolean","title":"Reachable","default":false},"host_key_pinned":{"type":"boolean","title":"Host Key Pinned","default":false},"host_key_verified":{"type":"boolean","title":"Host Key Verified","default":false},"host_key_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Host Key Type"},"host_key_fingerprint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Host Key Fingerprint"},"host_key_line":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Host Key Line"},"authenticated":{"type":"boolean","title":"Authenticated","default":false},"inbound_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inbound Path"},"outbound_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outbound Path"},"inbound_entries":{"anyOf":[{"items":{"$ref":"#/components/schemas/CollexusRemoteFileRead"},"type":"array"},{"type":"null"}],"title":"Inbound Entries"}},"type":"object","required":["status","detail"],"title":"CollexusSftpCheckResponse","description":"What one connection check learned, in the order a human reads it."},"CollexusUnrecognisedStatus":{"properties":{"status":{"type":"string","title":"Status"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["status","count"],"title":"CollexusUnrecognisedStatus"},"CommitmentHorizon":{"type":"string","enum":["immediate","within_7d","within_30d","beyond_30d","indefinite"],"title":"CommitmentHorizon","description":"When the committed money is expected to land."},"CommitmentShape":{"type":"string","enum":["new_arrangement","immediate_payment","settlement","arrangement_repair","promise_reset","deferral","refused","other"],"title":"CommitmentShape","description":"Taxonomy of commitment outcomes extracted from a collections call."},"ComplianceAlert":{"properties":{"threshold":{"type":"number","title":"Threshold"},"affected_agents":{"items":{"type":"string"},"type":"array","title":"Affected Agents"}},"type":"object","required":["threshold","affected_agents"],"title":"ComplianceAlert","description":"Agents currently below the QA score threshold."},"ConnectedDurationCurvePoint":{"properties":{"threshold_seconds":{"type":"integer","title":"Threshold Seconds"},"calls_at_or_above_threshold":{"type":"integer","title":"Calls At Or Above Threshold"},"rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rate","description":"Share of connected calls with a recorded duration that lasted at least this many seconds (0-100)."}},"type":"object","required":["threshold_seconds","calls_at_or_above_threshold","rate"],"title":"ConnectedDurationCurvePoint","description":"One point on the connected-call survival curve."},"ConnectedDurationMetrics":{"properties":{"connected_calls":{"type":"integer","title":"Connected Calls"},"measured_connected_calls":{"type":"integer","title":"Measured Connected Calls","description":"Connected calls with a recorded non-negative duration."},"curve":{"items":{"$ref":"#/components/schemas/ConnectedDurationCurvePoint"},"type":"array","title":"Curve"},"trend":{"items":{"$ref":"#/components/schemas/ConnectedDurationTrendPoint"},"type":"array","title":"Trend"}},"type":"object","required":["connected_calls","measured_connected_calls","curve","trend"],"title":"ConnectedDurationMetrics","description":"Duration-based retention, independent of answer/outcome classifiers.\n\nCarries the curve at every threshold, overall and per day, so the client\nselects a threshold without another request."},"ConnectedDurationTrendPoint":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"measured_connected_calls":{"type":"integer","title":"Measured Connected Calls"},"curve":{"items":{"$ref":"#/components/schemas/ConnectedDurationCurvePoint"},"type":"array","title":"Curve"}},"type":"object","required":["date","measured_connected_calls","curve"],"title":"ConnectedDurationTrendPoint","description":"One day's connected-call survival curve."},"ContactClassification":{"type":"string","enum":["contact","contact_unknown","attempt","in_progress","not_counted"],"title":"ContactClassification","description":"What a call counts as for the frequency caps."},"ContactEventRead":{"properties":{"occurred_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Occurred On"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"channel":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel"},"completed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Completed"},"done_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Done Date"}},"type":"object","title":"ContactEventRead","description":"Wire shape for a prior contact. Mirrors `src.crm.base.ContactEvent`."},"ConversationOutcome":{"type":"string","enum":["engaged","refused","wrong_person","other"],"title":"ConversationOutcome","description":"AI-classified judgement of what kind of conversation occurred.\n\nOnly applicable when answered_by=HUMAN. Runtime actions such as scheduling\na callback or transferring the caller are recorded independently in\n``WorkflowDisposition`` and must never overwrite this judgement."},"CorrectClassificationRequest":{"properties":{"answered_by":{"anyOf":[{"$ref":"#/components/schemas/AnsweredBy"},{"type":"null"}],"description":"Corrected value for who answered (human, voicemail, unclear)"},"conversation_outcome":{"anyOf":[{"$ref":"#/components/schemas/ConversationOutcome"},{"type":"null"}],"description":"Corrected conversation outcome. Only valid when the call's answered_by is (or is being corrected to) 'human'; explicit null clears it."},"note":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Note","description":"Why the correction was made; stored on the audit row"}},"type":"object","title":"CorrectClassificationRequest","description":"Admin correction of a finalized call's classification.\n\nBoth fields are optional; at least one must be present. Omitting a field\nleaves it alone, which is why ``conversation_outcome`` distinguishes\n\"absent\" from \"explicitly null\" via ``model_fields_set`` — sending null is a\nrequest to clear it."},"CorrectClassificationResponse":{"properties":{"call":{"$ref":"#/components/schemas/CallDetailResponse","description":"The call after the correction"},"membership_reopened":{"type":"boolean","title":"Membership Reopened","description":"Whether a campaign membership this outcome had closed was returned to in_progress. The campaign still needs activating before the next call goes out."},"cancelled_scheduled_calls":{"type":"integer","title":"Cancelled Scheduled Calls","description":"Queued automated attempts cancelled because the corrected outcome is one the retry ladder stops on. Only unclaimed attempts are cancelled, so a call already being placed is never interrupted.","default":0},"membership_held_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Membership Held Reason","description":"Set when the campaign membership stayed closed even though the label that closed it was corrected away: 'attempts_exhausted' (the policy's attempt budget is spent) or 'commitment_still_refused' (the commitment classifier independently says the customer refused). Tells the reviewer why the account did not come back."},"invalidated_artifacts":{"items":{"type":"string"},"type":"array","title":"Invalidated Artifacts","description":"Human-only artifacts cleared because the call is no longer marked human-answered (summary, coaching, tags, qa_scorecard, idv, ...)"},"summary_regeneration_available":{"type":"boolean","title":"Summary Regeneration Available","description":"The call is now human-answered but carries a no-contact stub summary; retrying finalization would regenerate its artifacts.","default":false}},"type":"object","required":["call","membership_reopened"],"title":"CorrectClassificationResponse","description":"The corrected call plus what the correction changed beyond the two fields.\n\nThe side effects are the point of the feature — a reviewer needs to know\nwhether the campaign actually reopened and what a re-marked non-human call\njust threw away — so they are reported explicitly instead of being left for\nthe client to infer from the refreshed detail."},"CrmAccountSummary":{"properties":{"provider":{"type":"string","title":"Provider"},"id":{"type":"string","title":"Id"},"display_name":{"type":"string","title":"Display Name"},"phones":{"items":{"type":"string"},"type":"array","title":"Phones"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"dob":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Dob"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"ssn_last4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ssn Last4"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"matched_contact_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matched Contact Type"},"context":{"anyOf":[{"$ref":"#/components/schemas/AccountContextRead"},{"type":"null"}]}},"type":"object","required":["provider","id","display_name"],"title":"CrmAccountSummary"},"CrmCallLinkRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"decision":{"type":"string","enum":["linked","none_of_these"],"title":"Decision"},"account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Id"},"account_row_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Account Row Id"},"account_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Display Name"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"matched_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matched Phone"},"matched_on":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Matched On"},"linked_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Linked By User Id"},"linked_at":{"type":"string","format":"date-time","title":"Linked At"},"identity":{"anyOf":[{"$ref":"#/components/schemas/CrmIdentityReferenceRead"},{"type":"null"}]},"context":{"anyOf":[{"$ref":"#/components/schemas/AccountContextRead"},{"type":"null"}]}},"type":"object","required":["id","provider","decision","linked_at"],"title":"CrmCallLinkRead"},"CrmIdentityReferenceRead":{"properties":{"full_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name"},"phones":{"items":{"type":"string"},"type":"array","title":"Phones"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"dob":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Dob"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"ssn_last4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ssn Last4"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"}},"type":"object","title":"CrmIdentityReferenceRead","description":"Minimal linked-account identity facts needed by IDV cards."},"CrmIntegrationConfig":{"properties":{"provider":{"type":"string","enum":["collect","spark"],"title":"Provider"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"}},"type":"object","required":["provider"],"title":"CrmIntegrationConfig"},"CrmIntegrationResponse":{"properties":{"provider":{"type":"string","enum":["collect","spark"],"title":"Provider"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"},"id":{"type":"string","format":"uuid","title":"Id"}},"type":"object","required":["provider","id"],"title":"CrmIntegrationResponse"},"CrmLinkRequest":{"properties":{"account_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Id","description":"Candidate account id to link. Omit for none_of_these."},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number","description":"Candidate account number selected by the agent."},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id","description":"Candidate customer id selected by the agent."},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id","description":"Owning creditor / client id of the selected candidate."},"decision":{"type":"string","enum":["linked","none_of_these"],"title":"Decision","default":"linked"}},"type":"object","title":"CrmLinkRequest"},"CrmLookupRequest":{"properties":{"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Phone number to match"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email","description":"Email address to match"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Customer name to match"},"dob":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Dob","description":"Date of birth to match"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number","description":"Provider-side account number to match"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id","description":"Provider-side customer id to match"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id","description":"Owning creditor / client id to match"}},"type":"object","title":"CrmLookupRequest"},"CrmLookupResponse":{"properties":{"candidates":{"items":{"$ref":"#/components/schemas/CrmAccountSummary"},"type":"array","title":"Candidates"},"total_matched":{"type":"integer","title":"Total Matched","default":0},"truncated":{"type":"boolean","title":"Truncated","default":false}},"type":"object","title":"CrmLookupResponse"},"CrmNoteExportRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"status":{"type":"string","enum":["pending","success","failed"],"title":"Status"},"kind":{"type":"string","enum":["outcome","manual"],"title":"Kind","default":"outcome"},"provider_note_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Note Id"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"requested_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Requested By User Id"},"attempted_at":{"type":"string","format":"date-time","title":"Attempted At"},"already_saved":{"type":"boolean","title":"Already Saved","default":false}},"type":"object","required":["id","provider","status","attempted_at"],"title":"CrmNoteExportRead"},"CrmSaveNoteResponse":{"properties":{"provider":{"type":"string","title":"Provider"},"note_id":{"type":"string","title":"Note Id"},"export":{"$ref":"#/components/schemas/CrmNoteExportRead"},"already_saved":{"type":"boolean","title":"Already Saved","default":false}},"type":"object","required":["provider","note_id","export"],"title":"CrmSaveNoteResponse"},"CrmStateResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider"},"link":{"anyOf":[{"$ref":"#/components/schemas/CrmCallLinkRead"},{"type":"null"}]},"latest_export":{"anyOf":[{"$ref":"#/components/schemas/CrmNoteExportRead"},{"type":"null"}]},"latest_manual_export":{"anyOf":[{"$ref":"#/components/schemas/CrmNoteExportRead"},{"type":"null"}]}},"type":"object","required":["enabled"],"title":"CrmStateResponse"},"CrmTestConnectionResponse":{"properties":{"provider":{"type":"string","enum":["collect","spark"],"title":"Provider"},"status":{"type":"string","const":"ok","title":"Status","default":"ok"},"message":{"type":"string","title":"Message"},"operator_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Operator Id"},"sample_lookup_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sample Lookup Count"}},"type":"object","required":["provider","message"],"title":"CrmTestConnectionResponse"},"CsvAccountImportResult":{"properties":{"run":{"$ref":"#/components/schemas/AccountSyncRunRead"},"total_rows":{"type":"integer","title":"Total Rows"},"imported":{"type":"integer","title":"Imported"},"created":{"type":"integer","title":"Created"},"updated":{"type":"integer","title":"Updated"},"skipped":{"type":"integer","title":"Skipped"},"warnings":{"items":{"type":"string"},"type":"array","title":"Warnings"}},"type":"object","required":["run","total_rows","imported","created","updated","skipped"],"title":"CsvAccountImportResult","description":"Outcome of one atomic, server-validated CSV account import."},"CustomActionCardContractGenerateRequest":{"properties":{"intent_prompt":{"type":"string","minLength":1,"title":"Intent Prompt","description":"Natural-language description of what the action card should do"},"current_name":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Current Name","description":"Existing tool name to preserve when regenerating"},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category","description":"Preferred category hint"}},"type":"object","required":["intent_prompt"],"title":"CustomActionCardContractGenerateRequest","description":"Input payload for generating tool contract from intent."},"CustomActionCardContractGenerateResponse":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name"},"description":{"type":"string","minLength":1,"title":"Description"},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema","description":"JSON schema used as LLM function parameters"},"ui_prompt":{"type":"string","minLength":1,"title":"Ui Prompt","description":"Prompt describing desired UI style and behavior"}},"type":"object","required":["name","display_name","description","ui_prompt"],"title":"CustomActionCardContractGenerateResponse","description":"Generated tool contract used for card creation and tool calling."},"CustomActionCardCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Unique tool identifier"},"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name","description":"Human-readable name"},"description":{"type":"string","minLength":1,"title":"Description","description":"Card description"},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category","description":"Category label"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema","description":"JSON schema used as LLM function parameters"},"ui_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ui Prompt","description":"Prompt describing desired UI and interaction"},"is_active":{"type":"boolean","title":"Is Active","description":"Whether the card is available","default":true},"component_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Component Source","description":"Reviewable generated component source"}},"type":"object","required":["name","display_name","description"],"title":"CustomActionCardCreate","description":"Input schema for creating a custom action card."},"CustomActionCardGenerateRequest":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name"},"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name"},"description":{"type":"string","minLength":1,"title":"Description"},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema","description":"JSON schema used as LLM function parameters"},"ui_prompt":{"type":"string","minLength":1,"title":"Ui Prompt","description":"Prompt describing desired UI and interaction"}},"type":"object","required":["name","display_name","description","ui_prompt"],"title":"CustomActionCardGenerateRequest","description":"Input payload for generated card component source."},"CustomActionCardGenerateResponse":{"properties":{"component_source":{"type":"string","title":"Component Source"}},"type":"object","required":["component_source"],"title":"CustomActionCardGenerateResponse","description":"Generated source code response."},"CustomActionCardResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema"},"ui_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ui Prompt"},"component_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Component Source"},"is_active":{"type":"boolean","title":"Is Active"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"updated_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Updated By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","display_name","description","category","input_schema","ui_prompt","component_source","is_active","created_by","updated_by","created_at","updated_at"],"title":"CustomActionCardResponse","description":"Full response for admin management screens."},"CustomActionCardRuntimeResponse":{"properties":{"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"component_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Component Source"}},"type":"object","required":["name","display_name","description","category","component_source"],"title":"CustomActionCardRuntimeResponse","description":"Runtime payload for rendering cards in the call UI."},"CustomActionCardUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Name"},"display_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Display Name"},"description":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Description"},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category"},"input_schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Input Schema"},"ui_prompt":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Ui Prompt"},"component_source":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Component Source"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"CustomActionCardUpdate","description":"Input schema for updating a custom action card."},"DoNotCallCreate":{"properties":{"phone_number":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Phone Number"},"provider":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Provider"},"external_id":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"External Id"},"reason":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Reason"}},"type":"object","title":"DoNotCallCreate"},"DoNotCallRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"phone_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone Number"},"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider"},"external_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"External Id"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"source":{"type":"string","title":"Source"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","source","created_at"],"title":"DoNotCallRead"},"EditSummaryRequest":{"properties":{"summary_markdown":{"type":"string","minLength":1,"title":"Summary Markdown","description":"The edited markdown summary to persist. Must not be empty or whitespace-only."}},"type":"object","required":["summary_markdown"],"title":"EditSummaryRequest","description":"Request to overwrite the stored call summary with agent-edited markdown."},"EgressAiCallAgreement":{"properties":{"amount":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Amount"},"date_iso":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Iso"},"date_spoken":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Spoken"},"method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Method"},"frequency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Frequency"}},"type":"object","title":"EgressAiCallAgreement","description":"Customer-confirmed terms recorded by the autonomous runtime."},"EgressAiCallPayment":{"properties":{"provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider"},"invoice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invoice Id"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"link_opened":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Link Opened"},"link_delivery_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Link Delivery Status"}},"type":"object","title":"EgressAiCallPayment","description":"Safe payment status persisted by the autonomous runtime.\n\nA payable URL is intentionally not part of this schema or the underlying\nartifact; ``invoice_id`` is sufficient for an authorized operator to look\nthe payment up in Glider."},"EgressCallBundle":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"metadata":{"anyOf":[{"$ref":"#/components/schemas/EgressCallMetadata"},{"type":"null"}]},"outcome":{"anyOf":[{"$ref":"#/components/schemas/EgressOutcomeResponse"},{"type":"null"}]},"transcript":{"anyOf":[{"$ref":"#/components/schemas/EgressTranscriptResponse"},{"type":"null"}]},"summary":{"anyOf":[{"$ref":"#/components/schemas/EgressSummaryResponse"},{"type":"null"}]},"coaching":{"anyOf":[{"$ref":"#/components/schemas/EgressCoachingResponse"},{"type":"null"}]},"scorecard":{"anyOf":[{"$ref":"#/components/schemas/EgressScorecardResponse"},{"type":"null"}]},"tool_calls":{"anyOf":[{"$ref":"#/components/schemas/EgressToolCallsResponse"},{"type":"null"}]},"latency":{"anyOf":[{"$ref":"#/components/schemas/CallLatencySummary"},{"type":"null"}]},"idv":{"anyOf":[{"$ref":"#/components/schemas/IdvRecord"},{"type":"null"}]},"langfuse":{"anyOf":[{"$ref":"#/components/schemas/EgressLangfuseBundle"},{"type":"null"}]},"generated_at":{"type":"string","format":"date-time","title":"Generated At"},"omitted":{"items":{"$ref":"#/components/schemas/EgressOmittedSection"},"type":"array","title":"Omitted"}},"type":"object","required":["call_id","metadata","outcome","transcript","summary","coaching","scorecard","tool_calls","latency","idv","langfuse","generated_at","omitted"],"title":"EgressCallBundle","description":"One-shot, PII-scrubbed analysis context for a call.\n\nLatency is intentionally included even though the cookie-auth call-detail\nAPI restricts it to admins: egress is separately machine-authenticated and\nlatency is a first-class debugging signal. The value is a numeric rollup\nproduced by ``calls.latency_rollup`` and requires no text scrubbing."},"EgressCallMetadata":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"call_mode":{"anyOf":[{"$ref":"#/components/schemas/CallMode"},{"type":"null"}]},"call_source":{"anyOf":[{"$ref":"#/components/schemas/CallSource"},{"type":"null"}]},"call_direction":{"anyOf":[{"$ref":"#/components/schemas/CallDirection"},{"type":"null"}]},"status":{"anyOf":[{"$ref":"#/components/schemas/CallStatus"},{"type":"null"}]},"started_at":{"type":"string","format":"date-time","title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ended At"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"conversation_outcome":{"anyOf":[{"$ref":"#/components/schemas/ConversationOutcome"},{"type":"null"}]},"workflow_disposition":{"anyOf":[{"$ref":"#/components/schemas/WorkflowDisposition"},{"type":"null"}]},"agent_end_reason":{"anyOf":[{"$ref":"#/components/schemas/AgentEndReason"},{"type":"null"}]},"answered_by":{"anyOf":[{"$ref":"#/components/schemas/AnsweredBy"},{"type":"null"}]},"telephony_result":{"anyOf":[{"$ref":"#/components/schemas/TelephonyResult"},{"type":"null"}]},"detected_scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detected Scenario"},"client":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client"},"qa_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Qa Score"},"idv_outcome":{"anyOf":[{"$ref":"#/components/schemas/IdvOutcome"},{"type":"null"}]},"idv_source":{"anyOf":[{"$ref":"#/components/schemas/IdvSource"},{"type":"null"}]},"recording_disclosed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Recording Disclosed"},"tags":{"anyOf":[{},{"type":"null"}],"title":"Tags","description":"Detected call tags; transcript evidence is scrubbed"},"agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Id"},"account_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Account Id","description":"Opaque Whispa account row id (the Accounts page id) the call is linked to; null when unlinked or the account was never synced"}},"type":"object","required":["id","scenario","call_mode","call_source","call_direction","status","started_at","ended_at","duration_seconds","conversation_outcome","workflow_disposition","agent_end_reason","answered_by","telephony_result","detected_scenario","client","qa_score","idv_outcome","idv_source","recording_disclosed","agent_id"],"title":"EgressCallMetadata","description":"Allowlisted call metadata (no customer identity, no audio)."},"EgressCallOutcome":{"properties":{"commitment_shape":{"$ref":"#/components/schemas/CommitmentShape"},"commitment_horizon":{"anyOf":[{"$ref":"#/components/schemas/CommitmentHorizon"},{"type":"null"}]},"is_new_commitment":{"type":"boolean","title":"Is New Commitment"},"installment_amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Installment Amount"},"first_payment_amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"First Payment Amount"},"payment_frequency":{"anyOf":[{"$ref":"#/components/schemas/PaymentFrequency"},{"type":"null"}]},"installment_count":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Installment Count"},"explicit_total_amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Explicit Total Amount"},"total_commitment_amount":{"anyOf":[{"type":"number","minimum":0.0},{"type":"null"}],"title":"Total Commitment Amount"},"total_commitment_source":{"$ref":"#/components/schemas/TotalCommitmentSource"},"confidence":{"type":"number","maximum":1.0,"minimum":0.0,"title":"Confidence"},"evidence_quote":{"type":"string","minLength":1,"title":"Evidence Quote","description":"Supporting transcript excerpt; scrubbed"}},"type":"object","required":["commitment_shape","commitment_horizon","is_new_commitment","installment_amount","first_payment_amount","payment_frequency","installment_count","explicit_total_amount","total_commitment_amount","total_commitment_source","confidence","evidence_quote"],"title":"EgressCallOutcome","description":"Structured collections commitment with transcript evidence scrubbed."},"EgressCoachingResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"coaching":{"$ref":"#/components/schemas/CoachingFeedback"}},"type":"object","required":["call_id","coaching"],"title":"EgressCoachingResponse","description":"Structured, scrubbed coaching generated for a call."},"EgressDiscoveredCall":{"properties":{"metadata":{"$ref":"#/components/schemas/EgressCallMetadata"},"revision":{"type":"string","title":"Revision","description":"Opaque persisted revision; deduplicate with call ID"},"changed_at":{"type":"string","format":"date-time","title":"Changed At"}},"type":"object","required":["metadata","revision","changed_at"],"title":"EgressDiscoveredCall"},"EgressDiscoveryPage":{"properties":{"items":{"items":{"$ref":"#/components/schemas/EgressDiscoveredCall"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor","description":"Continue this page sequence, if present"},"checkpoint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checkpoint","description":"Resume /egress/calls/changes after durably saving the results. Change feeds issue a checkpoint only after the window is drained."}},"type":"object","required":["items","next_cursor","checkpoint"],"title":"EgressDiscoveryPage"},"EgressIdvResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"record":{"anyOf":[{"$ref":"#/components/schemas/IdvRecord"},{"type":"null"}]}},"type":"object","required":["call_id","record"],"title":"EgressIdvResponse","description":"A call's value-free IDV record: factor keys, labels and seconds only."},"EgressLangfuseBundle":{"properties":{"traces":{"items":{"$ref":"#/components/schemas/EgressTrace"},"type":"array","title":"Traces"},"traces_truncated":{"type":"boolean","title":"Traces Truncated"},"generations":{"items":{"$ref":"#/components/schemas/EgressLangfuseGeneration"},"type":"array","title":"Generations"},"session_filter":{"type":"string","title":"Session Filter","description":"JSON filter value for Langfuse's v2 observations endpoint"}},"type":"object","required":["traces","traces_truncated","generations","session_filter"],"title":"EgressLangfuseBundle","description":"Inline scrubbed traces plus a compact generation index."},"EgressLangfuseGeneration":{"properties":{"generation_name":{"type":"string","title":"Generation Name"},"trace_id":{"type":"string","title":"Trace Id"},"trace_url":{"type":"string","title":"Trace Url"}},"type":"object","required":["generation_name","trace_id","trace_url"],"title":"EgressLangfuseGeneration","description":"Deep link to one Langfuse generation represented in the trace payload."},"EgressLatencyResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"summary":{"anyOf":[{"$ref":"#/components/schemas/CallLatencySummary"},{"type":"null"}]},"turns":{"items":{"$ref":"#/components/schemas/EgressVoiceLatencyTurn"},"type":"array","title":"Turns"}},"type":"object","required":["call_id","summary","turns"],"title":"EgressLatencyResponse","description":"A call's latency rollup and the autonomous-voice turns behind it."},"EgressOmittedSection":{"properties":{"section":{"type":"string","title":"Section"},"reason":{"type":"string","title":"Reason"}},"type":"object","required":["section","reason"],"title":"EgressOmittedSection","description":"A bundle section that was unavailable or withheld."},"EgressOutcomeResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"call_outcome":{"anyOf":[{"$ref":"#/components/schemas/EgressCallOutcome"},{"type":"null"}]},"workflow_disposition":{"anyOf":[{"$ref":"#/components/schemas/WorkflowDisposition"},{"type":"null"}]},"agent_end_reason":{"anyOf":[{"$ref":"#/components/schemas/AgentEndReason"},{"type":"null"}]},"ai_call_end_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ai Call End Reason"},"ai_call_identity_verified":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ai Call Identity Verified"},"ai_call_agreement":{"anyOf":[{"$ref":"#/components/schemas/EgressAiCallAgreement"},{"type":"null"}]},"ai_call_payment":{"anyOf":[{"$ref":"#/components/schemas/EgressAiCallPayment"},{"type":"null"}]}},"type":"object","required":["call_id","call_outcome","workflow_disposition","agent_end_reason","ai_call_end_reason","ai_call_identity_verified","ai_call_agreement","ai_call_payment"],"title":"EgressOutcomeResponse","description":"Post-call outcome plus deterministic autonomous-runtime facts."},"EgressScorecardItem":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"score_type":{"type":"string","enum":["pass_fail","numeric"],"title":"Score Type"},"result":{"type":"string","enum":["met","not_met","not_applicable"],"title":"Result"},"score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score"},"max_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Score"},"score_excluded":{"type":"boolean","title":"Score Excluded"},"manual_review":{"type":"boolean","title":"Manual Review"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment","description":"Model rationale; scrubbed"},"evidence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evidence","description":"Transcript snippet; scrubbed"}},"type":"object","required":["key","title","score_type","result","score","max_score","score_excluded","manual_review"],"title":"EgressScorecardItem","description":"One scored QA scorecard item; model-written text scrubbed.\n\nKeys, titles, and scores are structural (template config + computed\nnumbers) and pass through untouched. ``comment`` and ``evidence`` are\nwritten by the model from the transcript, so both are scrubbed."},"EgressScorecardResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"template_key":{"type":"string","title":"Template Key"},"display_name":{"type":"string","title":"Display Name"},"generated_at":{"type":"string","format":"date-time","title":"Generated At"},"status":{"type":"string","title":"Status"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Reviewed At"},"overall_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Overall Score"},"total_max_score":{"type":"integer","title":"Total Max Score"},"pass_fail_status":{"anyOf":[{"type":"string","enum":["pass","fail","not_applicable"]},{"type":"null"}],"title":"Pass Fail Status"},"auto_fail":{"type":"boolean","title":"Auto Fail"},"auto_fail_reasons":{"items":{"type":"string"},"type":"array","title":"Auto Fail Reasons"},"sections":{"items":{"$ref":"#/components/schemas/EgressScorecardSection"},"type":"array","title":"Sections"},"commentary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commentary","description":"Overall QA commentary; scrubbed"}},"type":"object","required":["call_id","template_key","display_name","generated_at","status","reviewed_at","overall_score","total_max_score","pass_fail_status","auto_fail","auto_fail_reasons","sections"],"title":"EgressScorecardResponse","description":"Allowlisted QA scorecard.\n\nReviewer-identity fields on the stored artifact (``reviewed_by_name``,\n``reviewed_by_user_id``) are deliberately absent — ``status`` still tells\nthe agent whether a human reviewed it. All free text is scrubbed."},"EgressScorecardSection":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"items":{"items":{"$ref":"#/components/schemas/EgressScorecardItem"},"type":"array","title":"Items"},"subtotal":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subtotal"},"subtotal_max_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subtotal Max Score"}},"type":"object","required":["key","title","items","subtotal","subtotal_max_score"],"title":"EgressScorecardSection","description":"A QA scorecard section with its scored items."},"EgressSummaryResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"summary":{"anyOf":[{},{"type":"null"}],"title":"Summary","description":"Structured summary; all string content scrubbed"},"summary_markdown":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary Markdown"}},"type":"object","required":["call_id","summary_markdown"],"title":"EgressSummaryResponse","description":"Scrubbed call summary (structured JSON and/or legacy markdown)."},"EgressToolCall":{"properties":{"tool_call_id":{"type":"string","title":"Tool Call Id"},"tool_name":{"type":"string","title":"Tool Name"},"status":{"type":"string","enum":["completed","cancelled"],"title":"Status"},"arguments":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Arguments"},"result":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Result"},"after_sequence":{"type":"integer","title":"After Sequence"},"tool_index":{"type":"integer","title":"Tool Index"},"started_elapsed_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Started Elapsed Seconds"},"completed_elapsed_seconds":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Completed Elapsed Seconds"}},"type":"object","required":["tool_call_id","tool_name","status","arguments","result","after_sequence","tool_index","started_elapsed_seconds","completed_elapsed_seconds"],"title":"EgressToolCall","description":"One persisted autonomous-agent tool invocation.\n\nThe source event was already deny-by-default sanitized by the voice\nruntime. Egress still allowlists the envelope and re-scrubs every string\nleaf so its stronger \"nothing leaves unscrubbed\" contract remains true."},"EgressToolCallsResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"tool_calls":{"items":{"$ref":"#/components/schemas/EgressToolCall"},"type":"array","title":"Tool Calls"}},"type":"object","required":["call_id","tool_calls"],"title":"EgressToolCallsResponse","description":"Scrubbed terminal tool calls for a call."},"EgressTrace":{"properties":{"id":{"type":"string","title":"Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"timestamp":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timestamp"},"latency":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latency"},"total_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Tokens","description":"Sum of observation token usage, when reported. Counts only the returned observations — a lower bound when the response is truncated."},"observations":{"items":{"$ref":"#/components/schemas/EgressTraceObservation"},"type":"array","title":"Observations"}},"type":"object","required":["id","name","timestamp","latency","observations"],"title":"EgressTrace","description":"Compact, scrubbed view of a Langfuse trace."},"EgressTraceObservation":{"properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"start_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"End Time"},"level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Level"},"status_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status Message"},"input":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Input","description":"Stringified and scrubbed"},"output":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output","description":"Stringified and scrubbed"}},"type":"object","required":["id","type","name","model","start_time","end_time","level","status_message"],"title":"EgressTraceObservation","description":"Compact, scrubbed view of a Langfuse observation."},"EgressTracesResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"traces":{"items":{"$ref":"#/components/schemas/EgressTrace"},"type":"array","title":"Traces"},"traces_truncated":{"type":"boolean","title":"Traces Truncated","description":"True when the call has more observations upstream than the fetch cap returned (some traces may be partial or missing)","default":false}},"type":"object","required":["call_id","traces"],"title":"EgressTracesResponse","description":"Scrubbed Langfuse traces for a call."},"EgressTranscriptChunk":{"properties":{"sequence":{"type":"integer","title":"Sequence"},"speaker":{"type":"string","title":"Speaker"},"text":{"type":"string","title":"Text"},"start_time":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"End Time"}},"type":"object","required":["sequence","speaker","text","start_time","end_time"],"title":"EgressTranscriptChunk","description":"A single transcript chunk with scrubbed text."},"EgressTranscriptResponse":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"chunks":{"items":{"$ref":"#/components/schemas/EgressTranscriptChunk"},"type":"array","title":"Chunks"}},"type":"object","required":["call_id","chunks"],"title":"EgressTranscriptResponse","description":"Scrubbed transcript for a call."},"EgressVoiceLatencyTurn":{"properties":{"turn_id":{"type":"string","title":"Turn Id"},"recorded_at":{"type":"string","format":"date-time","title":"Recorded At"},"completion_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completion Status"},"response_kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response Kind"},"response_total_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Response Total Ms"},"endpointing_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Endpointing Ms"},"turn_release_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Turn Release Ms"},"llm_ttft_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Llm Ttft Ms"},"tool_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tool Ms"},"speech_release_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Speech Release Ms"},"tts_ttfb_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tts Ttfb Ms"},"transport_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Transport Ms"},"tool_handler_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Tool Handler Ms"},"llm_thinking_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Llm Thinking Ms"},"llm_output_tokens":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Llm Output Tokens"},"llm_generation_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Llm Generation Ms"},"waited_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Waited Ms"},"barge_in_stop_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Barge In Stop Ms"}},"type":"object","required":["turn_id","recorded_at","completion_status","response_kind","response_total_ms","endpointing_ms","turn_release_ms","llm_ttft_ms","tool_ms","speech_release_ms","tts_ttfb_ms","transport_ms","tool_handler_ms","llm_thinking_ms","llm_output_tokens","llm_generation_ms","waited_ms","barge_in_stop_ms"],"title":"EgressVoiceLatencyTurn","description":"One autonomous-voice latency row: numbers and labels only, no text.\n\nThe stages are defined in ``src.agent_runtime.voice.latency``. On an\nanswered turn they sum to ``response_total_ms``; the ``opening`` row times\nthe call's first audio rather than a reply."},"ErrorModel":{"properties":{"detail":{"anyOf":[{"type":"string"},{"additionalProperties":{"type":"string"},"type":"object"}],"title":"Detail"}},"type":"object","required":["detail"],"title":"ErrorModel"},"FeedbackDimension":{"properties":{"title":{"type":"string","title":"Title","description":"Title of this dimension"},"positive_feedback":{"items":{"type":"string"},"type":"array","title":"Positive Feedback","description":"The single most important thing the agent did well in this dimension (one item; one sentence, max ~15 words)"},"improvements":{"items":{"type":"string"},"type":"array","title":"Improvements","description":"The single most impactful, actionable improvement for this dimension (one item; one sentence, max ~20 words, starting with a verb; a second only for a separate compliance-critical issue)"}},"type":"object","required":["title","positive_feedback","improvements"],"title":"FeedbackDimension","description":"Feedback for a specific dimension.\n\n`extra=\"ignore\"` allows historical rows that still carry a numeric `score`\nfield to deserialize cleanly — the value is dropped on read."},"FeedbackResponse":{"properties":{"success":{"type":"boolean","title":"Success"},"message":{"type":"string","title":"Message","description":"Status message"}},"type":"object","required":["success","message"],"title":"FeedbackResponse","description":"Response after submitting feedback."},"FeedbackType":{"type":"string","enum":["bug_report","suggestion","other"],"title":"FeedbackType","description":"Types of feedback that can be submitted."},"FilterOption":{"properties":{"label":{"type":"string","title":"Label"},"value":{"type":"string","title":"Value"}},"type":"object","required":["label","value"],"title":"FilterOption","description":"A single filter option with label and value."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HangupAiCallResponse":{"properties":{"status":{"type":"string","title":"Status"}},"type":"object","required":["status"],"title":"HangupAiCallResponse"},"HealthCheck":{"properties":{"status":{"type":"string","enum":["ok","degraded","error"],"title":"Status"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"latency_ms":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latency Ms"}},"type":"object","required":["status"],"title":"HealthCheck","description":"Individual health check result."},"HealthResponse":{"properties":{"status":{"type":"string","enum":["healthy","degraded","unhealthy"],"title":"Status"},"checks":{"additionalProperties":{"$ref":"#/components/schemas/HealthCheck"},"type":"object","title":"Checks"},"timestamp":{"type":"string","title":"Timestamp"},"version":{"type":"string","title":"Version","default":"0.0.190"}},"type":"object","required":["status","checks","timestamp"],"title":"HealthResponse","description":"Overall health response."},"IdvAnswer":{"properties":{"turn":{"type":"integer","title":"Turn"},"at":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"At"},"asked":{"items":{"type":"string"},"type":"array","title":"Asked"},"style":{"anyOf":[{"type":"string","enum":["open","readback","hint"]},{"type":"null"}],"title":"Style"},"said_on_file":{"items":{"type":"string"},"type":"array","title":"Said On File"},"split":{"type":"boolean","title":"Split"},"accepted":{"items":{"type":"string"},"type":"array","title":"Accepted"},"rejected":{"items":{"type":"string"},"type":"array","title":"Rejected"},"judged_by":{"items":{"type":"string","pattern":"^[A-Za-z0-9._:/@-]{1,128}$"},"type":"array","title":"Judged By"},"dropped":{"anyOf":[{"type":"string","enum":["timeout","unavailable","stale"]},{"type":"null"}],"title":"Dropped"}},"additionalProperties":false,"type":"object","required":["turn","at","asked","style","said_on_file","split","accepted","rejected","judged_by","dropped"],"title":"IdvAnswer","description":"One customer turn during IDV and what the matcher made of it."},"IdvOutcome":{"type":"string","enum":["verified","partial","incomplete"],"title":"IdvOutcome","description":"Identity-verification outcome for a call, denormalized from the IDV analyzer.\n\nOnly set when IDV was required and a verdict was produced. A NULL column\ncan mean IDV was not applicable, is still pending, or no verdict was\navailable; API consumers use ``idv_required`` plus call status to\ndistinguish those states.\nDerived from the terminal `identity_verification_state[\"status\"]`:\n\n- VERIFIED: status `complete` — identity confirmed per the scenario's policy.\n- PARTIAL: at least one identity factor was confirmed, but the scenario's\n  completion rule was never satisfied.\n- INCOMPLETE: required, and not a single factor was confirmed.\n\nPARTIAL exists because \"not verified\" covers two operationally different\ncalls: one where the customer engaged with verification and it ran out of\nroad, and one where it never started. Only the second is a candidate for\n\"the agent didn't try\". Note this is *tracking* state, not an adherence\ngrade — the leadership IDV rate deliberately reads the reviewed QA\nscorecard instead (see `shared.idv`), because a human reviewer can correct\nit and the analyzer cannot.\n\nThere is deliberately no `skipped` outcome. The live state machine still has\na `skipped` terminal so the analyzer stops firing on a call that is not going\nto verify, but as a *result* it said nothing true that `incomplete` doesn't:\nverification was required and did not happen. It also read as a third,\nambiguous colour on any report — neither pass nor fail — while the thing a\nreviewer actually needs to know (was skipping appropriate here?) is a\ntranscript judgement the tracker never made."},"IdvRecord":{"properties":{"version":{"type":"integer","const":1,"title":"Version","default":1},"rule":{"items":{"$ref":"#/components/schemas/IdvRuleGroup"},"type":"array","title":"Rule"},"on_file":{"additionalProperties":{"type":"boolean"},"type":"object","title":"On File"},"path":{"type":"string","enum":["not_required","never_started","first_try_pass","pass_after_retry","fail_exhausted","hung_up_during_idv","fail_ended"],"title":"Path"},"seconds_to_verify":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Seconds To Verify"},"keyterms_from_turn":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Keyterms From Turn"},"answers":{"items":{"$ref":"#/components/schemas/IdvAnswer"},"type":"array","title":"Answers"}},"additionalProperties":false,"type":"object","required":["rule","on_file","path","seconds_to_verify","keyterms_from_turn","answers"],"title":"IdvRecord"},"IdvRuleGroup":{"properties":{"fields":{"items":{"type":"string"},"type":"array","title":"Fields"},"min":{"type":"integer","title":"Min"}},"additionalProperties":false,"type":"object","required":["fields","min"],"title":"IdvRuleGroup","description":"``min`` of ``fields`` must be verified (the scenario's completion rule)."},"IdvSource":{"type":"string","enum":["live","post_call","inherited"],"title":"IdvSource","description":"Which mechanism produced the call's persisted IDV state.\n\n- LIVE: the in-call IDV analyzer's terminal state (the normal path).\n- POST_CALL: the post-call IDV judge — runs when the live analyzer never\n  produced a state (e.g. no scenario reached the session) or the scenario\n  was reclassified after the call, judging the full transcript against the\n  resolved scenario's IDV rules.\n- INHERITED: the origin leg of a transfer verified the customer, and this\n  recipient leg inherits that verdict — verification travels with the\n  conversation, not the leg (see calls.idv_resolution). The verification\n  exchange is on the origin leg's transcript, not this one's."},"InboundRouteCreate":{"properties":{"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name"},"scenario":{"type":"string","maxLength":100,"minLength":1,"title":"Scenario","description":"ai_agent scenario with scenario_metadata.supports_inbound"},"user_id":{"type":"string","format":"uuid","title":"User Id","description":"Owning service user for session ownership/attribution"},"voice_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Voice Id"},"opening_line":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Opening Line","description":"Overrides the scenario's inbound_greeting; raw $placeholder template, rendered per call."},"human_destination":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Human Destination","description":"Transfer target for this route; empty = offer callback instead"},"fallback_destination":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Fallback Destination","description":"Queue/voicemail destination (TCN: human hunt group SID) for auto-answered calls the autonomous agent cannot take, and for callers it cannot continue with (unknown caller, model failure, failed identity check)"},"hours_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hours Start","description":"'HH:MM' local time"},"hours_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hours End","description":"'HH:MM' local time"},"hours_days":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Hours Days","description":"date.weekday() ints (0=Mon); null = every day"},"hours_timezone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Hours Timezone"},"transfer_hours_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Hours Start","description":"'HH:MM' local time; null with end = the team's business hours"},"transfer_hours_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Hours End","description":"'HH:MM' local time; null with start = the team's business hours"},"transfer_hours_days":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Transfer Hours Days","description":"Live-transfer date.weekday() ints (0=Mon); null = every day"},"transfer_hours_timezone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Transfer Hours Timezone"},"transfer_hours_exclude_public_holidays":{"type":"boolean","title":"Transfer Hours Exclude Public Holidays","description":"Close live transfers on Australian national public holidays","default":false},"unknown_caller_policy":{"$ref":"#/components/schemas/UnknownCallerPolicy","default":"proceed"},"max_concurrent":{"anyOf":[{"type":"integer","maximum":64.0,"minimum":1.0},{"type":"null"}],"title":"Max Concurrent"},"provider":{"type":"string","maxLength":32,"minLength":1,"title":"Provider"},"provider_ref":{"type":"string","maxLength":120,"minLength":1,"title":"Provider Ref","description":"Provider-native leg ref: 3CX Route Point DN / E.164 number"},"enabled":{"type":"boolean","title":"Enabled","default":false}},"type":"object","required":["display_name","scenario","user_id","provider","provider_ref"],"title":"InboundRouteCreate"},"InboundRouteRead":{"properties":{"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name"},"scenario":{"type":"string","maxLength":100,"minLength":1,"title":"Scenario","description":"ai_agent scenario with scenario_metadata.supports_inbound"},"user_id":{"type":"string","format":"uuid","title":"User Id","description":"Owning service user for session ownership/attribution"},"voice_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Voice Id"},"opening_line":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Opening Line","description":"Overrides the scenario's inbound_greeting; raw $placeholder template, rendered per call."},"human_destination":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Human Destination","description":"Transfer target for this route; empty = offer callback instead"},"fallback_destination":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Fallback Destination","description":"Queue/voicemail destination (TCN: human hunt group SID) for auto-answered calls the autonomous agent cannot take, and for callers it cannot continue with (unknown caller, model failure, failed identity check)"},"hours_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hours Start","description":"'HH:MM' local time"},"hours_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hours End","description":"'HH:MM' local time"},"hours_days":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Hours Days","description":"date.weekday() ints (0=Mon); null = every day"},"hours_timezone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Hours Timezone"},"transfer_hours_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Hours Start","description":"'HH:MM' local time; null with end = the team's business hours"},"transfer_hours_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Hours End","description":"'HH:MM' local time; null with start = the team's business hours"},"transfer_hours_days":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Transfer Hours Days","description":"Live-transfer date.weekday() ints (0=Mon); null = every day"},"transfer_hours_timezone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Transfer Hours Timezone"},"transfer_hours_exclude_public_holidays":{"type":"boolean","title":"Transfer Hours Exclude Public Holidays","description":"Close live transfers on Australian national public holidays","default":false},"unknown_caller_policy":{"$ref":"#/components/schemas/UnknownCallerPolicy","default":"proceed"},"max_concurrent":{"anyOf":[{"type":"integer","maximum":64.0,"minimum":1.0},{"type":"null"}],"title":"Max Concurrent"},"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"provider_ref":{"type":"string","title":"Provider Ref"},"enabled":{"type":"boolean","title":"Enabled"},"configuration_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Configuration Error"},"required_provider_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Required Provider Ref"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["display_name","scenario","user_id","id","provider","provider_ref","enabled","created_at","updated_at"],"title":"InboundRouteRead"},"InboundRouteUpdate":{"properties":{"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name"},"scenario":{"type":"string","maxLength":100,"minLength":1,"title":"Scenario","description":"ai_agent scenario with scenario_metadata.supports_inbound"},"user_id":{"type":"string","format":"uuid","title":"User Id","description":"Owning service user for session ownership/attribution"},"voice_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Voice Id"},"opening_line":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Opening Line","description":"Overrides the scenario's inbound_greeting; raw $placeholder template, rendered per call."},"human_destination":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Human Destination","description":"Transfer target for this route; empty = offer callback instead"},"fallback_destination":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Fallback Destination","description":"Queue/voicemail destination (TCN: human hunt group SID) for auto-answered calls the autonomous agent cannot take, and for callers it cannot continue with (unknown caller, model failure, failed identity check)"},"hours_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hours Start","description":"'HH:MM' local time"},"hours_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hours End","description":"'HH:MM' local time"},"hours_days":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Hours Days","description":"date.weekday() ints (0=Mon); null = every day"},"hours_timezone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Hours Timezone"},"transfer_hours_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Hours Start","description":"'HH:MM' local time; null with end = the team's business hours"},"transfer_hours_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Transfer Hours End","description":"'HH:MM' local time; null with start = the team's business hours"},"transfer_hours_days":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Transfer Hours Days","description":"Live-transfer date.weekday() ints (0=Mon); null = every day"},"transfer_hours_timezone":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Transfer Hours Timezone"},"transfer_hours_exclude_public_holidays":{"type":"boolean","title":"Transfer Hours Exclude Public Holidays","description":"Close live transfers on Australian national public holidays","default":false},"unknown_caller_policy":{"$ref":"#/components/schemas/UnknownCallerPolicy","default":"proceed"},"max_concurrent":{"anyOf":[{"type":"integer","maximum":64.0,"minimum":1.0},{"type":"null"}],"title":"Max Concurrent"},"provider_ref":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Provider Ref","description":"Unified 3CX Route Point DN; editable to repair legacy routes. Omitted by pre-unification clients to keep the current DN."},"enabled":{"type":"boolean","title":"Enabled","default":false}},"type":"object","required":["display_name","scenario","user_id"],"title":"InboundRouteUpdate"},"JointPartyRead":{"properties":{"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"relationship":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Relationship"}},"type":"object","title":"JointPartyRead","description":"Wire shape for an additional party on an account.\n\nMirrors `src.crm.base.JointParty`. Kept here as a Pydantic model rather\nthan reusing the dataclass directly so the API boundary stays validated\nand OpenAPI-discoverable for the generated frontend client."},"LatencyLegSummary":{"properties":{"p50_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"P50 Ms"},"p95_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"P95 Ms"},"worst_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Worst Ms"},"n":{"type":"integer","title":"N"}},"type":"object","required":["p50_ms","p95_ms","worst_ms","n"],"title":"LatencyLegSummary","description":"Percentiles for one latency leg and its contributing sample count."},"LatencyPercentiles":{"properties":{"p50_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"P50 Ms"},"p95_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"P95 Ms"},"worst_ms":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Worst Ms"},"n":{"type":"integer","title":"N","description":"Number of non-null measurements in the distribution"}},"type":"object","required":["p50_ms","p95_ms","worst_ms","n"],"title":"LatencyPercentiles","description":"Distribution summary for one latency anchor."},"LedgerEntryRead":{"properties":{"occurred_on":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Occurred On"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Amount"},"balance_after":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance After"},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind"}},"type":"object","title":"LedgerEntryRead","description":"Wire shape for a financial ledger line. Mirrors `src.crm.base.LedgerEntry`."},"MarkSummaryCopiedResponse":{"properties":{"session_id":{"type":"string","title":"Session Id","description":"Session ID"},"summary_copied_at":{"type":"string","format":"date-time","title":"Summary Copied At","description":"When the summary was first copied. Idempotent: stays at the first copy time even if the agent copies again."}},"type":"object","required":["session_id","summary_copied_at"],"title":"MarkSummaryCopiedResponse","description":"Response confirming a call's summary has been marked as copied."},"NarrativeActionOut":{"properties":{"title":{"type":"string","title":"Title"},"text":{"type":"string","title":"Text"},"drill_type":{"type":"string","enum":["agent","calls","call","none"],"title":"Drill Type","default":"none"},"drill_params":{"additionalProperties":{"type":"string"},"type":"object","title":"Drill Params","default":{}}},"type":"object","required":["title","text"],"title":"NarrativeActionOut","description":"One 'do today' item — an imperative move with a derived drill link."},"NarrativeCalloutOut":{"properties":{"kind":{"type":"string","enum":["risk","strength","watch","portfolio"],"title":"Kind"},"title":{"type":"string","title":"Title"},"text":{"type":"string","title":"Text"},"drill_type":{"type":"string","enum":["agent","calls","call","none"],"title":"Drill Type","default":"none"},"drill_params":{"additionalProperties":{"type":"string"},"type":"object","title":"Drill Params","default":{}}},"type":"object","required":["kind","title","text"],"title":"NarrativeCalloutOut"},"NarrativeOut":{"properties":{"status":{"type":"string","enum":["pending","generating","ready","fallback","failed"],"title":"Status"},"state_of_play":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State Of Play"},"working":{"items":{"type":"string"},"type":"array","title":"Working","default":[]},"actions":{"items":{"$ref":"#/components/schemas/NarrativeActionOut"},"type":"array","title":"Actions","default":[]},"watch":{"items":{"type":"string"},"type":"array","title":"Watch","default":[]},"quiet":{"type":"boolean","title":"Quiet","default":false},"headline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Headline"},"body":{"items":{"type":"string"},"type":"array","title":"Body","default":[]},"callouts":{"items":{"$ref":"#/components/schemas/NarrativeCalloutOut"},"type":"array","title":"Callouts","default":[]},"generated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Generated At"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model"},"stale":{"type":"boolean","title":"Stale","default":false}},"type":"object","required":["status"],"title":"NarrativeOut","description":"Briefing in a fixed skeleton (state of play → working → actions →\nwatch) so the card reads as a huddle brief, not a verdict. The legacy\nheadline/body/callouts fields carry pre-skeleton stored rows while they\nare served stale during regeneration; new rows never populate them."},"OrganizationSettingsRead":{"properties":{"client_classification_enabled":{"type":"boolean","title":"Client Classification Enabled"},"team_timezone":{"type":"string","title":"Team Timezone"},"business_hours_start":{"type":"string","title":"Business Hours Start"},"business_hours_end":{"type":"string","title":"Business Hours End"},"business_hours_days":{"items":{"type":"integer"},"type":"array","title":"Business Hours Days"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"updated_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Updated By User Id"}},"type":"object","required":["client_classification_enabled","team_timezone","business_hours_start","business_hours_end","business_hours_days","updated_at","updated_by_user_id"],"title":"OrganizationSettingsRead"},"OrganizationSettingsUpdate":{"properties":{"client_classification_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Client Classification Enabled"},"team_timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Team Timezone"},"business_hours_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Hours Start"},"business_hours_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Hours End"},"business_hours_days":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Business Hours Days"}},"additionalProperties":false,"type":"object","title":"OrganizationSettingsUpdate"},"OverviewResponse":{"properties":{"period":{"$ref":"#/components/schemas/PeriodInfo"},"view":{"type":"string","enum":["daily","weekly"],"title":"View"},"volume":{"$ref":"#/components/schemas/VolumeLine"},"tiles":{"items":{"$ref":"#/components/schemas/Tile"},"type":"array","title":"Tiles"},"portfolio":{"items":{"$ref":"#/components/schemas/PortfolioRow"},"type":"array","title":"Portfolio"},"tag_rates":{"items":{"$ref":"#/components/schemas/TagRate"},"type":"array","title":"Tag Rates"},"narrative":{"$ref":"#/components/schemas/NarrativeOut"},"queue":{"items":{"$ref":"#/components/schemas/QueueItem"},"type":"array","title":"Queue"},"agents":{"items":{"$ref":"#/components/schemas/AgentRow"},"type":"array","title":"Agents"}},"type":"object","required":["period","view","volume","tiles","portfolio","tag_rates","narrative","queue","agents"],"title":"OverviewResponse"},"Page_AccountSearchRead_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AccountSearchRead"},"type":"array","title":"Items"},"total":{"type":"integer","minimum":0.0,"title":"Total"},"page":{"type":"integer","minimum":1.0,"title":"Page"},"size":{"type":"integer","minimum":1.0,"title":"Size"},"pages":{"type":"integer","minimum":0.0,"title":"Pages"}},"type":"object","required":["items","total","page","size","pages"],"title":"Page[AccountSearchRead]"},"Page_AdminUserResponse_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/AdminUserResponse"},"type":"array","title":"Items"},"total":{"type":"integer","minimum":0.0,"title":"Total"},"page":{"type":"integer","minimum":1.0,"title":"Page"},"size":{"type":"integer","minimum":1.0,"title":"Size"},"pages":{"type":"integer","minimum":0.0,"title":"Pages"}},"type":"object","required":["items","total","page","size","pages"],"title":"Page[AdminUserResponse]"},"Page_CallListItem_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CallListItem"},"type":"array","title":"Items"},"total":{"type":"integer","minimum":0.0,"title":"Total"},"page":{"type":"integer","minimum":1.0,"title":"Page"},"size":{"type":"integer","minimum":1.0,"title":"Size"},"pages":{"type":"integer","minimum":0.0,"title":"Pages"}},"type":"object","required":["items","total","page","size","pages"],"title":"Page[CallListItem]"},"Page_CampaignAccountRead_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CampaignAccountRead"},"type":"array","title":"Items"},"total":{"type":"integer","minimum":0.0,"title":"Total"},"page":{"type":"integer","minimum":1.0,"title":"Page"},"size":{"type":"integer","minimum":1.0,"title":"Size"},"pages":{"type":"integer","minimum":0.0,"title":"Pages"}},"type":"object","required":["items","total","page","size","pages"],"title":"Page[CampaignAccountRead]"},"Page_ReviewQueueItem_":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ReviewQueueItem"},"type":"array","title":"Items"},"total":{"type":"integer","minimum":0.0,"title":"Total"},"page":{"type":"integer","minimum":1.0,"title":"Page"},"size":{"type":"integer","minimum":1.0,"title":"Size"},"pages":{"type":"integer","minimum":0.0,"title":"Pages"}},"type":"object","required":["items","total","page","size","pages"],"title":"Page[ReviewQueueItem]"},"PaymentFrequency":{"type":"string","enum":["one_off","weekly","fortnightly","monthly"],"title":"PaymentFrequency","description":"Cadence of a scheduled commitment."},"PaymentIntegrationConfig":{"properties":{"provider":{"type":"string","const":"glider","title":"Provider","default":"glider"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"}},"type":"object","title":"PaymentIntegrationConfig"},"PaymentIntegrationResponse":{"properties":{"provider":{"type":"string","const":"glider","title":"Provider","default":"glider"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"},"id":{"type":"string","format":"uuid","title":"Id"}},"type":"object","required":["id"],"title":"PaymentIntegrationResponse"},"PaymentIntegrationStatus":{"properties":{"provider":{"type":"string","const":"glider","title":"Provider","default":"glider"},"credentials_configured":{"type":"boolean","title":"Credentials Configured"},"enabled":{"type":"boolean","title":"Enabled"},"active":{"type":"boolean","title":"Active"},"base_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Base Url"}},"type":"object","required":["credentials_configured","enabled","active"],"title":"PaymentIntegrationStatus"},"PaymentPortalIntegrationConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"}},"type":"object","title":"PaymentPortalIntegrationConfig","description":"The payment-portal integration's stored configuration."},"PaymentPortalIntegrationResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"},"id":{"type":"string","format":"uuid","title":"Id"}},"type":"object","required":["id"],"title":"PaymentPortalIntegrationResponse"},"PaymentPortalIntegrationStatus":{"properties":{"available":{"type":"boolean","title":"Available"},"credentials_configured":{"type":"boolean","title":"Credentials Configured"},"enabled":{"type":"boolean","title":"Enabled"},"active":{"type":"boolean","title":"Active"},"api_base_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Base Url"},"auth_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Auth Url"},"audience":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audience"},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"}},"type":"object","required":["available","credentials_configured","enabled","active"],"title":"PaymentPortalIntegrationStatus"},"PaymentPortalTestConnectionResponse":{"properties":{"message":{"type":"string","title":"Message"}},"type":"object","required":["message"],"title":"PaymentPortalTestConnectionResponse"},"PaymentTestConnectionResponse":{"properties":{"provider":{"type":"string","const":"glider","title":"Provider"},"message":{"type":"string","title":"Message"}},"type":"object","required":["provider","message"],"title":"PaymentTestConnectionResponse"},"PerformanceFilters":{"properties":{"date_from":{"type":"string","format":"date-time","title":"Date From"},"date_to":{"type":"string","format":"date-time","title":"Date To"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"agent_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Id"},"status":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Status"},"call_direction":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Call Direction"},"call_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Call Mode"},"filter_user_id":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Filter User Id"},"qa_score_bucket":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Qa Score Bucket"},"tag_key":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tag Key"},"client":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Client"},"campaign_id":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Campaign Id"},"crm_linked":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Crm Linked"},"range_days":{"type":"integer","title":"Range Days"}},"type":"object","required":["date_from","date_to","range_days"],"title":"PerformanceFilters","description":"Echo back applied filters to the client."},"PerformanceMetric":{"properties":{"key":{"type":"string","const":"qa_score","title":"Key","default":"qa_score"},"label":{"type":"string","title":"Label","default":"QA Score"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value","description":"Average QA score for the period"},"target":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Target","description":"Target benchmark for the metric"},"delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta","description":"Difference vs previous period (points)"},"trend_positive":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Trend Positive","description":"Whether the change vs previous period is positive"}},"type":"object","title":"PerformanceMetric","description":"Aggregate metric displayed in the summary cards."},"PerformanceSummaryResponse":{"properties":{"metrics":{"items":{"$ref":"#/components/schemas/PerformanceMetric"},"type":"array","title":"Metrics"},"trends":{"items":{"$ref":"#/components/schemas/TrendPoint"},"type":"array","title":"Trends"},"call_time_trends":{"items":{"$ref":"#/components/schemas/CallTimeTrendPoint"},"type":"array","title":"Call Time Trends","default":[]},"connected_duration":{"$ref":"#/components/schemas/ConnectedDurationMetrics"},"autonomous_voice_latency":{"anyOf":[{"$ref":"#/components/schemas/AutonomousVoiceLatencyAggregate"},{"type":"null"}]},"leaderboard":{"items":{"$ref":"#/components/schemas/AgentPerformance"},"type":"array","title":"Leaderboard"},"alerts":{"$ref":"#/components/schemas/ComplianceAlert"},"total_calls":{"type":"integer","title":"Total Calls"},"call_statistics":{"$ref":"#/components/schemas/CallStatistics"},"filters":{"$ref":"#/components/schemas/PerformanceFilters"}},"type":"object","required":["metrics","trends","connected_duration","leaderboard","alerts","total_calls","call_statistics","filters"],"title":"PerformanceSummaryResponse","description":"Full payload consumed by the frontend performance dashboard."},"PeriodInfo":{"properties":{"type":{"type":"string","enum":["day","wtd","week","month"],"title":"Type"},"start":{"type":"string","format":"date-time","title":"Start"},"end":{"type":"string","format":"date-time","title":"End"},"label":{"type":"string","title":"Label"},"prior_label":{"type":"string","title":"Prior Label"},"baseline_hint":{"type":"string","title":"Baseline Hint","default":""},"prev":{"anyOf":[{"$ref":"#/components/schemas/PeriodNavTarget"},{"type":"null"}]},"next":{"anyOf":[{"$ref":"#/components/schemas/PeriodNavTarget"},{"type":"null"}]}},"type":"object","required":["type","start","end","label","prior_label"],"title":"PeriodInfo"},"PeriodNavTarget":{"properties":{"period_type":{"type":"string","enum":["day","wtd","week","month"],"title":"Period Type"},"anchor":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Anchor"}},"type":"object","required":["period_type"],"title":"PeriodNavTarget","description":"One pager arrow: the (period_type, anchor) the frontend navigates to.\nComputed server-side (periods.period_nav) so business-day and month\narithmetic never gets re-derived in the browser. `anchor=None` is the\nfamily's canonical current view (anchor-less URL)."},"PlaceAiCallRequest":{"properties":{"telephony_provider":{"anyOf":[{"type":"string","enum":["threecx","tcn","twilio"]},{"type":"null"}],"title":"Telephony Provider"},"phone_number":{"type":"string","maxLength":32,"minLength":4,"title":"Phone Number","description":"E.164 phone number to dial, e.g. +14155551212"},"scenario":{"type":"string","maxLength":100,"minLength":1,"title":"Scenario","description":"Scenario name with mode='ai_agent' (its scenario_metadata.voice_agent_config defines the persona)."},"crm_account_id":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Crm Account Id","description":"Optional CRM account id to dial against. When CRM integration is enabled the account is resolved and mapped into the voice agent's context (unless an explicit demo_context is given), and the call session is auto-linked to it on placement."},"demo_context":{"anyOf":[{"$ref":"#/components/schemas/AiCallDemoContext"},{"type":"null"}],"description":"Optional account context substituted into the voice agent's prompt; omitted fields use the built-in demo account. Takes precedence over crm_account_id-derived context when both are given."},"override_compliance":{"type":"boolean","title":"Override Compliance","description":"Admin escape hatch: skip the outbound compliance gate (do-not-call, suppression, contact windows, frequency caps) for this manual dial. The override is logged with the acting user.","default":false},"voice_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Voice Id","description":"Provider-qualified TTS voice for THIS call only, overriding the scenario's configured voice. Lets a voice be tried back-to-back without re-configuring the scenario (which would change it for every call in flight). The voice actually used is recorded on the call as tts_voice_id either way."},"cartesia_voice_id":{"anyOf":[{"type":"string","maxLength":64},{"type":"null"}],"title":"Cartesia Voice Id","description":"Deprecated compatibility alias for voice_id.","deprecated":true}},"type":"object","required":["phone_number","scenario"],"title":"PlaceAiCallRequest","description":"Payload to place an outbound AI-collector call."},"PlaceAiCallResponse":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id","description":"CallSession id; use as :session_id in /sessions/{id}/stream to subscribe to live events."},"conversation_id":{"type":"string","title":"Conversation Id","description":"The call's correlation handle — also stored in CallSession.agent_id."}},"type":"object","required":["session_id","conversation_id"],"title":"PlaceAiCallResponse","description":"Response after the outbound call has been dispatched to the voice runtime."},"PortfolioRow":{"properties":{"client":{"type":"string","title":"Client"},"engaged_calls":{"type":"integer","title":"Engaged Calls"},"dispute_rate":{"type":"number","title":"Dispute Rate"},"dispute_delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Dispute Delta"},"hardship_rate":{"type":"number","title":"Hardship Rate"},"commitment_rate":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Commitment Rate"}},"type":"object","required":["client","engaged_calls","dispute_rate","hardship_rate"],"title":"PortfolioRow"},"PossibleAccountMatchRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"external_id":{"type":"string","title":"External Id"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"display_name":{"type":"string","title":"Display Name"},"account_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Status"},"account_callable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Account Callable"},"account_synced_at":{"type":"string","format":"date-time","title":"Account Synced At"},"collection_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collection Stage"},"arranged_or_paid":{"type":"boolean","title":"Arranged Or Paid"},"balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance"},"removed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Removed At"},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id"},"campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Name"},"membership_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Membership Status"},"matched_on":{"items":{"type":"string","enum":["phone","address"]},"type":"array","title":"Matched On"}},"type":"object","required":["id","external_id","display_name","account_synced_at","arranged_or_paid","matched_on"],"title":"PossibleAccountMatchRead","description":"An account that shares a phone number or the address, but not the\ncustomer: often someone else in the same household."},"PreviousEngagedCall":{"properties":{"call_id":{"type":"string","format":"uuid","title":"Call Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"call_direction":{"anyOf":[{"$ref":"#/components/schemas/CallDirection"},{"type":"null"}]},"call_mode":{"$ref":"#/components/schemas/CallMode"},"conversation_outcome":{"$ref":"#/components/schemas/ConversationOutcome"},"commitment_shape":{"anyOf":[{"$ref":"#/components/schemas/CommitmentShape"},{"type":"null"}]},"summary_markdown":{"type":"string","title":"Summary Markdown"},"can_view_detail":{"type":"boolean","title":"Can View Detail","description":"Whether the requester may open /calls/{call_id}. The summary is deliberately shared across agents; the full call detail stays owner-or-admin, so the UI must gate its deep link on this."}},"type":"object","required":["call_id","started_at","call_mode","conversation_outcome","summary_markdown","can_view_detail"],"title":"PreviousEngagedCall","description":"The most recent relevant prior conversation with a phone number.\n\nThe public name is retained for API compatibility; eligible outcomes also\ninclude refused, wrong-person, callback-requested, and escalated calls."},"PreviousEngagedCallResponse":{"properties":{"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone","description":"Canonical E.164 the lookup ran on; null when the anchor session has no normalizable customer number (withheld/unknown)."},"pending":{"type":"boolean","title":"Pending","description":"A newer prior call to this number is still finalizing — the client should refetch briefly (bounded), the answer may improve.","default":false},"call":{"anyOf":[{"$ref":"#/components/schemas/PreviousEngagedCall"},{"type":"null"}]},"recent_call_count":{"type":"integer","title":"Recent Call Count","description":"Prior conversations (transfer legs collapsed) with this number in the recent window before this call, any outcome.","default":0}},"type":"object","title":"PreviousEngagedCallResponse","description":"Previous-contact lookup for a live session (always 200; empty is normal)."},"PromptConfigInput":{"properties":{"dimensions":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/PromptDimensionInput"},"type":"object"},{"type":"null"}],"title":"Dimensions","description":"Coaching dimensions (only for coaching prompts)"}},"type":"object","title":"PromptConfigInput","description":"Type-specific configuration for prompts.\n\nFor coaching prompts, includes dimension definitions.\nCan be extended for other prompt types as needed."},"PromptCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name","description":"Unique prompt name"},"type":{"type":"string","title":"Type","description":"Prompt type: coaching, summary, action_cards, suggested_responses, or tagging"},"content":{"type":"string","minLength":1,"title":"Content","description":"Prompt content/text"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description","description":"Optional description"},"config":{"anyOf":[{"$ref":"#/components/schemas/PromptConfigInput"},{"type":"null"}],"description":"Type-specific configuration (e.g., coaching dimensions)"}},"type":"object","required":["name","type","content"],"title":"PromptCreate","description":"Input schema for creating a new prompt."},"PromptDimensionInput":{"properties":{"title":{"type":"string","minLength":1,"title":"Title","description":"Dimension title"},"scoring_criteria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scoring Criteria","description":"Scoring criteria for this dimension"}},"type":"object","required":["title"],"title":"PromptDimensionInput","description":"Input schema for a single coaching dimension."},"PromptResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"type":{"type":"string","title":"Type"},"content":{"type":"string","title":"Content"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Config","description":"Type-specific configuration"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","type","content","description","created_at","updated_at"],"title":"PromptResponse","description":"Response data for a prompt."},"PromptUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type"},"content":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Content"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"config":{"anyOf":[{"$ref":"#/components/schemas/PromptConfigInput"},{"type":"null"}],"description":"Type-specific configuration (e.g., coaching dimensions)"}},"type":"object","title":"PromptUpdate","description":"Input schema for updating an existing prompt."},"ProviderRecordingUrlResponse":{"properties":{"provider":{"type":"string","title":"Provider","description":"Telephony provider hosting the recording"},"url":{"type":"string","title":"Url","description":"Short-lived download/playback URL"},"filename":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Filename","description":"Provider-side recording file name"}},"type":"object","required":["provider","url"],"title":"ProviderRecordingUrlResponse","description":"Short-lived link to a recording hosted by the telephony provider.\n\nMinted per request from CallSession.provider_call_ref — TCN's signed\nURLs expire after ~10 minutes, so clients must fetch this on demand\nand never persist the URL."},"PublicAppConfig":{"properties":{"features":{"$ref":"#/components/schemas/PublicFeatureFlags"},"market":{"$ref":"#/components/schemas/PublicMarketConfig"},"callback_hours":{"$ref":"#/components/schemas/PublicCallbackHours"}},"type":"object","required":["features","market","callback_hours"],"title":"PublicAppConfig","description":"Frontend-safe application configuration."},"PublicCallbackHours":{"properties":{"start":{"type":"string","title":"Start"},"end":{"type":"string","title":"End"},"days":{"items":{"type":"integer"},"type":"array","title":"Days"}},"type":"object","required":["start","end","days"],"title":"PublicCallbackHours","description":"When the team returns callbacks, in ``market.display_timezone``."},"PublicFeatureFlags":{"properties":{"chat_enabled":{"type":"boolean","title":"Chat Enabled"},"crm_enabled":{"type":"boolean","title":"Crm Enabled"},"ai_calls_enabled":{"type":"boolean","title":"Ai Calls Enabled"},"accounts_enabled":{"type":"boolean","title":"Accounts Enabled"},"campaigns_enabled":{"type":"boolean","title":"Campaigns Enabled"},"inbound_calls_enabled":{"type":"boolean","title":"Inbound Calls Enabled"},"qa_insights_enabled":{"type":"boolean","title":"Qa Insights Enabled"},"client_classification_enabled":{"type":"boolean","title":"Client Classification Enabled"},"wisr_payment_calculator_enabled":{"type":"boolean","title":"Wisr Payment Calculator Enabled"}},"type":"object","required":["chat_enabled","crm_enabled","ai_calls_enabled","accounts_enabled","campaigns_enabled","inbound_calls_enabled","qa_insights_enabled","client_classification_enabled","wisr_payment_calculator_enabled"],"title":"PublicFeatureFlags","description":"Frontend-safe feature flags."},"PublicMarketConfig":{"properties":{"market":{"type":"string","enum":["au","us"],"title":"Market"},"country":{"type":"string","title":"Country"},"locale":{"type":"string","title":"Locale"},"currency":{"type":"string","title":"Currency"},"display_timezone":{"type":"string","title":"Display Timezone"},"timezones":{"items":{"$ref":"#/components/schemas/PublicTimezoneOption"},"type":"array","title":"Timezones"},"locality_label":{"type":"string","title":"Locality Label"},"postal_code_label":{"type":"string","title":"Postal Code Label"},"region_label":{"type":"string","title":"Region Label"},"identity_ssn":{"type":"boolean","title":"Identity Ssn"}},"type":"object","required":["market","country","locale","currency","display_timezone","timezones","locality_label","postal_code_label","region_label","identity_ssn"],"title":"PublicMarketConfig","description":"What the frontend localises by: the deployment's MARKET profile."},"PublicTimezoneOption":{"properties":{"value":{"type":"string","title":"Value"},"label":{"type":"string","title":"Label"}},"type":"object","required":["value","label"],"title":"PublicTimezoneOption"},"PurgeResult":{"properties":{"deleted_count":{"type":"integer","title":"Deleted Count"},"cutoff_at":{"type":"string","format":"date-time","title":"Cutoff At"}},"type":"object","required":["deleted_count","cutoff_at"],"title":"PurgeResult"},"QaScorecard":{"properties":{"template_key":{"type":"string","title":"Template Key"},"display_name":{"type":"string","title":"Display Name"},"generated_at":{"type":"string","format":"date-time","title":"Generated At"},"status":{"type":"string","enum":["draft","reviewed"],"title":"Status","default":"draft"},"reviewed_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Reviewed By User Id"},"reviewed_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reviewed By Name"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Reviewed At"},"sections":{"items":{"$ref":"#/components/schemas/QaScorecardSection"},"type":"array","title":"Sections"},"overall_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Overall Score"},"total_max_score":{"type":"integer","title":"Total Max Score"},"pass_fail_status":{"anyOf":[{"type":"string","enum":["pass","fail","not_applicable"]},{"type":"null"}],"title":"Pass Fail Status"},"auto_fail":{"type":"boolean","title":"Auto Fail","description":"True when any auto_fail-flagged item resolved to 'not_met'.","default":false},"auto_fail_reasons":{"items":{"type":"string"},"type":"array","title":"Auto Fail Reasons","description":"Titles of items that triggered the auto-fail."},"commentary":{"type":"string","title":"Commentary"}},"type":"object","required":["template_key","display_name","generated_at","sections","total_max_score","commentary"],"title":"QaScorecard","description":"Persisted QA scorecard artifact."},"QaScorecardEditRequest":{"properties":{"items":{"items":{"$ref":"#/components/schemas/QaScorecardItemEdit"},"type":"array","title":"Items"},"commentary":{"anyOf":[{"type":"string","maxLength":2000,"minLength":1},{"type":"null"}],"title":"Commentary"}},"type":"object","title":"QaScorecardEditRequest","description":"Manual QA reviewer edits to apply to an existing scorecard."},"QaScorecardItem":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"score_type":{"type":"string","enum":["pass_fail","numeric"],"title":"Score Type"},"result":{"type":"string","enum":["met","not_met","not_applicable"],"title":"Result"},"score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score"},"max_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Score"},"comment":{"type":"string","title":"Comment"},"evidence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Evidence"},"score_excluded":{"type":"boolean","title":"Score Excluded","description":"True when this item was intentionally excluded from score calculation because the model failed to return an assessment.","default":false},"manual_review":{"type":"boolean","title":"Manual Review","description":"True when this item is excluded from the computed score because it needs human review or system access beyond the transcript.","default":false}},"type":"object","required":["key","title","score_type","result","comment"],"title":"QaScorecardItem","description":"Persisted scorecard item with template metadata and normalized scores."},"QaScorecardItemEdit":{"properties":{"section_key":{"type":"string","title":"Section Key"},"item_key":{"type":"string","title":"Item Key"},"result":{"anyOf":[{"type":"string","enum":["met","not_met","not_applicable"]},{"type":"null"}],"title":"Result"},"score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Score"},"comment":{"anyOf":[{"type":"string","maxLength":400,"minLength":1},{"type":"null"}],"title":"Comment"},"evidence":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}],"title":"Evidence"}},"type":"object","required":["section_key","item_key"],"title":"QaScorecardItemEdit","description":"Partial manual edit for one persisted scorecard item."},"QaScorecardResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"status":{"type":"string","enum":["ready","pending","not_applicable","disabled"],"title":"Status"},"scorecard":{"anyOf":[{"$ref":"#/components/schemas/QaScorecard"},{"type":"null"}]},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["enabled","status"],"title":"QaScorecardResponse","description":"API response for QA scorecard reads/generation."},"QaScorecardSection":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"items":{"items":{"$ref":"#/components/schemas/QaScorecardItem"},"type":"array","title":"Items"},"subtotal":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subtotal"},"subtotal_max_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Subtotal Max Score"}},"type":"object","required":["key","title","items"],"title":"QaScorecardSection","description":"Persisted scorecard section."},"QaScorecardTemplateOption":{"properties":{"key":{"type":"string","title":"Key"},"display_name":{"type":"string","title":"Display Name"},"total_max_score":{"type":"integer","title":"Total Max Score"}},"type":"object","required":["key","display_name","total_max_score"],"title":"QaScorecardTemplateOption","description":"One available template entry returned by GET /qa-scorecard/templates."},"QaScorecardTemplatesResponse":{"properties":{"templates":{"items":{"$ref":"#/components/schemas/QaScorecardTemplateOption"},"type":"array","title":"Templates"}},"type":"object","required":["templates"],"title":"QaScorecardTemplatesResponse","description":"Listing of registered scorecard templates for admin selectors."},"QueueItem":{"properties":{"call_id":{"type":"string","title":"Call Id"},"severity":{"type":"integer","title":"Severity"},"kind":{"type":"string","const":"low_qa","title":"Kind"},"extra_kinds":{"items":{"type":"string","const":"low_qa"},"type":"array","title":"Extra Kinds","default":[]},"title":{"type":"string","title":"Title"},"detail":{"type":"string","title":"Detail"},"agent_name":{"type":"string","title":"Agent Name"},"agent_user_id":{"type":"string","title":"Agent User Id"},"occurred_at":{"type":"string","format":"date-time","title":"Occurred At"},"qa_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Qa Score"}},"type":"object","required":["call_id","severity","kind","title","detail","agent_name","agent_user_id","occurred_at"],"title":"QueueItem","description":"One flagged call, worst QA score first. `severity`/`kind`/\n`extra_kinds` are kept for the pack/UI shape but are constant under the\nsingle trigger (2 / \"low_qa\" / []). Stateless exception list — review\nstate is a planned fast-follow (B5)."},"RecentCall":{"properties":{"id":{"type":"string","title":"Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"qa_score":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Qa Score"},"empathy":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Empathy"},"commitment_shape":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commitment Shape"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"headline":{"type":"string","title":"Headline"}},"type":"object","required":["id","started_at","headline"],"title":"RecentCall"},"RelatedAccountRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"external_id":{"type":"string","title":"External Id"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"display_name":{"type":"string","title":"Display Name"},"account_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Status"},"account_callable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Account Callable"},"account_synced_at":{"type":"string","format":"date-time","title":"Account Synced At"},"collection_stage":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Collection Stage"},"arranged_or_paid":{"type":"boolean","title":"Arranged Or Paid"},"balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance"},"removed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Removed At"},"campaign_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Campaign Id"},"campaign_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Campaign Name"},"membership_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Membership Status"}},"type":"object","required":["id","external_id","display_name","account_synced_at","arranged_or_paid"],"title":"RelatedAccountRead","description":"Another account of the customer under review, as the reviewer needs it.\n\n``account_status``/``account_callable``/``account_synced_at`` mean what\nthey mean on :class:`ReviewQueueItem`. ``campaign_*`` describe the\naccount's live membership, if it has one."},"RelatedAccountsRead":{"properties":{"same_customer":{"items":{"$ref":"#/components/schemas/RelatedAccountRead"},"type":"array","title":"Same Customer"},"same_customer_has_more":{"type":"boolean","title":"Same Customer Has More","default":false},"possible":{"items":{"$ref":"#/components/schemas/PossibleAccountMatchRead"},"type":"array","title":"Possible"},"possible_has_more":{"type":"boolean","title":"Possible Has More","default":false}},"type":"object","title":"RelatedAccountsRead","description":"The other accounts a reviewer should know about before deciding.\n\nEach list is bounded; ``*_has_more`` says when more exist than are shown."},"RemoveAccountsRequest":{"properties":{"account_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":500,"minItems":1,"title":"Account Ids"}},"type":"object","required":["account_ids"],"title":"RemoveAccountsRequest","description":"Working-set rows to drop, as selected on the Accounts table."},"RemoveAccountsResult":{"properties":{"removed":{"type":"integer","title":"Removed"},"skipped":{"items":{"$ref":"#/components/schemas/SkippedAccountRemoval"},"type":"array","title":"Skipped"}},"type":"object","required":["removed"],"title":"RemoveAccountsResult","description":"Per-account outcome of one removal batch.\n\nPartial success is the norm, not an error: a single account already dialling\nmust not strand the rest of the selection, so it comes back in ``skipped``\nwhile everything else is removed."},"ReplayEvent":{"properties":{"id":{"type":"string","title":"Id"},"event_type":{"type":"string","title":"Event Type","description":"Event channel: transcript, analysis, coaching, tool_call"},"sequence":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sequence","description":"Transcript sequence number associated with this event"},"elapsed_seconds":{"type":"number","title":"Elapsed Seconds","description":"Seconds from call start for replay timing"},"payload":{"additionalProperties":true,"type":"object","title":"Payload","description":"Event payload (SSE-compatible)"}},"type":"object","required":["id","event_type","elapsed_seconds","payload"],"title":"ReplayEvent","description":"Session event with timing for replay synchronization."},"ReplayMode":{"type":"string","enum":["playback","reanalysis"],"title":"ReplayMode","description":"Replay mode selection."},"RetentionSettingsRead":{"properties":{"retention_days":{"type":"integer","title":"Retention Days"},"auto_delete_enabled":{"type":"boolean","title":"Auto Delete Enabled"},"last_swept_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Swept At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"updated_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Updated By User Id"}},"type":"object","required":["retention_days","auto_delete_enabled","last_swept_at","updated_at","updated_by_user_id"],"title":"RetentionSettingsRead"},"RetentionSettingsUpdate":{"properties":{"retention_days":{"anyOf":[{"type":"integer","maximum":3650.0,"minimum":1.0},{"type":"null"}],"title":"Retention Days"},"auto_delete_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Delete Enabled"}},"additionalProperties":false,"type":"object","title":"RetentionSettingsUpdate"},"ReviewCall":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"started_at":{"type":"string","format":"date-time","title":"Started At"},"direction":{"anyOf":[{"$ref":"#/components/schemas/CallDirection"},{"type":"null"}]},"handled_by_ai":{"type":"boolean","title":"Handled By Ai"},"duration_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Seconds"},"conversation_outcome":{"anyOf":[{"$ref":"#/components/schemas/ConversationOutcome"},{"type":"null"}]},"workflow_disposition":{"anyOf":[{"$ref":"#/components/schemas/WorkflowDisposition"},{"type":"null"}]},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"}},"type":"object","required":["id","started_at","handled_by_ai"],"title":"ReviewCall","description":"The call that put a membership under review, as the reviewer needs it."},"ReviewQueueItem":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"campaign_id":{"type":"string","format":"uuid","title":"Campaign Id"},"campaign_name":{"type":"string","title":"Campaign Name"},"account_id":{"type":"string","format":"uuid","title":"Account Id"},"external_id":{"type":"string","title":"External Id"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"display_name":{"type":"string","title":"Display Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"account_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Status"},"account_callable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Account Callable"},"account_synced_at":{"type":"string","format":"date-time","title":"Account Synced At"},"balance":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Balance"},"arrears_amount":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Arrears Amount"},"attempts":{"type":"integer","title":"Attempts"},"review_reason":{"type":"string","enum":["inbound_callback","do_not_contact_request","wrong_person","refused","inbound_engaged"],"title":"Review Reason"},"waiting_since":{"type":"string","format":"date-time","title":"Waiting Since"},"review_call_session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Review Call Session Id"},"call":{"anyOf":[{"$ref":"#/components/schemas/ReviewCall"},{"type":"null"}]},"suggested_action":{"anyOf":[{"type":"string","enum":["resolved","removed","exhausted","escalated","resume","do_not_contact"]},{"type":"null"}],"title":"Suggested Action"},"suggestion_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suggestion Reason"},"other_accounts":{"type":"integer","title":"Other Accounts","default":0},"other_accounts_arranged_or_paid":{"type":"integer","title":"Other Accounts Arranged Or Paid","default":0}},"type":"object","required":["id","campaign_id","campaign_name","account_id","external_id","display_name","account_synced_at","attempts","review_reason","waiting_since"],"title":"ReviewQueueItem","description":"One membership waiting on an operator decision, with what they need to\ndecide: the account's standing, why it is here, and the triggering call.\n\n``id`` is the campaign membership id the status endpoint takes.\n``call`` is None once retention has deleted the triggering call."},"ScenarioCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Unique scenario identifier"},"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name","description":"Human-readable name"},"description":{"type":"string","minLength":1,"title":"Description","description":"Detailed description of the scenario"},"action_cards_prompt_id":{"type":"string","format":"uuid","title":"Action Cards Prompt Id","description":"ID of the action cards prompt"},"suggested_responses_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Suggested Responses Prompt Id","description":"ID of the suggested responses prompt"},"coaching_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Coaching Prompt Id","description":"ID of the coaching prompt"},"summary_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Summary Prompt Id","description":"ID of the call summary prompt"},"tagging_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tagging Prompt Id","description":"ID of the call tagging prompt"},"tool_names":{"items":{"type":"string"},"type":"array","title":"Tool Names","description":"Associated tool names"},"scenario_metadata":{"additionalProperties":true,"type":"object","title":"Scenario Metadata","description":"Additional metadata"},"is_active":{"type":"boolean","title":"Is Active","description":"Whether scenario is active","default":true},"mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mode","description":"Scenario mode: 'training' or 'production'","default":"production"},"customer_simulation_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Simulation Prompt","description":"Customer simulation prompt for training mode"},"scorecard_template_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scorecard Template Key","description":"QA scorecard template key for this scenario. Validated against the in-process template registry. Falls back to QA_SCORECARD_DEFAULT_TEMPLATE."}},"type":"object","required":["name","display_name","description","action_cards_prompt_id"],"title":"ScenarioCreate","description":"Input schema for creating a new scenario."},"ScenarioListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"tool_count":{"type":"integer","title":"Tool Count"},"scenario_metadata":{"additionalProperties":true,"type":"object","title":"Scenario Metadata"},"is_active":{"type":"boolean","title":"Is Active"},"is_default":{"type":"boolean","title":"Is Default"},"mode":{"type":"string","title":"Mode"},"scorecard_template_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scorecard Template Key"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","display_name","description","tool_count","scenario_metadata","is_active","is_default","mode","created_at","updated_at"],"title":"ScenarioListResponse","description":"Response for listing scenarios with summary info."},"ScenarioResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"action_cards_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Action Cards Prompt Id"},"suggested_responses_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Suggested Responses Prompt Id"},"coaching_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Coaching Prompt Id"},"summary_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Summary Prompt Id"},"tagging_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tagging Prompt Id"},"tool_names":{"items":{"type":"string"},"type":"array","title":"Tool Names"},"scenario_metadata":{"additionalProperties":true,"type":"object","title":"Scenario Metadata"},"is_active":{"type":"boolean","title":"Is Active"},"is_default":{"type":"boolean","title":"Is Default"},"mode":{"type":"string","title":"Mode"},"scorecard_template_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scorecard Template Key"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","display_name","description","tool_names","scenario_metadata","is_active","is_default","mode","created_at","updated_at"],"title":"ScenarioResponse","description":"Response data for a scenario."},"ScenarioUpdate":{"properties":{"display_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Display Name","description":"Human-readable name"},"description":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Description","description":"Detailed description of the scenario"},"action_cards_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Action Cards Prompt Id","description":"ID of the action cards prompt"},"suggested_responses_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Suggested Responses Prompt Id","description":"ID of the suggested responses prompt"},"coaching_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Coaching Prompt Id","description":"ID of the coaching prompt"},"summary_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Summary Prompt Id","description":"ID of the call summary prompt"},"tagging_prompt_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Tagging Prompt Id","description":"ID of the call tagging prompt"},"tool_names":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tool Names","description":"Associated tool names"},"scenario_metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Scenario Metadata","description":"Additional metadata"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active","description":"Whether scenario is active"},"mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Mode","description":"Scenario mode: 'training' or 'production'"},"customer_simulation_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Simulation Prompt","description":"Customer simulation prompt for training mode"},"scorecard_template_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scorecard Template Key","description":"QA scorecard template key for this scenario. Set to null to fall back to QA_SCORECARD_DEFAULT_TEMPLATE."}},"type":"object","title":"ScenarioUpdate","description":"Input schema for updating an existing scenario."},"ScorecardCoverage":{"properties":{"template_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Template Key"},"scored":{"type":"integer","title":"Scored","default":0},"eligible":{"type":"integer","title":"Eligible","default":0}},"type":"object","title":"ScorecardCoverage","description":"Which template the aggregation is scoped to, and how many of the\nagent's engaged calls it actually scored (review B6)."},"ScorecardSectionAgg":{"properties":{"key":{"type":"string","title":"Key"},"title":{"type":"string","title":"Title"},"agent_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Agent Pct"},"team_pct":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Team Pct"},"delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta"},"status":{"type":"string","enum":["good","warn","crit","neutral"],"title":"Status","default":"neutral"}},"type":"object","required":["key","title"],"title":"ScorecardSectionAgg"},"SessionMessageCreate":{"properties":{"text":{"type":"string","minLength":1,"title":"Text","description":"Transcript text provided by the speaker"},"speaker":{"type":"string","title":"Speaker","description":"Speaker identifier, e.g. agent or customer","default":"agent"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario","description":"Scenario identifier for this message (database scenario name)"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Optional metadata to enrich analyzer context (e.g. call type, additional context)"},"is_partial":{"type":"boolean","title":"Is Partial","description":"True when this is an interim partial transcript (not yet committed by STT)","default":false},"start_time":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Start Time","description":"Start time of first word in seconds (from stream start)"},"end_time":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"End Time","description":"End time of last word in seconds (from stream start)"}},"type":"object","required":["text"],"title":"SessionMessageCreate","description":"Payload accepted when appending messages to a session."},"SessionMonitorStatusResponse":{"properties":{"active":{"type":"boolean","title":"Active"},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Started At"},"call_mode":{"anyOf":[{"$ref":"#/components/schemas/CallMode"},{"type":"null"}]},"crm_link":{"anyOf":[{"$ref":"#/components/schemas/CrmCallLinkRead"},{"type":"null"}]}},"type":"object","required":["active"],"title":"SessionMonitorStatusResponse","description":"Small polling response; transcript and analysis travel over SSE."},"SessionSnapshotResponse":{"properties":{"transcript":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Transcript"},"metadata":{"additionalProperties":true,"type":"object","title":"Metadata"},"artifacts":{"additionalProperties":true,"type":"object","title":"Artifacts"},"sequence":{"type":"integer","title":"Sequence"},"tool_events":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Tool Events","default":[]},"call_mode":{"anyOf":[{"$ref":"#/components/schemas/CallMode"},{"type":"null"}]},"crm_link":{"anyOf":[{"$ref":"#/components/schemas/CrmCallLinkRead"},{"type":"null"}]}},"type":"object","required":["transcript","metadata","artifacts","sequence"],"title":"SessionSnapshotResponse","description":"Full session state snapshot for supervisor bootstrap."},"SessionStartResponse":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id"}},"type":"object","required":["session_id"],"title":"SessionStartResponse","description":"Response data returned when starting a new session."},"SkippedAccountRemoval":{"properties":{"account_id":{"type":"string","format":"uuid","title":"Account Id"},"reason":{"type":"string","enum":["not_found","call_in_progress"],"title":"Reason"}},"type":"object","required":["account_id","reason"],"title":"SkippedAccountRemoval","description":"One account the batch deliberately left in place, and why."},"SmsIntegrationConfig":{"properties":{"provider":{"type":"string","const":"twilio","title":"Provider","default":"twilio"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"}},"type":"object","title":"SmsIntegrationConfig"},"SmsIntegrationResponse":{"properties":{"provider":{"type":"string","const":"twilio","title":"Provider","default":"twilio"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"},"id":{"type":"string","format":"uuid","title":"Id"}},"type":"object","required":["id"],"title":"SmsIntegrationResponse"},"SmsIntegrationStatus":{"properties":{"provider":{"type":"string","const":"twilio","title":"Provider","default":"twilio"},"credentials_configured":{"type":"boolean","title":"Credentials Configured"},"enabled":{"type":"boolean","title":"Enabled"},"active":{"type":"boolean","title":"Active"},"dry_run":{"type":"boolean","title":"Dry Run"},"account_sid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Sid"},"api_key_sid":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key Sid"},"sms_from":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sms From"}},"type":"object","required":["credentials_configured","enabled","active","dry_run"],"title":"SmsIntegrationStatus"},"SmsTestRequest":{"properties":{"provider":{"type":"string","const":"twilio","title":"Provider","default":"twilio"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"additionalProperties":true,"type":"object","title":"Config"},"to":{"type":"string","title":"To","default":""}},"type":"object","title":"SmsTestRequest"},"SmsTestResponse":{"properties":{"provider":{"type":"string","const":"twilio","title":"Provider"},"message":{"type":"string","title":"Message"}},"type":"object","required":["provider","message"],"title":"SmsTestResponse"},"SparkArrangementDraft":{"properties":{"origin":{"type":"string","enum":["court_order","customer_requested","agent_initiated","ivr_initiated","ivr_agent_initiated_other","ivr_agent_initiated_ss","reduced_settlement_arrangement"],"title":"Origin"},"payment_mode":{"type":"string","enum":["sequenceshift","direct_debit","direct_credit","app_payment"],"title":"Payment Mode"},"frequency":{"type":"string","enum":["weekly","fortnightly","monthly","lumpsum","quarterly"],"title":"Frequency"},"installment_amount":{"anyOf":[{"type":"number","maximum":10000000.0,"exclusiveMinimum":0.0},{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d{0,2}0*$"}],"title":"Installment Amount"},"occurrences":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Occurrences"},"from_date":{"type":"string","format":"date","title":"From Date"}},"type":"object","required":["origin","payment_mode","frequency","installment_amount","occurrences","from_date"],"title":"SparkArrangementDraft"},"SparkCallOutcomeDraft":{"properties":{"contact_through":{"type":"string","enum":["inbound_call","outbound_call"],"title":"Contact Through"},"customer_id":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Customer Id"},"contact_type":{"type":"string","maxLength":64,"minLength":1,"title":"Contact Type"},"action_taken":{"anyOf":[{"type":"string","enum":["arrangement","call_back_later","hardship","on_hold","no_outcome","repossessed"]},{"type":"null"}],"title":"Action Taken"},"reason_code_key":{"anyOf":[{"type":"string","enum":["DEPOSIT_IN_PROGRESS","NO_ANSWER","no_action_needed","PROMISE_TO_PAY","REQUEST_FOR_FEE_WAIVER","REQUEST_FOR_HARDSHIP","REFUSE_TO_PAY","SELLING_COLLATERAL","SPECIAL_HANDLING","UNABLE_TO_PAY","UNABLE_TO_TALK","ivr_disconnected","ivr_transfer"]},{"type":"null"}],"title":"Reason Code Key"},"sub_call_type":{"anyOf":[{"type":"string","enum":["call_terminated","customer_contacted","contact_no_outcome","follow_up_needed","lmtc_via_text","lmtc_on_voice_mail","no_answer","disconnected","Third-party_contacted","v-mail_no_message_left","wrong_number"]},{"type":"null"}],"title":"Sub Call Type"},"comments":{"type":"string","maxLength":2000,"title":"Comments","default":""},"arrangement":{"anyOf":[{"$ref":"#/components/schemas/SparkArrangementDraft"},{"type":"null"}]},"hold_till":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Hold Till"},"callback_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Callback Date"},"callback_time":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Callback Time"},"acknowledge_unconfirmed":{"type":"boolean","title":"Acknowledge Unconfirmed","default":false}},"type":"object","required":["contact_through","contact_type"],"title":"SparkCallOutcomeDraft","description":"What the agent confirmed. Account and agent identity are not in here:\nthe server resolves both, so a request cannot write against an account the\ncall isn't linked to or under someone else's name."},"SparkCallOutcomeExportRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","enum":["success","failed","unknown"],"title":"Status"},"provider_operation_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Operation Id"},"error_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error Message"},"requested_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Requested By User Id"},"attempted_at":{"type":"string","format":"date-time","title":"Attempted At"}},"type":"object","required":["id","status","attempted_at"],"title":"SparkCallOutcomeExportRead"},"SparkCallOutcomeSaveResponse":{"properties":{"export":{"$ref":"#/components/schemas/SparkCallOutcomeExportRead"},"already_saved":{"type":"boolean","title":"Already Saved","default":false}},"type":"object","required":["export"],"title":"SparkCallOutcomeSaveResponse"},"SparkCallOutcomeState":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"blocked_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blocked Reason"},"finalizing":{"type":"boolean","title":"Finalizing","default":false},"agent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Agent Name"},"account_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Account Number"},"customer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Name"},"parties":{"items":{"$ref":"#/components/schemas/SparkCallPartyRead"},"type":"array","title":"Parties"},"customer_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Id"},"contact_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Contact Type"},"suggestion":{"anyOf":[{"$ref":"#/components/schemas/SparkCallOutcomeSuggestion"},{"type":"null"}]},"latest_export":{"anyOf":[{"$ref":"#/components/schemas/SparkCallOutcomeExportRead"},{"type":"null"}]}},"type":"object","required":["enabled"],"title":"SparkCallOutcomeState","description":"Everything the review form needs, resolved server-side."},"SparkCallOutcomeSuggestion":{"properties":{"source":{"type":"string","enum":["transcript","classification"],"title":"Source","default":"classification"},"contact_through":{"anyOf":[{"type":"string","enum":["inbound_call","outbound_call"]},{"type":"null"}],"title":"Contact Through"},"action_taken":{"anyOf":[{"type":"string","enum":["arrangement","call_back_later","hardship","on_hold","no_outcome","repossessed"]},{"type":"null"}],"title":"Action Taken"},"reason_code_key":{"anyOf":[{"type":"string","enum":["DEPOSIT_IN_PROGRESS","NO_ANSWER","no_action_needed","PROMISE_TO_PAY","REQUEST_FOR_FEE_WAIVER","REQUEST_FOR_HARDSHIP","REFUSE_TO_PAY","SELLING_COLLATERAL","SPECIAL_HANDLING","UNABLE_TO_PAY","UNABLE_TO_TALK","ivr_disconnected","ivr_transfer"]},{"type":"null"}],"title":"Reason Code Key"},"sub_call_type":{"anyOf":[{"type":"string","enum":["call_terminated","customer_contacted","contact_no_outcome","follow_up_needed","lmtc_via_text","lmtc_on_voice_mail","no_answer","disconnected","Third-party_contacted","v-mail_no_message_left","wrong_number"]},{"type":"null"}],"title":"Sub Call Type"},"frequency":{"anyOf":[{"type":"string","enum":["weekly","fortnightly","monthly","lumpsum","quarterly"]},{"type":"null"}],"title":"Frequency"},"installment_amount":{"anyOf":[{"type":"string","pattern":"^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"},{"type":"null"}],"title":"Installment Amount"},"occurrences":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Occurrences"},"from_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"From Date"},"payment_mode":{"anyOf":[{"type":"string","enum":["sequenceshift","direct_debit","direct_credit","app_payment"]},{"type":"null"}],"title":"Payment Mode"},"origin":{"anyOf":[{"type":"string","enum":["court_order","customer_requested","agent_initiated","ivr_initiated","ivr_agent_initiated_other","ivr_agent_initiated_ss","reduced_settlement_arrangement"]},{"type":"null"}],"title":"Origin"},"hold_till":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Hold Till"},"callback_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Callback Date"},"callback_time":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Callback Time"},"comments":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comments"},"explanation":{"type":"string","title":"Explanation"}},"type":"object","required":["explanation"],"title":"SparkCallOutcomeSuggestion","description":"A starting point for the review form, never a decision."},"SparkCallPartyRead":{"properties":{"customer_id":{"type":"string","title":"Customer Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"third_party":{"type":"boolean","title":"Third Party","default":false},"contact_types":{"items":{"type":"string"},"type":"array","title":"Contact Types"}},"type":"object","required":["customer_id","contact_types"],"title":"SparkCallPartyRead","description":"A borrower or third-party authority the call can be logged against."},"SuggestedResponseLatencyLegs":{"properties":{"stt":{"$ref":"#/components/schemas/LatencyLegSummary"},"commit":{"$ref":"#/components/schemas/LatencyLegSummary"},"ttft":{"$ref":"#/components/schemas/LatencyLegSummary"},"delivery":{"$ref":"#/components/schemas/LatencyLegSummary"}},"type":"object","required":["stt","commit","ttft","delivery"],"title":"SuggestedResponseLatencyLegs"},"SuggestedResponsePromptResponse":{"properties":{"found":{"type":"boolean","title":"Found","description":"Whether a matching Langfuse generation was found"},"sequence":{"type":"integer","title":"Sequence","description":"Transcript sequence of the turn"},"system_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"System Prompt"},"user_prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Prompt","description":"Rendered user prompt incl. injected context"},"output":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Output","description":"The suggestion the model produced"},"trace_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Trace Url","description":"Deep link to the Langfuse trace"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail","description":"Reason no prompt was returned, when found is false"}},"type":"object","required":["found","sequence"],"title":"SuggestedResponsePromptResponse","description":"Rendered prompt + output for the suggested response at one turn.\n\nReconstructed from the Langfuse generation trace so the suggested-responses\nprompt can be tuned against what the agent actually said. Output-only data\nlives in our DB; the prompt *input* (context) only exists in Langfuse."},"SummaryRequest":{"properties":{"transcript":{"items":{"$ref":"#/components/schemas/TranscriptEntry"},"type":"array","title":"Transcript","description":"Conversation transcript"},"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario","description":"Optional fallback when the call has no persisted scenario"}},"type":"object","required":["transcript"],"title":"SummaryRequest","description":"Request to generate call summary."},"SummaryResponse":{"properties":{"success":{"type":"boolean","title":"Success","description":"Whether summary generation succeeded"},"session_id":{"type":"string","title":"Session Id","description":"Session ID"},"summary_markdown":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary Markdown","description":"Free-form markdown summary of the call"},"talk_time_stats":{"anyOf":[{"$ref":"#/components/schemas/TalkTimeStats"},{"type":"null"}],"description":"Talk time distribution statistics"}},"type":"object","required":["success","session_id"],"title":"SummaryResponse","description":"Response containing call summary."},"TCNAgent":{"properties":{"tcn_user_id":{"type":"string","title":"Tcn User Id","description":"TCN userId (UUID string) — the key mapped to a Whispa user"},"name":{"type":"string","title":"Name","description":"Display name","default":""},"username":{"type":"string","title":"Username","description":"TCN username","default":""},"email":{"type":"string","title":"Email","description":"Agent email (used to auto-suggest a Whispa account)","default":""},"agent_sid":{"type":"string","title":"Agent Sid","description":"TCN agent SID","default":""},"hunt_group_name":{"type":"string","title":"Hunt Group Name","description":"Hunt group name","default":""},"disabled":{"type":"boolean","title":"Disabled","description":"Whether the agent is disabled in TCN","default":false}},"type":"object","required":["tcn_user_id"],"title":"TCNAgent","description":"An agent from a TCN org (for agent discovery / linking)."},"TCNAgentListRequest":{"properties":{"provider":{"type":"string","const":"tcn","title":"Provider","default":"tcn"},"config":{"$ref":"#/components/schemas/TCNConfig-Input"}},"type":"object","required":["config"],"title":"TCNAgentListRequest","description":"Request to list agents from a TCN org."},"TCNBotConfig":{"properties":{"name":{"type":"string","maxLength":80,"title":"Name","default":""},"agent_sid":{"type":"string","pattern":"^[1-9]\\d*$","title":"Agent Sid"},"api_key":{"type":"string","title":"Api Key","default":""},"tcn_user_id":{"type":"string","pattern":"^(?:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})?$","title":"Tcn User Id","default":""},"enabled":{"type":"boolean","title":"Enabled","default":true}},"type":"object","required":["agent_sid"],"title":"TCNBotConfig","description":"One separately authenticated voice slot in the bot pool.\n\nA bot signs in either with a pasted token or as its TCN user through the\ndeployment's service account, which renews the token itself."},"TCNConfig-Input":{"properties":{"voice_agent":{"anyOf":[{"$ref":"#/components/schemas/TCNVoiceAgentConfig"},{"type":"null"}]},"store_audio":{"type":"boolean","title":"Store Audio","default":false},"api_key":{"type":"string","title":"Api Key","description":"TCN Personal Access Token (JWT)"},"base_url":{"type":"string","title":"Base Url","description":"TCN API base URL (region-specific)","default":"https://api.syd.tcn.com"},"tcn_user_map":{"additionalProperties":{"type":"string","format":"uuid"},"type":"object","title":"Tcn User Map","description":"Maps TCN userId (UUID string) to Whispa user_id"},"suspend_grace_seconds":{"type":"number","minimum":0.0,"title":"Suspend Grace Seconds","description":"How long a session stays open after the agent leaves a call without wrap-up (payment-line park), awaiting a resume of the same TCN call. 0 disables suspend/resume.","default":360.0}},"type":"object","required":["api_key"],"title":"TCNConfig","description":"Configuration for TCN integration.\n\nTCN exposes a single org-wide server-streaming endpoint\n(``/api/v1alpha1/asm/asm/managerstreamagentstate``) that emits per-agent\nstate frames. Authentication is a Personal Access Token (Bearer)."},"TCNConfig-Output":{"properties":{"voice_agent":{"anyOf":[{"$ref":"#/components/schemas/TCNVoiceAgentConfig"},{"type":"null"}]},"store_audio":{"type":"boolean","title":"Store Audio","default":false},"api_key":{"type":"string","title":"Api Key","description":"TCN Personal Access Token (JWT)"},"base_url":{"type":"string","title":"Base Url","description":"TCN API base URL (region-specific)","default":"https://api.syd.tcn.com"},"tcn_user_map":{"additionalProperties":{"type":"string","format":"uuid"},"type":"object","title":"Tcn User Map","description":"Maps TCN userId (UUID string) to Whispa user_id"},"suspend_grace_seconds":{"type":"number","minimum":0.0,"title":"Suspend Grace Seconds","description":"How long a session stays open after the agent leaves a call without wrap-up (payment-line park), awaiting a resume of the same TCN call. 0 disables suspend/resume.","default":360.0}},"type":"object","required":["api_key"],"title":"TCNConfig","description":"Configuration for TCN integration.\n\nTCN exposes a single org-wide server-streaming endpoint\n(``/api/v1alpha1/asm/asm/managerstreamagentstate``) that emits per-agent\nstate frames. Authentication is a Personal Access Token (Bearer)."},"TCNIntegrationConfig":{"properties":{"provider":{"type":"string","const":"tcn","title":"Provider","default":"tcn"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"$ref":"#/components/schemas/TCNConfig-Input"}},"type":"object","required":["config"],"title":"TCNIntegrationConfig","description":"Request model for TCN integration config."},"TCNIntegrationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","const":"tcn","title":"Provider","default":"tcn"},"enabled":{"type":"boolean","title":"Enabled"},"config":{"$ref":"#/components/schemas/TCNConfig-Output"},"reload_warning":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reload Warning","description":"Set when the saved config could not be applied to the live adapter. DB is updated but the running stream may still use the previous config until the backend restarts."}},"type":"object","required":["id","enabled","config"],"title":"TCNIntegrationResponse","description":"Response model for TCN integration config."},"TCNTestRequest":{"properties":{"provider":{"type":"string","const":"tcn","title":"Provider","default":"tcn"},"config":{"$ref":"#/components/schemas/TCNConfig-Input"}},"type":"object","required":["config"],"title":"TCNTestRequest","description":"Request to test TCN configuration."},"TCNVoiceAgentConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":false},"agent_sid":{"type":"string","pattern":"^(?:[1-9]\\d*)?$","title":"Agent Sid","default":""},"hunt_group_sid":{"type":"string","pattern":"^(?:[1-9]\\d*)?$","title":"Hunt Group Sid","default":""},"bots":{"items":{"$ref":"#/components/schemas/TCNBotConfig"},"type":"array","maxItems":7,"title":"Bots"},"max_outbound_calls":{"type":"integer","maximum":7.0,"minimum":0.0,"title":"Max Outbound Calls","default":5},"caller_id":{"type":"string","title":"Caller Id","default":""},"human_queue":{"type":"string","pattern":"^(?:[1-9]\\d*)?$","title":"Human Queue","default":""},"default_region":{"type":"string","title":"Default Region","default":"AU"}},"type":"object","title":"TCNVoiceAgentConfig","description":"Dedicated bot identity; SIP networking is configured on the worker."},"TagRate":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"count":{"type":"integer","title":"Count"},"rate":{"type":"number","title":"Rate"}},"type":"object","required":["key","label","count","rate"],"title":"TagRate"},"TagStrength":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"agent_qa":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Agent Qa"},"team_qa":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Team Qa"},"delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta"},"sample":{"type":"integer","title":"Sample","default":0}},"type":"object","required":["key","label"],"title":"TagStrength"},"TalkTimeStats":{"properties":{"agent_percentage":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Agent Percentage","description":"Percentage of talk time by the agent"},"customer_percentage":{"type":"integer","maximum":100.0,"minimum":0.0,"title":"Customer Percentage","description":"Percentage of talk time by the customer"},"agent_utterances":{"type":"integer","minimum":0.0,"title":"Agent Utterances","description":"Number of utterances by the agent"},"customer_utterances":{"type":"integer","minimum":0.0,"title":"Customer Utterances","description":"Number of utterances by the customer"}},"type":"object","required":["agent_percentage","customer_percentage","agent_utterances","customer_utterances"],"title":"TalkTimeStats","description":"Talk time statistics for a call."},"TeamCreate":{"properties":{"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"scenario_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Scenario Ids"}},"type":"object","required":["name"],"title":"TeamCreate"},"TeamRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"is_active":{"type":"boolean","title":"Is Active"},"scenarios":{"items":{"$ref":"#/components/schemas/TeamScenarioRead"},"type":"array","title":"Scenarios"},"user_count":{"type":"integer","title":"User Count","default":0},"lead_count":{"type":"integer","title":"Lead Count","default":0},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","is_active","created_at","updated_at"],"title":"TeamRead"},"TeamScenarioRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"}},"type":"object","required":["id","name","display_name"],"title":"TeamScenarioRead"},"TeamUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Name"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"scenario_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array"},{"type":"null"}],"title":"Scenario Ids"}},"type":"object","title":"TeamUpdate"},"TelephonyIntegrationConfig":{"properties":{"provider":{"type":"string","title":"Provider","description":"Provider identifier, e.g. 'threecx' or 'awsconnect'"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"$ref":"#/components/schemas/ThreeCXConfig"}},"type":"object","required":["provider","config"],"title":"TelephonyIntegrationConfig"},"TelephonyIntegrationResponse":{"properties":{"provider":{"type":"string","title":"Provider","description":"Provider identifier, e.g. 'threecx' or 'awsconnect'"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"$ref":"#/components/schemas/ThreeCXConfig"},"id":{"type":"string","format":"uuid","title":"Id"}},"type":"object","required":["provider","config","id"],"title":"TelephonyIntegrationResponse"},"TelephonyResult":{"type":"string","enum":["connected","busy","no_answer","rejected","failed"],"title":"TelephonyResult","description":"Telephony-level call connection result.\n\nRepresents what happened at the telephony level before any conversation.\nThis is typically provided by the PBX/telephony system, not AI-classified."},"TelephonyTestRequest":{"properties":{"provider":{"type":"string","title":"Provider","description":"Provider identifier"},"config":{"$ref":"#/components/schemas/ThreeCXConfig"}},"type":"object","required":["provider","config"],"title":"TelephonyTestRequest"},"ThreeCXConfig":{"properties":{"host":{"type":"string","title":"Host","description":"3CX host or URL"},"client_id":{"type":"string","title":"Client Id","description":"OAuth2 client ID","default":"whispa"},"default_region":{"type":"string","maxLength":2,"minLength":2,"pattern":"^[A-Za-z]{2}$","title":"Default Region","description":"ISO country code used to interpret national customer numbers and format autonomous-agent dial destinations","default":"AU"},"client_secret":{"type":"string","title":"Client Secret","description":"OAuth2 client secret","default":""},"api_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Api Key","description":"[Deprecated] Use client_secret"},"monitored_extensions":{"items":{"type":"string"},"type":"array","title":"Monitored Extensions"},"extension_user_map":{"anyOf":[{"additionalProperties":{"type":"string","format":"uuid"},"type":"object"},{"type":"null"}],"title":"Extension User Map","description":"Maps extension numbers to Whispa user IDs"},"use_external_audio":{"type":"boolean","title":"Use External Audio","description":"Use external audio source (e.g. desktop app) instead of 3CX audio stream","default":true},"store_audio":{"type":"boolean","title":"Store Audio","description":"Archive call audio to Whispa storage — copilot desktop audio (per-chunk PCM plus a final WAV per call) and the autonomous agent's full-call WAV alike. When off, audio only feeds live transcription and the telephony system's own recording is the recording of record.","default":false},"voice_agent":{"anyOf":[{"$ref":"#/components/schemas/ThreeCXVoiceAgentConfig"},{"type":"null"}],"description":"Outbound autonomous-agent routing; reuses this 3CX connection"}},"type":"object","required":["host"],"title":"ThreeCXConfig"},"ThreeCXTestCallRequest":{"properties":{"phone_number":{"type":"string","maxLength":32,"minLength":1,"title":"Phone Number","description":"Destination accepted by the configured 3CX dial plan"}},"type":"object","required":["phone_number"],"title":"ThreeCXTestCallRequest","description":"Destination for a transport-only outbound 3CX diagnostic."},"ThreeCXTestCallResponse":{"properties":{"status":{"type":"string","const":"dialing","title":"Status","default":"dialing"},"participant_id":{"type":"integer","title":"Participant Id"}},"type":"object","required":["participant_id"],"title":"ThreeCXTestCallResponse","description":"Acknowledgement after 3CX creates the outbound participant."},"ThreeCXVoiceAgentConfig":{"properties":{"enabled":{"type":"boolean","title":"Enabled","description":"Whether the autonomous agent can place outbound calls","default":false},"agent_dn":{"type":"string","title":"Agent Dn","description":"Route Point DN the agent dials FROM (must be a Wroutepoint)","default":""},"agent_device_id":{"type":"string","title":"Agent Device Id","description":"Device ID for makecall (blank → device-less)","default":""},"human_destination":{"type":"string","title":"Human Destination","description":"Extension/queue to warm-transfer callers to (blank → transfer disabled)","default":""},"human_queue":{"type":"string","title":"Human Queue","description":"Queue DN that takes outbound callers when the agent cannot continue (model failure, failed identity check); blank → the call closes","default":""},"dial_prefix":{"type":"string","maxLength":16,"pattern":"^[0-9*#]*$","title":"Dial Prefix","description":"PBX access prefix prepended after converting customer numbers to the configured default region's national format","default":""}},"type":"object","title":"ThreeCXVoiceAgentConfig","description":"Outbound autonomous-agent settings, nested under the 3CX provider config.\n\nThe agent dials OUT over the same 3CX connection (host/client_id/secret) as\nthe inbound copilot — only the outbound routing differs, so it lives here as a\nsub-section rather than a separate provider. A future telephony provider that\nsupports the autonomous agent would carry its own equivalent sub-config.\n\nSTT keys stay in env (ASSEMBLYAI_API_KEY or DEEPGRAM_API_KEY), as does\nthe selected provider's API key; the TTS voice is per-scenario\n(voice_agent_config.voice_id, with legacy Cartesia ids still accepted)."},"Tile":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"unit":{"type":"string","enum":["percent","count","currency"],"title":"Unit"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"prior":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Prior"},"delta":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Delta"},"target":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Target"},"sample":{"type":"integer","title":"Sample","default":0},"status":{"type":"string","enum":["good","warn","crit","neutral"],"title":"Status","default":"neutral"},"good_direction":{"type":"string","enum":["up","down"],"title":"Good Direction","default":"up"},"available":{"type":"boolean","title":"Available","default":true},"definition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Definition"},"secondary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Secondary"},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caption"}},"type":"object","required":["key","label","unit"],"title":"Tile","description":"A headline metric tile with prior-period comparison. Status, delta\ndirection and the definition are all server-computed (review A5/B7) —\nthe frontend never re-derives thresholds."},"ToolCatalogResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"is_active":{"type":"boolean","title":"Is Active"},"input_schema":{"additionalProperties":true,"type":"object","title":"Input Schema"}},"type":"object","required":["id","name","display_name","description","is_active"],"title":"ToolCatalogResponse","description":"Response for the action card catalog used in scenario configuration."},"ToolCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Unique tool identifier"},"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name","description":"Human-readable name"},"description":{"type":"string","minLength":1,"title":"Description","description":"Description of what the tool does"},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters","description":"Tool parameters/fields configuration"},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category","description":"Category for grouping tools"},"is_active":{"type":"boolean","title":"Is Active","description":"Whether tool is active","default":true}},"type":"object","required":["name","display_name","description"],"title":"ToolCreate","description":"Input schema for creating a new tool (action card)."},"ToolListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","display_name","description","category","is_active","created_at","updated_at"],"title":"ToolListResponse","description":"Response for listing tools with summary info."},"ToolResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"parameters":{"additionalProperties":true,"type":"object","title":"Parameters"},"category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","display_name","description","parameters","category","is_active","created_at","updated_at"],"title":"ToolResponse","description":"Response data for a tool."},"ToolUpdate":{"properties":{"display_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Display Name","description":"Human-readable name"},"description":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Description","description":"Description of what the tool does"},"parameters":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Parameters","description":"Tool parameters/fields configuration"},"category":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Category","description":"Category for grouping tools"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active","description":"Whether tool is active"}},"type":"object","title":"ToolUpdate","description":"Input schema for updating an existing tool."},"TotalCommitmentSource":{"type":"string","enum":["explicit","derived","not_available"],"title":"TotalCommitmentSource","description":"Provenance of `total_commitment_amount`."},"TrainingAgentConnection":{"properties":{"signed_url":{"type":"string","title":"Signed Url","description":"Short-lived ElevenLabs signed URL for one browser conversation with the deployment's training agent."}},"type":"object","required":["signed_url"],"title":"TrainingAgentConnection"},"TrainingAgentStatus":{"properties":{"configured":{"type":"boolean","title":"Configured","description":"Whether ELEVENLABS_API_KEY is set, i.e. training calls work"},"agent_name":{"type":"string","title":"Agent Name","description":"Deployment's training agent name in the ElevenLabs workspace"}},"type":"object","required":["configured","agent_name"],"title":"TrainingAgentStatus"},"TrainingPersonaCreate":{"properties":{"name":{"type":"string","maxLength":100,"minLength":1,"title":"Name","description":"Unique persona identifier"},"display_name":{"type":"string","maxLength":200,"minLength":1,"title":"Display Name","description":"Human-readable name"},"description":{"type":"string","minLength":1,"title":"Description","description":"Situation summary shown on the persona card"},"scenario_id":{"type":"string","format":"uuid","title":"Scenario Id","description":"Training scenario this persona belongs to"},"debtor_name":{"type":"string","maxLength":200,"minLength":1,"title":"Debtor Name","description":"Fictional debtor full name"},"date_of_birth":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Date Of Birth"},"address":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Address"},"creditor_account":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Creditor Account","description":"Creditor / account description"},"amount_owed":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Amount Owed","description":"Free-text overdue amount"},"temperament_tags":{"items":{"type":"string"},"type":"array","title":"Temperament Tags","description":"Temperament labels driving card badges (e.g. busy, aggressive)"},"difficulty":{"type":"string","title":"Difficulty","description":"easy | medium | hard","default":"medium"},"affordability":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Affordability","description":"What the debtor can realistically pay"},"backstory":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Backstory","description":"Extra colour for how the persona behaves"},"prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Override","description":"Verbatim simulation prompt; wins over the structured template"},"first_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Message","description":"Opening line the simulated customer speaks"},"voice":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice","description":"Simulated customer voice: male | female (null = agent default)"},"is_active":{"type":"boolean","title":"Is Active","description":"Whether the persona is shown","default":true}},"type":"object","required":["name","display_name","description","scenario_id","debtor_name"],"title":"TrainingPersonaCreate","description":"Input schema for creating a training persona."},"TrainingPersonaListResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"scenario_id":{"type":"string","format":"uuid","title":"Scenario Id"},"scenario_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario Name"},"scenario_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario Display Name"},"debtor_name":{"type":"string","title":"Debtor Name"},"date_of_birth":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Birth"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"creditor_account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creditor Account"},"amount_owed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Amount Owed"},"temperament_tags":{"items":{"type":"string"},"type":"array","title":"Temperament Tags"},"difficulty":{"type":"string","title":"Difficulty"},"affordability":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Affordability"},"first_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Message"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","display_name","description","scenario_id","debtor_name","date_of_birth","address","creditor_account","amount_owed","temperament_tags","difficulty","affordability","first_message","is_active","created_at","updated_at"],"title":"TrainingPersonaListResponse","description":"Browse payload for the persona card grid (all users).\n\nDeliberately excludes ``backstory``, ``prompt_override`` and\n``resolved_prompt`` — they are the hidden behavioural script; shipping\nthem on the browse list would let trainees read how the simulated\ncustomer is going to behave. The full payload stays on the detail and\nadmin endpoints."},"TrainingPersonaResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"display_name":{"type":"string","title":"Display Name"},"description":{"type":"string","title":"Description"},"scenario_id":{"type":"string","format":"uuid","title":"Scenario Id"},"scenario_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario Name","description":"Joined Scenario.name for /training hydration"},"scenario_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario Display Name"},"debtor_name":{"type":"string","title":"Debtor Name"},"date_of_birth":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Of Birth"},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address"},"creditor_account":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Creditor Account"},"amount_owed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Amount Owed"},"temperament_tags":{"items":{"type":"string"},"type":"array","title":"Temperament Tags"},"difficulty":{"type":"string","title":"Difficulty"},"affordability":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Affordability"},"backstory":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Backstory"},"prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Override"},"first_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Message"},"voice":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice"},"resolved_prompt":{"type":"string","title":"Resolved Prompt","description":"Final simulation prompt (override or structured template)"},"resolved_voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolved Voice Id","description":"ElevenLabs voice ID for the persona's voice, applied as a runtime TTS override at call start (null = agent default voice)"},"is_active":{"type":"boolean","title":"Is Active"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"updated_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Updated By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","name","display_name","description","scenario_id","debtor_name","date_of_birth","address","creditor_account","amount_owed","temperament_tags","difficulty","affordability","backstory","prompt_override","first_message","voice","resolved_prompt","is_active","created_by","updated_by","created_at","updated_at"],"title":"TrainingPersonaResponse","description":"Full persona payload including computed prompt for call-start overrides."},"TrainingPersonaUpdate":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":100,"minLength":1},{"type":"null"}],"title":"Name"},"display_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Display Name"},"description":{"anyOf":[{"type":"string","minLength":1},{"type":"null"}],"title":"Description"},"scenario_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Scenario Id"},"debtor_name":{"anyOf":[{"type":"string","maxLength":200,"minLength":1},{"type":"null"}],"title":"Debtor Name"},"date_of_birth":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Date Of Birth"},"address":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Address"},"creditor_account":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Creditor Account"},"amount_owed":{"anyOf":[{"type":"string","maxLength":100},{"type":"null"}],"title":"Amount Owed"},"temperament_tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Temperament Tags"},"difficulty":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Difficulty"},"affordability":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Affordability"},"backstory":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Backstory"},"prompt_override":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Prompt Override"},"first_message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Message"},"voice":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"TrainingPersonaUpdate","description":"Input schema for updating a training persona (partial)."},"TranscriptEntry":{"properties":{"speaker":{"type":"string","title":"Speaker","description":"Speaker identifier (e.g., 'agent', 'customer')"},"text":{"type":"string","title":"Text","description":"The spoken text"},"start_time":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Start Time","description":"Seconds from call start (positions timeline markers)"}},"type":"object","required":["speaker","text"],"title":"TranscriptEntry","description":"A single transcript entry."},"TrendPoint":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"qa_score":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Qa Score"}},"type":"object","required":["date"],"title":"TrendPoint","description":"Daily QA score average."},"TurnLatencyBeacon":{"properties":{"turn_id":{"type":"string","maxLength":64,"minLength":1,"title":"Turn Id"},"producer":{"type":"string","maxLength":64,"minLength":1,"title":"Producer"},"delivery_ms":{"type":"integer","maximum":60000.0,"minimum":0.0,"title":"Delivery Ms","description":"Milliseconds between backend SessionEvent.created_at and the client's SSE onmessage timestamp for the first suggested-responses envelope of the turn."},"client_received_at_wall":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Client Received At Wall","description":"Client Date.now() when the envelope was received (ms since epoch)."}},"type":"object","required":["turn_id","producer","delivery_ms"],"title":"TurnLatencyBeacon","description":"Frontend beacon payload for the Leg 4 (SSE delivery) VAQI-L sample."},"TwilioVoiceConfig":{"properties":{"caller_id":{"type":"string","pattern":"^\\+[1-9]\\d{6,14}$","title":"Caller Id","description":"Twilio number outbound calls are placed from"},"public_base_url":{"type":"string","title":"Public Base Url","description":"Public HTTPS URL of this API, which Twilio connects call audio to (blank → API_BASE_URL)","default":""},"human_destination":{"type":"string","pattern":"^(?:\\+[1-9]\\d{6,14})?$","title":"Human Destination","description":"Phone number callers are transferred to (blank → transfer disabled)","default":""},"human_queue":{"type":"string","pattern":"^(?:\\+[1-9]\\d{6,14})?$","title":"Human Queue","description":"Phone number that takes outbound callers when the agent cannot continue; blank → the call closes","default":""},"default_region":{"type":"string","title":"Default Region","default":"US"},"store_audio":{"type":"boolean","title":"Store Audio","default":false}},"type":"object","required":["caller_id"],"title":"TwilioVoiceConfig","description":"Autonomous-agent settings for calls carried by our own Twilio numbers.\n\nCredentials are not stored here: the agent uses the Twilio API key from\nthe Twilio SMS integration (or ``TWILIO_*`` env)."},"TwilioVoiceIntegrationConfig":{"properties":{"provider":{"type":"string","const":"twilio","title":"Provider","default":"twilio"},"enabled":{"type":"boolean","title":"Enabled","default":true},"config":{"$ref":"#/components/schemas/TwilioVoiceConfig"}},"type":"object","required":["config"],"title":"TwilioVoiceIntegrationConfig","description":"Request model for Twilio Voice integration config."},"TwilioVoiceIntegrationResponse":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","const":"twilio","title":"Provider","default":"twilio"},"enabled":{"type":"boolean","title":"Enabled"},"config":{"$ref":"#/components/schemas/TwilioVoiceConfig"}},"type":"object","required":["id","enabled","config"],"title":"TwilioVoiceIntegrationResponse","description":"Response model for Twilio Voice integration config."},"UnknownCallerPolicy":{"type":"string","enum":["proceed","fallback"],"title":"UnknownCallerPolicy","description":"How to treat a caller whose number matches no CRM account.\n\nMultiple matches never use this policy: they require a specialist because\nv1 deliberately has no account-selection or multi-account self-service."},"UpdateClassificationRequest":{"properties":{"scenario":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Scenario","description":"New scenario name to assign to this call"},"regenerate_artifacts":{"type":"boolean","title":"Regenerate Artifacts","description":"Whether to regenerate coaching/summary with the new scenario's prompts","default":false}},"type":"object","title":"UpdateClassificationRequest","description":"Request to update call classification fields."},"UploadCallResponse":{"properties":{"session_id":{"type":"string","format":"uuid","title":"Session Id"},"message":{"type":"string","title":"Message"},"transcript_length":{"type":"integer","title":"Transcript Length"}},"type":"object","required":["session_id","message","transcript_length"],"title":"UploadCallResponse","description":"Response from uploading a call recording."},"UserRead":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"type":"string","format":"email","title":"Email"},"is_active":{"type":"boolean","title":"Is Active","default":true},"is_superuser":{"type":"boolean","title":"Is Superuser","default":false},"is_verified":{"type":"boolean","title":"Is Verified","default":false},"role":{"$ref":"#/components/schemas/UserRole"},"team_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Team Id"},"first_name":{"type":"string","title":"First Name"},"last_name":{"type":"string","title":"Last Name"}},"type":"object","required":["id","email","role","first_name","last_name"],"title":"UserRead"},"UserRole":{"type":"string","enum":["admin","team_lead","user"],"title":"UserRole"},"UserSettingsRead":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"default_scenario_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Default Scenario Id"},"default_scenario_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Scenario Name"},"default_scenario_display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Default Scenario Display Name"},"auto_switch_scenario":{"type":"boolean","title":"Auto Switch Scenario"},"copilot_enabled":{"type":"boolean","title":"Copilot Enabled"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["user_id","auto_switch_scenario","copilot_enabled","created_at","updated_at"],"title":"UserSettingsRead"},"UserSettingsUpdate":{"properties":{"default_scenario_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Default Scenario Id","description":"Default production scenario for new calls. Null clears the setting."},"auto_switch_scenario":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Switch Scenario","description":"Whether post-call analysis may switch to the AI-detected scenario."}},"type":"object","title":"UserSettingsUpdate"},"UserUpdate":{"properties":{"password":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Password"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"is_superuser":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Superuser"},"is_verified":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Verified"},"first_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"First Name"},"last_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Name"}},"type":"object","title":"UserUpdate"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VoiceCatalogItem":{"properties":{"id":{"type":"string","title":"Id","description":"Provider-qualified value stored on a scenario"},"provider":{"type":"string","enum":["cartesia","deepgram"],"title":"Provider"},"name":{"type":"string","title":"Name","description":"Provider display name, e.g. 'Arlo - Service Specialist'"},"description":{"type":"string","title":"Description","description":"Provider description of the voice","default":""},"gender":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gender","description":"masculine | feminine | gender_neutral"},"language":{"type":"string","title":"Language","description":"ISO 639-1 language code","default":""},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country","description":"ISO 3166-1 alpha-2 code"},"is_pro":{"type":"boolean","title":"Is Pro","description":"Whether this is a pro voice","default":false},"is_runtime_default":{"type":"boolean","title":"Is Runtime Default","description":"True for the voice a scenario falls back to when it names none.","default":false}},"type":"object","required":["id","provider","name"],"title":"VoiceCatalogItem","description":"One provider-qualified voice the autonomous agent can speak with."},"VoiceCatalogResponse":{"properties":{"voices":{"items":{"$ref":"#/components/schemas/VoiceCatalogItem"},"type":"array","title":"Voices"},"models":{"items":{"$ref":"#/components/schemas/VoiceModelCatalogItem"},"type":"array","title":"Models"},"has_more":{"type":"boolean","title":"Has More","description":"True when the filter matched more voices than one page holds — narrow it with search rather than assuming this is everything."},"default_voice_id":{"type":"string","title":"Default Voice Id","description":"The voice used when a scenario configures none."},"default_model_id":{"type":"string","title":"Default Model Id","description":"The Cartesia model used when a scenario configures none."},"unavailable_providers":{"items":{"type":"string","enum":["cartesia","deepgram"]},"type":"array","title":"Unavailable Providers","description":"Configured providers omitted because their catalog failed."}},"type":"object","required":["voices","models","has_more","default_voice_id","default_model_id"],"title":"VoiceCatalogResponse","description":"The configured providers' voices an operator can choose between."},"VoiceModelCatalogItem":{"properties":{"id":{"type":"string","title":"Id"},"provider":{"type":"string","const":"cartesia","title":"Provider"},"name":{"type":"string","title":"Name"},"status":{"type":"string","enum":["stable","beta"],"title":"Status"},"description":{"type":"string","title":"Description"},"is_runtime_default":{"type":"boolean","title":"Is Runtime Default"}},"type":"object","required":["id","provider","name","status","description","is_runtime_default"],"title":"VoiceModelCatalogItem","description":"One TTS model an operator can select independently of the voice."},"VolumeLine":{"properties":{"dials":{"type":"integer","title":"Dials"},"human_answered":{"type":"integer","title":"Human Answered"},"engaged":{"type":"integer","title":"Engaged"}},"type":"object","required":["dials","human_answered","engaged"],"title":"VolumeLine","description":"Funnel context — one line, not a dialer dashboard (that's /performance)."},"WorkflowDisposition":{"type":"string","enum":["none","callback_scheduled","transferred","human_followup_required","do_not_contact"],"title":"WorkflowDisposition","description":"Deterministic action the autonomous workflow took before finalizing.\n\n``NONE`` is explicit for finalized autonomous calls with no special\nhandoff/follow-up action. NULL means the dimension does not apply (human\ncopilot, uploaded, or legacy calls), rather than overloading NULL with two\nmeanings."},"fastapi___compat__v2__Body_auth-auth_cookie__login":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"^password$"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","format":"password","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"format":"password","title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_auth-auth:cookie.login"},"fastapi___compat__v2__Body_auth-auth_jwt__login":{"properties":{"grant_type":{"anyOf":[{"type":"string","pattern":"^password$"},{"type":"null"}],"title":"Grant Type"},"username":{"type":"string","title":"Username"},"password":{"type":"string","format":"password","title":"Password"},"scope":{"type":"string","title":"Scope","default":""},"client_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Id"},"client_secret":{"anyOf":[{"type":"string"},{"type":"null"}],"format":"password","title":"Client Secret"}},"type":"object","required":["username","password"],"title":"Body_auth-auth:jwt.login"},"src__calls__schemas__AutonomousVoiceLatencyByKind":{"properties":{"plain":{"$ref":"#/components/schemas/LatencyLegSummary"},"tool":{"$ref":"#/components/schemas/LatencyLegSummary"},"runtime":{"$ref":"#/components/schemas/LatencyLegSummary"}},"type":"object","required":["plain","tool","runtime"],"title":"AutonomousVoiceLatencyByKind","description":"End-to-end response time split by what answered the caller."},"src__calls__schemas__AutonomousVoiceLatencyLegs":{"properties":{"endpointing":{"$ref":"#/components/schemas/LatencyLegSummary"},"turn_release":{"anyOf":[{"$ref":"#/components/schemas/LatencyLegSummary"},{"type":"null"}]},"llm_ttft":{"$ref":"#/components/schemas/LatencyLegSummary"},"tool":{"anyOf":[{"$ref":"#/components/schemas/LatencyLegSummary"},{"type":"null"}]},"speech_release":{"anyOf":[{"$ref":"#/components/schemas/LatencyLegSummary"},{"type":"null"}]},"tts_ttfb":{"$ref":"#/components/schemas/LatencyLegSummary"},"transport":{"$ref":"#/components/schemas/LatencyLegSummary"}},"type":"object","required":["endpointing","llm_ttft","tts_ttfb","transport"],"title":"AutonomousVoiceLatencyLegs","description":"Stages of one spoken reply, in order; on a turn they sum to its total.\n\nThe stages added after the first calls were recorded are optional, so the\nsummaries stored on those calls still load."},"src__performance__schemas__AutonomousVoiceLatencyByKind":{"properties":{"plain":{"$ref":"#/components/schemas/LatencyPercentiles","description":"The model answered directly"},"tool":{"$ref":"#/components/schemas/LatencyPercentiles","description":"The model called a tool first"},"runtime":{"$ref":"#/components/schemas/LatencyPercentiles","description":"The runtime spoke a line of its own, with no model reply"}},"type":"object","required":["plain","tool","runtime"],"title":"AutonomousVoiceLatencyByKind","description":"End-to-end response time split by what answered the caller."},"src__performance__schemas__AutonomousVoiceLatencyLegs":{"properties":{"endpointing":{"$ref":"#/components/schemas/LatencyPercentiles"},"turn_release":{"$ref":"#/components/schemas/LatencyPercentiles"},"llm_ttft":{"$ref":"#/components/schemas/LatencyPercentiles"},"tool":{"$ref":"#/components/schemas/LatencyPercentiles"},"speech_release":{"$ref":"#/components/schemas/LatencyPercentiles"},"tts_ttfb":{"$ref":"#/components/schemas/LatencyPercentiles"},"transport":{"$ref":"#/components/schemas/LatencyPercentiles"}},"type":"object","required":["endpointing","turn_release","llm_ttft","tool","speech_release","tts_ttfb","transport"],"title":"AutonomousVoiceLatencyLegs","description":"Autonomous response waterfall stages, in the order a reply passes them.\n\nOn a single turn the stages sum to its end-to-end time. The tool stage\nonly exists on turns that called one."}},"securitySchemes":{"OAuth2PasswordBearer":{"type":"oauth2","flows":{"password":{"scopes":{},"tokenUrl":"auth/bearer/login"}}},"APIKeyCookie":{"type":"apiKey","in":"cookie","name":"access_token"}}}}