{"components":{"schemas":{"ContentCreationCoverageRequest":{"properties":{"content":{"title":"Content","type":"string"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"gemini/gemini-2.5-flash","title":"Model"},"pull_through_priorities":{"default":[],"items":{"$ref":"#/components/schemas/ContentCreationPullThroughPriority"},"title":"Pull Through Priorities","type":"array"}},"required":["content"],"title":"ContentCreationCoverageRequest","type":"object"},"ContentCreationDraftRequest":{"properties":{"audience_persona_ids":{"default":[],"items":{"type":"string"},"title":"Audience Persona Ids","type":"array"},"content":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Content"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"text","title":"Content Type"},"content_type_value":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Content Type Value"},"draft_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Draft Id"},"knowledgebase_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Knowledgebase Id"},"project_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Project Id"},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Prompt"},"pull_through_priorities":{"default":[],"items":{"$ref":"#/components/schemas/ContentCreationPullThroughPriority"},"title":"Pull Through Priorities","type":"array"},"source_document_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source Document Id"},"source_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"freeform","title":"Source Mode"},"source_url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source Url"},"test_history":{"anyOf":[{"items":{"additionalProperties":true,"type":"object"},"type":"array"},{"type":"null"}],"default":null,"title":"Test History"},"themes":{"default":[],"items":{"type":"string"},"title":"Themes","type":"array"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Title"},"tone_persona_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Id"},"voice_profile_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Profile Id"}},"title":"ContentCreationDraftRequest","type":"object"},"ContentCreationEnhanceRequest":{"properties":{"audiences":{"default":[],"items":{"type":"string"},"title":"Audiences","type":"array"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"auto","title":"Content Type"},"content_type_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Content Type Label"},"current_draft":{"title":"Current Draft","type":"string"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"gemini/gemini-2.5-flash","title":"Model"},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Prompt"},"themes":{"default":[],"items":{"type":"string"},"title":"Themes","type":"array"},"tone_persona_helper":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Helper"},"tone_persona_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Label"},"unmet_priorities":{"default":[],"items":{"$ref":"#/components/schemas/ContentCreationPullThroughPriority"},"title":"Unmet Priorities","type":"array"}},"required":["current_draft"],"title":"ContentCreationEnhanceRequest","type":"object"},"ContentCreationExportRequest":{"properties":{"content_html":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"","title":"Content Html"},"content_text":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"","title":"Content Text"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Content Type"},"format":{"default":"pdf","title":"Format","type":"string"},"themes":{"default":[],"items":{"type":"string"},"title":"Themes","type":"array"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"Untitled","title":"Title"},"tone_persona":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona"}},"title":"ContentCreationExportRequest","type":"object"},"ContentCreationGenerateRequest":{"properties":{"audiences":{"default":[],"items":{"type":"string"},"title":"Audiences","type":"array"},"content_type":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"auto","title":"Content Type"},"content_type_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Content Type Label"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"gemini/gemini-2.5-flash","title":"Model"},"preferred_title_length":{"anyOf":[{"type":"integer"},{"type":"null"}],"default":null,"title":"Preferred Title Length"},"prompt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Prompt"},"pull_through_priorities":{"default":[],"items":{"$ref":"#/components/schemas/ContentCreationPullThroughPriority"},"title":"Pull Through Priorities","type":"array"},"source_document_excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source Document Excerpt"},"source_document_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source Document Id"},"source_document_title":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Source Document Title"},"source_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"freeform","title":"Source Mode"},"template_instructions":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Template Instructions"},"template_reference_excerpt":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Template Reference Excerpt"},"themes":{"default":[],"items":{"type":"string"},"title":"Themes","type":"array"},"tone_persona_helper":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Helper"},"tone_persona_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Id"},"tone_persona_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Label"},"voice_profile_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Voice Profile Id"}},"title":"ContentCreationGenerateRequest","type":"object"},"ContentCreationPullThroughPriority":{"properties":{"from_kb":{"anyOf":[{"type":"boolean"},{"type":"null"}],"default":false,"title":"From Kb"},"level":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"must","title":"Level"},"text":{"title":"Text","type":"string"}},"required":["text"],"title":"ContentCreationPullThroughPriority","type":"object"},"ContentCreationRewritePhrasesRequest":{"properties":{"content_type_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Content Type Label"},"full_draft":{"title":"Full Draft","type":"string"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"gemini/gemini-2.5-flash","title":"Model"},"segments":{"default":[],"items":{"$ref":"#/components/schemas/ContentCreationSegmentRewriteItem"},"title":"Segments","type":"array"},"tone_persona_helper":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Helper"},"tone_persona_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Label"}},"required":["full_draft"],"title":"ContentCreationRewritePhrasesRequest","type":"object"},"ContentCreationRewriteSegmentsRequest":{"properties":{"content_type_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Content Type Label"},"full_draft":{"title":"Full Draft","type":"string"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"gemini/gemini-2.5-flash","title":"Model"},"segments":{"default":[],"items":{"$ref":"#/components/schemas/ContentCreationSegmentRewriteItem"},"title":"Segments","type":"array"},"tone_persona_helper":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Helper"},"tone_persona_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Label"}},"required":["full_draft"],"title":"ContentCreationRewriteSegmentsRequest","type":"object"},"ContentCreationSegmentRewriteItem":{"properties":{"actions":{"default":[],"items":{"type":"string"},"title":"Actions","type":"array"},"grade":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Grade"},"persona_name":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Persona Name"},"risks":{"default":[],"items":{"type":"string"},"title":"Risks","type":"array"},"segment_text":{"title":"Segment Text","type":"string"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Summary"}},"required":["segment_text"],"title":"ContentCreationSegmentRewriteItem","type":"object"},"CreateDocumentRequest":{"properties":{"content":{"title":"Content","type":"string"},"content_type":{"default":"text","title":"Content Type","type":"string"},"media_provenance":{"default":null,"title":"Media Provenance","type":"string"},"source_url":{"default":null,"title":"Source Url","type":"string"},"tags":{"default":[],"items":{"type":"string"},"title":"Tags","type":"array"},"title":{"title":"Title","type":"string"}},"required":["title","content"],"title":"CreateDocumentRequest","type":"object"},"DeAIifyRequest":{"properties":{"content_type_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Content Type Label"},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"default":"gemini/gemini-2.5-flash","title":"Model"},"selection_only":{"default":false,"title":"Selection Only","type":"boolean"},"text":{"title":"Text","type":"string"},"tone_persona_helper":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Helper"},"tone_persona_label":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Tone Persona Label"}},"required":["text"],"title":"DeAIifyRequest","type":"object"},"ExecuteWorkspaceSignalsRequest":{"properties":{"document_id":{"title":"Document Id","type":"string"},"user_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"User Id"},"workspace_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Workspace Id"}},"required":["document_id"],"title":"ExecuteWorkspaceSignalsRequest","type":"object"},"IngestRequest":{"properties":{"audio_url":{"default":null,"title":"Audio Url","type":"string"},"content_type":{"title":"Content Type","type":"string"},"media_provenance":{"default":null,"title":"Media Provenance","type":"string"},"source_url":{"title":"Source Url","type":"string"}},"required":["source_url","content_type"],"title":"IngestRequest","type":"object"},"QueryRequest":{"properties":{"doc_id":{"title":"Doc Id","type":"string"},"model":{"default":"gpt-3.5-turbo","title":"Model","type":"string"},"query_template":{"title":"Query Template","type":"string"}},"required":["query_template","doc_id"],"title":"QueryRequest","type":"object"},"TextQualityCheckRequest":{"properties":{"include_ai_detection":{"default":true,"title":"Include Ai Detection","type":"boolean"},"include_grammar":{"default":true,"title":"Include Grammar","type":"boolean"},"include_spelling":{"default":true,"title":"Include Spelling","type":"boolean"},"session_id":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Session Id"},"text":{"title":"Text","type":"string"}},"required":["text"],"title":"TextQualityCheckRequest","type":"object"},"TextQualityFeedbackRequest":{"properties":{"edit_id":{"title":"Edit Id","type":"string"}},"required":["edit_id"],"title":"TextQualityFeedbackRequest","type":"object"},"ValidationErrorModel":{"properties":{"ctx":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"default":null,"description":"An optional object which contains values required to render the error message.","title":"Error context"},"input":{"description":"The input provided for validation.","title":"Input"},"loc":{"description":"The error's location as a list.","items":{},"title":"Location","type":"array"},"msg":{"description":"A human readable explanation of the error.","title":"Message","type":"string"},"type":{"description":"A computer-readable identifier of the error type.","title":"Error Type","type":"string"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"description":"The URL to further information about the error.","title":"URL"}},"required":["type","loc","msg","input"],"title":"ValidationErrorModel","type":"object"}},"securitySchemes":{"ApiKeyAuth":{"description":"API key for authentication","in":"header","name":"X-API-Key","type":"apiKey"}}},"info":{"description":"Kumkuat - Document Management and AI Analysis Platform","title":"Kumkuat API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/api/chat/sessions/{session_id}/attachments":{"post":{"description":"Upload a file into an audience chat session (KUM-499).<br/><br/>The file becomes a workspace document that is private to the uploader<br/>(KUM-433 `private_to_user` tag) and is linked to the session via<br/>`chat_sessions.context.attachments`, so the persona can ground replies<br/>on it without the file surfacing in shared workspace views.","operationId":"upload_chat_session_attachment_api_chat_sessions__session_id__attachments_post","parameters":[{"in":"path","name":"session_id","required":true,"schema":{"title":"Session Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Attach a file to a chat session","tags":["documents"]}},"/api/chat/sessions/{session_id}/attachments/{document_id}":{"delete":{"description":"Drop a file from a chat session's attachments (KUM-499).<br/><br/>With `?delete_document=true`, the underlying private document is also<br/>deleted when the requesting user owns it.","operationId":"remove_chat_session_attachment_api_chat_sessions__session_id__attachments__document_id__delete","parameters":[{"in":"path","name":"session_id","required":true,"schema":{"title":"Session Id","type":"string"}},{"in":"path","name":"document_id","required":true,"schema":{"title":"Document Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Remove a file from a chat session","tags":["documents"]}},"/api/public/ensure-user-workspace":{"post":{"operationId":"ensure_user_workspace_api_public_ensure_user_workspace_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Optimized endpoint that creates user, workspace, and API key in a single transaction","tags":["default"]}},"/api/public/ensure-workspace-key":{"post":{"operationId":"ensure_workspace_key_api_public_ensure_workspace_key_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Ensure a workspace exists and return an API key","tags":["default"]}},"/api/public/get-user-api-key":{"post":{"operationId":"get_user_api_key_api_public_get_user_api_key_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get a user's API key by Firebase UID or email (alias for /api/public/user/api-key)","tags":["default"]}},"/api/public/get-user-workspaces":{"post":{"operationId":"get_user_workspaces_api_public_get_user_workspaces_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get all workspaces for a user by Firebase UID or email","tags":["default"]}},"/api/public/get-workspace-api-key":{"post":{"operationId":"get_workspace_api_key_api_public_get_workspace_api_key_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get API key for a specific workspace and user","tags":["default"]}},"/api/public/sso/discover":{"get":{"description":"<br/>Unauthenticated by design \u2014 it runs before anyone is signed in. It reveals<br/>only what every SSO login page reveals (that a domain has SSO and which<br/>provider id to start), never the workspace. See api/src/sso.py.","operationId":"sso_discover_api_public_sso_discover_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Login-page lookup: does this email's domain (or this slug) use single sign-on?","tags":["default"]}},"/api/public/user/api-key":{"post":{"operationId":"get_user_api_key_impl_api_public_user_api_key_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get a user's API key by Firebase UID or email","tags":["default"]}},"/api/v1/alerts/autocomplete":{"get":{"description":"Return audiences, companies, and commands for the alert composer autocomplete.<br/><br/>Query params:<br/>- q: optional search filter (case-insensitive substring match)<br/>- type: optional filter \u2014 'audience', 'company', or 'command'","operationId":"alerts_autocomplete_api_v1_alerts_autocomplete_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Workspace-scoped autocomplete for alert composer","tags":["alerts"]}},"/api/v1/audience-groups":{"get":{"description":"Return the workspace's audience groups with custom sort order.","operationId":"get_audience_groups_api_v1_audience_groups_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get audience group ordering","tags":["personas"]},"post":{"description":"Append a single audience category without touching the rest of the list.<br/><br/>Body: ``{ \"name\": \"...\", \"display_name\": \"...\"? }`` \u2192 201 ``{\"group\": {...}}``.<br/><br/>The bulk PUT above replaces the whole list (rows absent from its payload are<br/>deleted), which is the wrong tool for \"add one\" from a member-facing surface<br/>such as the Audience Library rail \u2014 a stale client would erase categories it<br/>never saw. This route only ever inserts; a name that already exists<br/>(case-insensitive) is a 409 carrying the existing row.","operationId":"add_audience_group_api_v1_audience_groups_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Add one audience category","tags":["personas"]},"put":{"description":"Bulk update audience groups (sort order + optional rename).<br/><br/>Body: ``{ \"groups\": [ { \"name\": \"...\", \"sort_order\": 0, \"display_name\": \"...\" }, ... ] }``","operationId":"update_audience_groups_api_v1_audience_groups_put","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update audience group ordering","tags":["personas"]}},"/api/v1/audience-summaries":{"get":{"description":"Return a synthesized audience-level summary for a persona category.<br/>Aggregates persona reaction insights across recent documents and uses an LLM<br/>to produce an overall grade, themes, actions, and risks.<br/>Set force_refresh=true to bypass the cache and regenerate.","operationId":"get_or_generate_audience_category_summary_api_v1_audience_summaries_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get or generate audience category summary","tags":["personas"]}},"/api/v1/audience-summaries/grades":{"get":{"description":"Return cached grade + trend for all (or specified) audience categories in one call.<br/>Reads from cache only \u2014 does NOT trigger LLM generation.<br/>Response: { grades: { \"Regulators\": { grade, trend, is_stale } | null, ... } }","operationId":"get_audience_category_grades_api_v1_audience_summaries_grades_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get cached grades for multiple audience categories","tags":["personas"]}},"/api/v1/audience-summaries/refresh":{"post":{"description":"Queue a background job to proactively regenerate all audience category<br/>summaries for the workspace.  This keeps the audience overview page fast<br/>by ensuring summaries are pre-computed rather than generated on demand.<br/><br/>Parameters (JSON body):<br/>- force_refresh: bool (default false) \u2013 regenerate even fresh summaries<br/>- days: int (default 30) \u2013 reaction lookback window<br/>- model: str (optional) \u2013 LLM model override<br/>- company_tag: str (optional) \u2013 scope to a specific company<br/>- pillar: str (optional) \u2013 scope to a specific narrative pillar","operationId":"queue_audience_cache_refresh_api_v1_audience_summaries_refresh_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Queue audience cache refresh job","tags":["personas"]}},"/api/v1/auth/keys":{"get":{"operationId":"list_api_keys_api_v1_auth_keys_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List API keys","tags":["default"]},"post":{"operationId":"create_api_key_api_v1_auth_keys_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create API key","tags":["default"]}},"/api/v1/auth/keys/{key_id}":{"delete":{"operationId":"revoke_api_key_api_v1_auth_keys__key_id__delete","parameters":[{"in":"path","name":"key_id","required":true,"schema":{"title":"Key Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Revoke API key","tags":["default"]}},"/api/v1/auth/keys/{key_id}/rotate":{"post":{"description":"Revoke an existing key and mint a replacement with the same name and workspace binding.<br/><br/>Returns the new key value (shown exactly once) and the new key metadata.<br/>The old key is deactivated atomically before the new one is returned.","operationId":"rotate_api_key_api_v1_auth_keys__key_id__rotate_post","parameters":[{"in":"path","name":"key_id","required":true,"schema":{"title":"Key Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Rotate API key","tags":["default"]}},"/api/v1/auto-tag-aliases":{"get":{"description":"Get alias normalization rules visible in the current workspace.","operationId":"get_auto_tag_aliases_api_v1_auto_tag_aliases_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get auto tag alias rules","tags":["auto_tags"]},"post":{"description":"Create an alias normalization rule for an auto tag.","operationId":"create_auto_tag_alias_api_v1_auto_tag_aliases_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create auto tag alias rule","tags":["auto_tags"]}},"/api/v1/auto-tag-aliases/apply-normalization":{"post":{"description":"Normalize existing applied auto tag values using current alias rules.","operationId":"apply_auto_tag_alias_normalization_api_v1_auto_tag_aliases_apply_normalization_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Apply alias normalization to existing applied tags","tags":["auto_tags"]}},"/api/v1/auto-tag-aliases/suggestions":{"get":{"description":"Get extracted value suggestions to speed up alias rule creation.","operationId":"get_auto_tag_alias_suggestions_api_v1_auto_tag_aliases_suggestions_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get alias suggestions from extracted values","tags":["auto_tags"]}},"/api/v1/auto-tag-aliases/{id}":{"delete":{"description":"Delete an auto tag alias rule.","operationId":"delete_auto_tag_alias_api_v1_auto_tag_aliases__id__delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"title":"Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete auto tag alias rule","tags":["auto_tags"]},"put":{"description":"Update an existing auto tag alias rule.","operationId":"update_auto_tag_alias_api_v1_auto_tag_aliases__id__put","parameters":[{"in":"path","name":"id","required":true,"schema":{"title":"Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update auto tag alias rule","tags":["auto_tags"]}},"/api/v1/auto-tags":{"get":{"description":"Get all auto tags visible in the current workspace","operationId":"get_auto_tags_api_v1_auto_tags_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get all auto tags","tags":["auto_tags"]},"post":{"description":"Create a new auto tag","operationId":"create_auto_tag_api_v1_auto_tags_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create auto tag","tags":["auto_tags"]}},"/api/v1/auto-tags/ensure":{"post":{"description":"Ensure all documents in the workspace have auto tags generated","operationId":"ensure_auto_tags_api_v1_auto_tags_ensure_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Ensure auto tags for all documents","tags":["default"]}},"/api/v1/auto-tags/generate-draft":{"post":{"description":"Generate auto tag fields from partial inputs.<br/>Name is required. By default, only missing fields are generated.","operationId":"generate_auto_tag_draft_api_v1_auto_tags_generate_draft_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate auto tag draft fields","tags":["auto_tags"]}},"/api/v1/auto-tags/status":{"get":{"description":"Get the current auto tag status for the workspace","operationId":"get_auto_tag_status_api_v1_auto_tags_status_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get auto tag status for workspace","tags":["default"]}},"/api/v1/auto-tags/test":{"post":{"description":"Test an auto tag against text input or an onboarded document without saving results","operationId":"test_auto_tag_api_v1_auto_tags_test_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Test auto tag extraction","tags":["auto_tags"]}},"/api/v1/auto-tags/{id}":{"delete":{"description":"Delete an auto tag","operationId":"delete_auto_tag_api_v1_auto_tags__id__delete","parameters":[{"in":"path","name":"id","required":true,"schema":{"title":"Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete auto tag","tags":["auto_tags"]},"get":{"description":"Get a specific auto tag visible in the current workspace","operationId":"get_auto_tag_by_id_api_v1_auto_tags__id__get","parameters":[{"in":"path","name":"id","required":true,"schema":{"title":"Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get auto tag by ID","tags":["auto_tags"]},"put":{"description":"Update an existing auto tag","operationId":"update_auto_tag_api_v1_auto_tags__id__put","parameters":[{"in":"path","name":"id","required":true,"schema":{"title":"Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update auto tag","tags":["auto_tags"]}},"/api/v1/communications":{"get":{"description":"Get documents for communications page with auto tags","operationId":"get_communications_api_v1_communications_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get communications with auto tags","tags":["documents"]}},"/api/v1/communications/tag-filters":{"get":{"description":"Get available tag-value filter options for the Communications page.","operationId":"get_communications_tag_filters_api_v1_communications_tag_filters_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get Communications tag-value filters","tags":["documents"]}},"/api/v1/content-creation/analyze-pull-through-coverage":{"post":{"description":"Grade each pull-through priority as covered / partial / missing in the given draft.","operationId":"analyze_pull_through_coverage_api_v1_content_creation_analyze_pull_through_coverage_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCreationCoverageRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Score each pull-through priority against a draft","tags":["documents"]}},"/api/v1/content-creation/check-quality":{"post":{"description":"Run grammar, spelling, and AI-detection checks via the configured text-quality provider.","operationId":"check_content_quality_api_v1_content_creation_check_quality_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextQualityCheckRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Check text quality (grammar, spelling, AI detection)","tags":["documents"]}},"/api/v1/content-creation/check-quality/accept":{"post":{"description":"Forward an accept signal to the text-quality provider for learning.","operationId":"accept_quality_edit_api_v1_content_creation_check_quality_accept_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextQualityFeedbackRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Accept a text-quality edit suggestion","tags":["documents"]}},"/api/v1/content-creation/check-quality/reject":{"post":{"description":"Forward a reject signal to the text-quality provider for learning.","operationId":"reject_quality_edit_api_v1_content_creation_check_quality_reject_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TextQualityFeedbackRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Reject a text-quality edit suggestion","tags":["documents"]}},"/api/v1/content-creation/deaiify":{"post":{"description":"LLM-powered analysis of AI-detection signals with span-anchored edit suggestions.","operationId":"deaiify_content_api_v1_content_creation_deaiify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeAIifyRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Suggest edits to reduce AI-detection signals in content","tags":["documents"]}},"/api/v1/content-creation/documents":{"get":{"description":"List content-creation drafts from one or more knowledgebases.<br/><br/>Query params:<br/>    kb_ids  \u2013 comma-separated knowledgebase IDs to fetch from (required)<br/>    limit   \u2013 max documents to return (default 50, max 200)","operationId":"list_content_creation_documents_api_v1_content_creation_documents_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List content documents across multiple knowledgebases","tags":["documents"]}},"/api/v1/content-creation/drafts":{"get":{"description":"List recent content drafts stored in the content-drafts knowledgebase.","operationId":"list_content_creation_drafts_api_v1_content_creation_drafts_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List content creation drafts","tags":["documents"]},"post":{"description":"Save a draft in the content-drafts knowledgebase using document storage.","operationId":"save_content_creation_draft_api_v1_content_creation_drafts_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCreationDraftRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create or update content creation draft","tags":["documents"]}},"/api/v1/content-creation/drafts/bulk-delete":{"post":{"description":"Soft-delete multiple content creation drafts by ID.","operationId":"bulk_delete_content_creation_drafts_api_v1_content_creation_drafts_bulk_delete_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Bulk delete content creation drafts","tags":["documents"]}},"/api/v1/content-creation/drafts/{draft_id}":{"delete":{"description":"Soft-delete a content creation draft by ID.","operationId":"delete_content_creation_draft_api_v1_content_creation_drafts__draft_id__delete","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete a content creation draft","tags":["documents"]},"get":{"description":"Fetch a single content draft by document ID.","operationId":"get_content_creation_draft_api_v1_content_creation_drafts__draft_id__get","parameters":[{"in":"path","name":"draft_id","required":true,"schema":{"title":"Draft Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get content creation draft","tags":["documents"]}},"/api/v1/content-creation/enhance-pull-through":{"post":{"description":"Re-prompt the generator with unmet priorities elevated to rewrite the current draft.","operationId":"enhance_pull_through_draft_api_v1_content_creation_enhance_pull_through_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCreationEnhanceRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Rewrite a draft so unmet pull-through priorities are delivered","tags":["documents"]}},"/api/v1/content-creation/export":{"post":{"description":"Export content creation draft to the requested format (pdf, docx, txt).","operationId":"export_content_creation_draft_api_v1_content_creation_export_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCreationExportRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Export content as PDF, DOCX, or TXT","tags":["documents"]}},"/api/v1/content-creation/generate":{"post":{"description":"Generate publication-ready content text from /content workspace context.","operationId":"generate_content_creation_draft_api_v1_content_creation_generate_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCreationGenerateRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate content draft text","tags":["documents"]}},"/api/v1/content-creation/knowledgebases":{"get":{"description":"Return all KBs visible to the user plus ensure the two default ones exist.","operationId":"list_content_creation_knowledgebases_api_v1_content_creation_knowledgebases_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List knowledgebases available for content drafts","tags":["documents"]}},"/api/v1/content-creation/rewrite-phrases":{"post":{"description":"LLM-powered phrase-level edit suggestions based on audience test feedback.","operationId":"rewrite_content_phrases_api_v1_content_creation_rewrite_phrases_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCreationRewritePhrasesRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Phrase-level edit suggestions driven by audience feedback","tags":["documents"]}},"/api/v1/content-creation/rewrite-segments":{"post":{"description":"LLM-powered rewrite of individual segments based on audience test feedback.","operationId":"rewrite_content_segments_api_v1_content_creation_rewrite_segments_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContentCreationRewriteSegmentsRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Rewrite specific draft segments to address audience feedback","tags":["documents"]}},"/api/v1/content-creation/source-documents":{"get":{"description":"List workspace documents tagged for /content source generation.","operationId":"list_content_creation_source_documents_api_v1_content_creation_source_documents_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List content source documents","tags":["documents"]}},"/api/v1/content-creation/source-documents/upload":{"post":{"description":"Upload a source document for /content generation using the standard ingestion pipeline.","operationId":"upload_content_creation_source_document_api_v1_content_creation_source_documents_upload_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Upload content source document","tags":["documents"]}},"/api/v1/content-creation/source-documents/{document_id}/attach":{"post":{"description":"Tag an existing workspace document for /content source generation.","operationId":"attach_content_creation_source_document_api_v1_content_creation_source_documents__document_id__attach_post","parameters":[{"in":"path","name":"document_id","required":true,"schema":{"title":"Document Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Attach existing document as content source","tags":["documents"]}},"/api/v1/documents":{"get":{"description":"Get all documents with pagination, filtering, and sorting","operationId":"get_all_documents_api_api_v1_documents_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get all documents","tags":["documents"]},"post":{"description":"Create a new document (admin/owner only)","operationId":"create_document_api_v1_documents_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDocumentRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create a new document","tags":["documents"]}},"/api/v1/documents/count":{"get":{"description":"Get total document count","operationId":"get_documents_count_api_api_v1_documents_count_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get document count","tags":["documents"]}},"/api/v1/documents/ingest":{"post":{"description":"Ingest a document from URL","operationId":"ingest_document_api_v1_documents_ingest_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Ingest a document","tags":["documents"]}},"/api/v1/documents/query":{"post":{"description":"Query a document using a template","operationId":"query_document_api_v1_documents_query_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QueryRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Query a document","tags":["documents"]}},"/api/v1/documents/upload":{"post":{"description":"Upload and ingest a file with document enrichment and auto tags","operationId":"upload_document_api_v1_documents_upload_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Upload and ingest a file","tags":["documents"]}},"/api/v1/documents/{doc_id}":{"delete":{"description":"Delete a document by ID","operationId":"delete_document_api_v1_documents__doc_id__delete","parameters":[{"in":"path","name":"doc_id","required":true,"schema":{"title":"Doc Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete a document","tags":["documents"]},"get":{"description":"Get a document by ID","operationId":"get_document_api_v1_documents__doc_id__get","parameters":[{"in":"path","name":"doc_id","required":true,"schema":{"title":"Doc Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get a specific document","tags":["documents"]},"patch":{"description":"Update document fields (e.g. extracted_date, title).","operationId":"update_document_api_v1_documents__doc_id__patch","parameters":[{"in":"path","name":"doc_id","required":true,"schema":{"title":"Doc Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update a document","tags":["documents"]}},"/api/v1/documents/{doc_id}/auto-tags":{"get":{"description":"Get all auto tags applied to a specific document","operationId":"get_document_auto_tags_api_v1_documents__doc_id__auto_tags_get","parameters":[{"in":"path","name":"doc_id","required":true,"schema":{"title":"Doc Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get auto tags for a document","tags":["documents"]}},"/api/v1/documents/{doc_id}/auto-tags/{applied_tag_id}":{"put":{"description":"Update the extracted value of an applied auto tag for a specific document","operationId":"update_document_auto_tag_api_v1_documents__doc_id__auto_tags__applied_tag_id__put","parameters":[{"in":"path","name":"doc_id","required":true,"schema":{"title":"Doc Id","type":"string"}},{"in":"path","name":"applied_tag_id","required":true,"schema":{"title":"Applied Tag Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update an applied auto tag value","tags":["documents"]}},"/api/v1/documents/{doc_id}/content":{"get":{"description":"Stream the stored file for a document, authorized per request.<br/><br/>This is the authenticated replacement for handing out public bucket URLs<br/>(KUM-1315): the objects become private, and callers read them through here<br/>so that access is re-checked every time rather than living forever in a URL.","operationId":"get_document_content_api_v1_documents__doc_id__content_get","parameters":[{"in":"path","name":"doc_id","required":true,"schema":{"title":"Doc Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Download a document's stored file","tags":["documents"]}},"/api/v1/documents/{doc_id}/retag":{"post":{"description":"Retag a document by rerunning all auto tags","operationId":"retag_document_api_v1_documents__doc_id__retag_post","parameters":[{"in":"path","name":"doc_id","required":true,"schema":{"title":"Doc Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Retag a document","tags":["auto_tags"]}},"/api/v1/executives-for-theme":{"post":{"description":"Get available executives for selected theme","operationId":"get_executives_for_theme_api_v1_executives_for_theme_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get available executives for selected theme","tags":["documents"]}},"/api/v1/executives/voice":{"put":{"description":"The per-executive voice toggle (KUM-1506). Body:<br/>``{\"executive\": \"<name>\", \"enabled\": true|false}``.<br/><br/>Enabling creates the voice persona when missing and auto-tunes it from the<br/>executive's tracked statements (one LLM call \u2014 the response can take a few<br/>seconds on first enable). Disabling only clears ``include_in_voice_list``;<br/>the tuned persona is kept so re-enabling is instant. The response reports<br/>values **read back** from the persona, not the request echo, because<br/>``update_persona_template`` silently drops unregistered keys.","operationId":"set_executive_voice_endpoint_api_v1_executives_voice_put","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Include or exclude an executive's voice in content creation","tags":["personas"]}},"/api/v1/executives/voices":{"get":{"description":"State of every executive voice persona in the workspace (KUM-1506).<br/><br/>Also arms the lazy CEO auto-add: loading the executives page is a natural<br/>moment to make sure the CEO's voice exists, and the kick is throttled and<br/>runs off-request, so this read stays cheap.","operationId":"list_executive_voices_endpoint_api_v1_executives_voices_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Executive content-creation voices for this workspace","tags":["personas"]}},"/api/v1/executives/{executive_name}":{"get":{"description":"Get detailed information about a specific executive","operationId":"get_executive_details_api_v1_executives__executive_name__get","parameters":[{"in":"path","name":"executive_name","required":true,"schema":{"title":"Executive Name","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get detailed information about a specific executive","tags":["documents"]}},"/api/v1/extract-text":{"post":{"description":"Extract text from an uploaded file and return it. Nothing is saved.<br/>Supports PDF, DOCX, PPTX, and text-based formats.","operationId":"extract_text_from_upload_api_v1_extract_text_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Extract text from an uploaded file without saving","tags":["documents"]}},"/api/v1/ingest/auto-detect":{"post":{"description":"Auto-detect content type and ingest document","operationId":"auto_detect_and_ingest_api_v1_ingest_auto_detect_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Auto-detect content type and ingest","tags":["documents"]}},"/api/v1/ingest/youtube":{"post":{"description":"Ingest YouTube video and extract transcript","operationId":"ingest_youtube_video_api_v1_ingest_youtube_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Ingest YouTube video","tags":["documents"]}},"/api/v1/insights":{"get":{"description":"Get AI comparative analysis for selected executives or companies on a specific theme","operationId":"get_insights_api_v1_insights_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get AI comparative analysis for executives or companies on a theme","tags":["documents"]},"post":{"description":"POST variant of insights query for larger payloads.","operationId":"post_insights_api_v1_insights_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get AI comparative analysis for executives or companies on a theme","tags":["documents"]}},"/api/v1/insights/refresh-summaries":{"post":{"description":"Refresh executive/company summary caches for the current workspace.","operationId":"refresh_insights_summaries_api_v1_insights_refresh_summaries_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Refresh summary cache tables for insights","tags":["documents"]}},"/api/v1/persona-summaries":{"get":{"description":"Synthesized summary for ONE persona \u2014 the favorites-card analogue of the<br/>audience category summary (KUM-444). Reuses the category summary generator<br/>scoped to a single persona and caches under a ``persona:<id>`` key. Reads<br/>cache by default; ``force_refresh=true`` regenerates.","operationId":"get_or_generate_persona_summary_api_v1_persona_summaries_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get or generate a single-persona reaction summary","tags":["personas"]}},"/api/v1/personas":{"get":{"description":"Get persona templates for the current workspace, optionally filtered by category.<br/><br/>Supports pagination via ``limit`` (default 200, max 500) and ``offset`` (default 0).<br/>Response includes ``total`` count before pagination so callers can detect truncation.<br/>Use ``?summary=1`` for the lightweight listing (no pagination cap applies there since<br/>summary objects are ~200B each).","operationId":"get_personas_api_v1_personas_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get all personas","tags":["personas"]},"post":{"description":"Create a new persona template","operationId":"create_persona_api_v1_personas_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create persona","tags":["personas"]}},"/api/v1/personas/avatar/generate":{"post":{"description":"Disabled (KUM-1321). Avatar generation was the last un-US-pinnable LLM path.<br/><br/>Retired rather than repointed, on three findings that all pointed the same way:<br/><br/>  * ``litellm.image_generation`` is the one litellm entry point the Vertex<br/>    failover wrapper cannot route, so with ``LLM_VERTEX_FAILOVER=1`` every<br/>    other call in the fleet moves to us-central1 and this one silently keeps<br/>    egressing to Google's global endpoint. It was the only remaining hole in<br/>    the US-region inference claim on KUM-1305.<br/>  * Imagen is not reachable on Vertex for this project at all --<br/>    ``imagen-4.0-generate-001``, ``imagegeneration@006`` and<br/>    ``imagen-3.0-generate-002`` all 404 in us-central1 -- so \"route it to<br/>    Vertex instead\" is a Model Garden enablement project, not a one-liner.<br/>  * Lifetime usage is six requests from one workspace in a single 109-second<br/>    burst on 2026-08-12, four of which failed. Nothing has called it since.<br/><br/>Two working avatar paths remain and are untouched: upload<br/>(``/api/v1/personas/avatar/upload``) and paste-an-image-URL. The \"Generate<br/>With AI\" card is removed from the editor so this returns for no one who did<br/>not call the API directly.<br/><br/>Re-enabling is deliberately a code change and not a flag, because a flag here<br/>silently reopens a customer-facing residency answer. It needs two things, and<br/>the second is not optional:<br/><br/>  1. a US-pinned image model enabled in Vertex Model Garden;<br/>  2. a prompt builder that does not paste an image into a text prompt. The<br/>     removed one interpolated ``reference_avatar_url`` verbatim, and<br/>     ``_normalize_avatar_url`` accepts ``data:image/...;base64,`` up to twice<br/>     ``_MAX_AVATAR_UPLOAD_BYTES`` -- so a reference avatar stored as an inline<br/>     data URL (which the upload path falls back to whenever GCS is<br/>     unavailable) went into the request as *text*. That is the measured<br/>     1,254,571-token prompt behind four 400s against a 32,768-token ceiling:<br/>     our bug, not a vendor fault, and it would recur on day one.","operationId":"generate_persona_avatar_api_v1_personas_avatar_generate_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate persona avatar image","tags":["personas"]}},"/api/v1/personas/avatar/upload":{"post":{"description":"Upload an avatar image for personas and return a usable avatar URL.","operationId":"upload_persona_avatar_api_v1_personas_avatar_upload_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Upload persona avatar image","tags":["personas"]}},"/api/v1/personas/build":{"post":{"description":"Queue one PERSONA_BUILD job per requested audience and kick each at once.<br/><br/>Body: ``{\"personas\": [{\"name\": \"...\", \"organisation\": \"...\", \"context\": \"...\"}, ...]}``<br/>(1\u2013100 rows) \u2192 202 ``{\"jobs\": [{\"job_id\", \"name\"}], \"requested\": n}``.<br/><br/>This is the asynchronous half of the Audience Library's \"Add audiences\":<br/>the foreground path ran two blocking LLM calls per row, chunked at five per<br/>request so a pasted list did not die at the proxy. Here each row is its own<br/>job \u2014 the job manager dedupes PERSONA_BUILD on the requested name, so the<br/>same name twice in one list (or one still queued) shares a job \u2014 and the<br/>requester gets a bell row per persona as it lands. Poll ``GET /api/v1/jobs/<id>``.","operationId":"build_personas_api_v1_personas_build_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Build personas in the background","tags":["personas"]}},"/api/v1/personas/bulk":{"post":{"description":"Bulk create persona templates for the current workspace.<br/>Skips duplicate names by default.","operationId":"bulk_create_personas_api_v1_personas_bulk_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Bulk create personas","tags":["personas"]}},"/api/v1/personas/bulk-update":{"post":{"description":"Apply per-persona field updates in one batch, with a per-persona report.<br/><br/>Deliberately NOT \"here is a proposal, here are 40 ids, fan it out\": the<br/>caller sends one explicit entry per persona, so what gets written is what<br/>was reviewed. ``dry_run`` returns the identical before/after computation<br/>without writing, which is what the UI renders as its preview \u2014 a preview<br/>built by the same code path as the write cannot drift from it.","operationId":"bulk_update_personas_api_v1_personas_bulk_update_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Apply a reviewed tuning proposal to many personas","tags":["personas"]}},"/api/v1/personas/categories":{"get":{"description":"Get all persona categories for the current workspace, sorted by custom order when available.","operationId":"get_persona_categories_api_v1_personas_categories_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get persona categories","tags":["personas"]}},"/api/v1/personas/chat-onboarding":{"post":{"description":"Stateless chat endpoint for persona onboarding and prompt coaching.<br/>The client sends full conversation history and receives the next assistant turn plus structured suggestions.","operationId":"persona_chat_onboarding_api_v1_personas_chat_onboarding_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Persona chat onboarding and prompt coaching","tags":["personas"]}},"/api/v1/personas/event-checks":{"get":{"description":"Workspace-wide ledger of real-event persona auto-tests (KUM-1387).<br/><br/>Event checks are ``persona_drift_checks`` rows with NULL<br/>``golden_response_id`` \u2014 a persona reacting to an actually-ingested document,<br/>graded for in-character consistency. Golden-baseline drift checks are a<br/>different population and are excluded here.<br/><br/>Ungated at the API (mirrors ``GET .../health``); the Validation Center UI<br/>gates on ``persona_health_enabled``. The summary reports **counts**, not<br/>percentages \u2014 the KUM-1345 evidence ruling applies to this surface too.","operationId":"get_workspace_event_checks_api_v1_personas_event_checks_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Real-world event auto-test results across the workspace","tags":["personas"]}},"/api/v1/personas/generate-draft":{"post":{"description":"Generate persona fields from partial inputs.<br/>Name is required. By default, only missing fields are generated.","operationId":"generate_persona_draft_api_v1_personas_generate_draft_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate persona draft fields","tags":["personas"]}},"/api/v1/personas/grade-timeline":{"get":{"description":"Return grade per persona per time period for the breakdown chart.<br/>Groups reaction insights by persona and time period (monthly or quarterly).<br/>Response: { timeline: { personaId: { \"2025-Q1\": { grade, count, reactions } } }, granularity }","operationId":"get_persona_grade_timeline_api_v1_personas_grade_timeline_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get grade timeline for personas by period","tags":["personas"]}},"/api/v1/personas/interact":{"post":{"description":"Interact with a synthetic persona","operationId":"interact_with_persona_api_v1_personas_interact_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Interact with persona","tags":["personas"]}},"/api/v1/personas/interactions":{"get":{"description":"Get persona interactions, optionally filtered by persona","operationId":"get_persona_interactions_api_v1_personas_interactions_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get persona interactions","tags":["personas"]}},"/api/v1/personas/interactions/{interaction_id}":{"get":{"description":"Get persona interaction results","operationId":"get_persona_interaction_api_v1_personas_interactions__interaction_id__get","parameters":[{"in":"path","name":"interaction_id","required":true,"schema":{"title":"Interaction Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get persona interaction","tags":["personas"]}},"/api/v1/personas/preview-compiled-prompt":{"post":{"description":"Return the exact system/user prompt payload that would be sent to the LLM.","operationId":"preview_compiled_persona_prompt_api_v1_personas_preview_compiled_prompt_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Preview compiled persona prompt payload","tags":["personas"]}},"/api/v1/personas/reaction-insights":{"get":{"description":"List cached persona reaction insights for the current workspace.<br/><br/>Set latest_only=true to collapse each (persona, document) pair to its<br/>newest row. It is NOT one row per persona \u2014 a persona that reacted to ten<br/>documents still returns ten rows. That wording used to say \"per persona\",<br/>which read as \"one row, total\" and sent the persona profile page to<br/>latest_only=false, where superseded scorecards skewed its relationship<br/>grade (KUM-989). Leave it off only when you want run history.","operationId":"list_persona_reaction_insights_api_v1_personas_reaction_insights_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List cached persona reaction insights","tags":["personas"]},"post":{"description":"Return cached persona reaction insights for a document/persona set.<br/>If force_refresh=true, regenerate and overwrite cache rows.","operationId":"get_or_generate_persona_reaction_insights_api_v1_personas_reaction_insights_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get or generate cached persona reaction insights","tags":["personas"]}},"/api/v1/personas/reaction-insights/async":{"post":{"description":"Queue a background job for generating persona reaction insights and return<br/>a job_id the client can poll. This unlocks batches of \u226510 audiences without<br/>tying them to a single-request gateway timeout and lets the UI append rows<br/>as they complete via polling the jobs + reaction-insights list endpoints.<br/><br/>The synchronous POST endpoint remains the right choice for small batches<br/>(see PERSONA_REACTION_SYNC_THRESHOLD); this route is for larger fan-outs.","operationId":"queue_persona_reaction_insights_job_api_v1_personas_reaction_insights_async_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Queue a background job to generate persona reaction insights","tags":["personas"]}},"/api/v1/personas/reaction-insights/history":{"get":{"description":"Return chronological reaction entries for a single persona + document,<br/>ordered newest-first. Used by the reaction-history timeline in the UI.","operationId":"get_persona_reaction_history_api_v1_personas_reaction_insights_history_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get reaction history for a persona+document pair","tags":["personas"]}},"/api/v1/personas/why-it-matters":{"post":{"description":"Grounded retrieval pass surfacing why a communication matters to a specific<br/>persona. Rides the grounded-context cache (``grounded_context_answer``, 7-day<br/>TTL + citations): a fresh cached answer is returned as-is unless<br/>``force_refresh`` is set, otherwise one web-grounded LLM call is made<br/>synchronously and persisted. Click-to-generate keeps LLM/search spend bounded.","operationId":"generate_persona_why_it_matters_api_v1_personas_why_it_matters_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate/fetch grounded 'why this matters' for a persona+document","tags":["personas"]}},"/api/v1/personas/why-it-matters/config":{"get":{"description":"Return whether the grounded 'Why this matters to them' section is available<br/>for this workspace (feature toggle, super-admin bypassed) and whether it is<br/>configured to generate automatically (workspace setting).","operationId":"get_why_it_matters_config_api_v1_personas_why_it_matters_config_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Why-this-matters availability + auto setting","tags":["personas"]}},"/api/v1/personas/{persona_id}":{"delete":{"description":"Delete a persona template","operationId":"delete_persona_endpoint_api_v1_personas__persona_id__delete","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete persona","tags":["personas"]},"get":{"description":"Get a specific persona template","operationId":"get_persona_api_v1_personas__persona_id__get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get persona by ID","tags":["personas"]},"put":{"description":"Update an existing persona template","operationId":"update_persona_endpoint_api_v1_personas__persona_id__put","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update persona","tags":["personas"]}},"/api/v1/personas/{persona_id}/analyze-voice":{"post":{"description":"Analyze writing samples to extract a structured voice profile for a persona.<br/><br/>Accepts either raw text samples or knowledgebase document IDs.<br/>Uses the workspace system default model (audience_model) for analysis.<br/>Stores the resulting voice profile in the persona's persona_config.","operationId":"analyze_voice_endpoint_api_v1_personas__persona_id__analyze_voice_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Analyze voice from writing samples","tags":["personas"]}},"/api/v1/personas/{persona_id}/auto-test":{"put":{"description":"Set the per-persona real-event auto-test opt-in (KUM-1296). Body:<br/>``{\"enabled\": true|false}``. Defaults to off; turning it on means every<br/>document ingested into the workspace costs this persona one generation plus<br/>one judge call, capped at ``EVENT_AUTO_TEST_PERSONA_CAP`` personas per event.<br/><br/>The response reports the value **read back** from the persona rather than the<br/>value that was posted: ``update_persona_template`` silently drops config keys<br/>that are missing from its allow-list while still returning success, so<br/>echoing the request would report a write that never landed.","operationId":"set_persona_auto_test_api_v1_personas__persona_id__auto_test_put","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Enable/disable auto-testing this persona against real events","tags":["personas"]}},"/api/v1/personas/{persona_id}/discover-linkedin":{"post":{"description":"Find LinkedIn profile candidates for a persona from real search results.<br/><br/>Search-engine backed, not LLM backed (KUM-1226). Grounded search cannot do<br/>this job on any transport: the query runs, but Google returns zero citable<br/>chunks for LinkedIn, so the model answers from memory with a name-shaped slug<br/>that nothing then verified. See ``cloud_providers/linkedin_resolver`` for the<br/>measurement, including a wrong first diagnosis worth not repeating.<br/><br/>Every URL returned is one a search engine produced. When retrieval finds<br/>nothing the response is an empty list plus a ``reason`` -- a guessed URL is<br/>worse than none, because applying a candidate writes a persona social link<br/>and points Bright Data at a profile that may not exist.","operationId":"discover_linkedin_for_persona_api_v1_personas__persona_id__discover_linkedin_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Discover LinkedIn profile for persona","tags":["personas"]}},"/api/v1/personas/{persona_id}/drift-check":{"post":{"description":"Enqueue a PERSONA_DRIFT_CHECK job for a single persona (re-run golden<br/>prompts, LLM-judge similarity, roll health state).","operationId":"trigger_persona_drift_check_api_v1_personas__persona_id__drift_check_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Trigger a persona drift check now","tags":["personas"]}},"/api/v1/personas/{persona_id}/drift-checks/{check_id}/confirm":{"post":{"description":"Confirm-or-tune \u2192 CONFIRM: the current response is fine, so promote it to<br/>the golden baseline (text + verified_by/at) and mark the check resolved.<br/>Feeds the human-in-the-loop revalidation back into the set, which is what<br/>keeps the baseline current instead of ossifying around an older answer.","operationId":"confirm_persona_drift_check_api_v1_personas__persona_id__drift_checks__check_id__confirm_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"check_id","required":true,"schema":{"title":"Check Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Confirm a drift check (response fine)","tags":["personas"]}},"/api/v1/personas/{persona_id}/drift-checks/{check_id}/tune":{"post":{"description":"Confirm-or-tune \u2192 TUNE: the response has drifted; mark the check resolved<br/>as 'tuned' (the UI routes the user to the refinements/feedback flow).","operationId":"tune_persona_drift_check_api_v1_personas__persona_id__drift_checks__check_id__tune_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"check_id","required":true,"schema":{"title":"Check Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Mark a drift check as being tuned","tags":["personas"]}},"/api/v1/personas/{persona_id}/drift-policy":{"get":{"description":"Return the effective drift-check cadence (override or workspace default).","operationId":"get_persona_drift_policy_api_v1_personas__persona_id__drift_policy_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get persona drift-check cadence","tags":["personas"]},"put":{"description":"Set (or clear) the per-persona drift-check cadence override. Body:<br/>``{\"frequency\": \"weekly|monthly|quarterly|manual\"}`` (empty/\"default\" clears).","operationId":"set_persona_drift_policy_api_v1_personas__persona_id__drift_policy_put","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Set persona drift-check cadence override","tags":["personas"]}},"/api/v1/personas/{persona_id}/feedback":{"post":{"description":"Submit feedback for a persona response (thumbs up/down + description).","operationId":"submit_persona_feedback_api_v1_personas__persona_id__feedback_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Submit persona response feedback","tags":["personas"]}},"/api/v1/personas/{persona_id}/generate":{"post":{"description":"Generate multi-format content (press release, blog post, social media, email,<br/>product description) written in a persona's voice profile.","operationId":"generate_persona_content_api_v1_personas__persona_id__generate_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate content in persona voice","tags":["personas"]}},"/api/v1/personas/{persona_id}/golden-responses":{"get":{"description":"List golden-set entries (trusted prompt/response baselines) for a persona.","operationId":"list_persona_golden_responses_api_v1_personas__persona_id__golden_responses_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List persona golden responses","tags":["personas"]},"post":{"description":"Add a golden-set entry.<br/><br/>Two modes:<br/>- Manual/real-world: provide `prompt` + `golden_response` (+ optional `source`).<br/>- Seed-from-feedback: provide `feedback_id`; the server hydrates prompt/response<br/>  from the positive feedback row and stamps source='user_feedback'.","operationId":"create_persona_golden_response_api_v1_personas__persona_id__golden_responses_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Add a golden response","tags":["personas"]}},"/api/v1/personas/{persona_id}/golden-responses/candidates":{"get":{"description":"List positive feedback items eligible to seed the golden set.<br/><br/>Each candidate carries `already_added` so the picker can disable items that<br/>have already been promoted (deduped by source_feedback_id).","operationId":"list_persona_golden_candidates_api_v1_personas__persona_id__golden_responses_candidates_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List seed-from-feedback candidates","tags":["personas"]}},"/api/v1/personas/{persona_id}/golden-responses/{golden_id}":{"delete":{"description":"Delete a golden-set entry.","operationId":"delete_persona_golden_response_api_v1_personas__persona_id__golden_responses__golden_id__delete","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"golden_id","required":true,"schema":{"title":"Golden Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete a golden response","tags":["personas"]},"patch":{"description":"Edit prompt/response or activate/deactivate a golden-set entry.","operationId":"update_persona_golden_response_api_v1_personas__persona_id__golden_responses__golden_id__patch","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"golden_id","required":true,"schema":{"title":"Golden Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update a golden response","tags":["personas"]}},"/api/v1/personas/{persona_id}/health":{"get":{"description":"Return a persona's rolling health state, drift cadence, and the latest<br/>drift run's checks (failing ones first) for the confirm-or-tune panel.<br/><br/>Ungated at the API (mirrors golden-responses / refinements); the UI gates on<br/>``persona_health_enabled``.","operationId":"get_persona_health_api_v1_personas__persona_id__health_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get persona health + latest drift checks","tags":["personas"]}},"/api/v1/personas/{persona_id}/intelligence":{"get":{"description":"Return a persona's synthesized snapshots plus its measured corpus facts.<br/><br/>Read-only: this never triggers synthesis. The ``sections`` snapshots are<br/>produced by the PERSONA_INTELLIGENCE job on the persona's refresh cadence or<br/>via the manual refresh endpoint below, so a page view costs no inference<br/>(KUM-681).<br/><br/>``measured`` (KUM-684) is different in kind and is computed here, per<br/>request: follower counts and a recent-activity feed are indexed reads over<br/>the persona's linked knowledgebases, not model output. Snapshotting them<br/>would gain nothing \u2014 there is no inference to amortize \u2014 and would cost<br/>accuracy, because the default refresh cadence is quarterly and a feed<br/>labelled \"live activity\" that is a quarter stale is the kind of thing<br/>KUM-680 removed from this page.<br/><br/>Both are workspace-scoped: stance is measured toward *this* workspace's<br/>company and so are mentions, which is why a marketplace install recomputes<br/>against the buyer's workspace rather than inheriting the seller's reading.","operationId":"get_persona_intelligence_api_v1_personas__persona_id__intelligence_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get a persona's intelligence snapshots","tags":["personas"]}},"/api/v1/personas/{persona_id}/link-external-source":{"post":{"description":"Link an external source (e.g. a journalist's column, a blog, or a publication URL)<br/>to a persona by creating a knowledgebase with a web/RSS watcher source.<br/>If the persona already has an external-source KB, the existing one is returned.","operationId":"link_external_source_to_persona_api_v1_personas__persona_id__link_external_source_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Link external source to persona","tags":["personas"]}},"/api/v1/personas/{persona_id}/link-file":{"post":{"description":"Upload a file (deck, doc, notes) and link it to a persona as a grounding<br/>source. The file is ingested into a per-persona \"Linked Files\"<br/>knowledgebase that is attached via linked_knowledgebase_ids, so its<br/>content grounds the persona and feeds persona refresh like watched<br/>web/social sources do.","operationId":"link_file_to_persona_api_v1_personas__persona_id__link_file_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Link an uploaded file to persona","tags":["personas"]}},"/api/v1/personas/{persona_id}/link-linkedin":{"post":{"description":"Link a LinkedIn profile to a persona by creating a knowledgebase with a<br/>LinkedIn watcher source.  If the persona already has a LinkedIn KB, the<br/>existing one is returned instead of creating a duplicate.","operationId":"link_linkedin_to_persona_api_v1_personas__persona_id__link_linkedin_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Link LinkedIn profile to persona","tags":["personas"]}},"/api/v1/personas/{persona_id}/quick-link":{"post":{"description":"Append one pasted profile or website URL to a persona's links (KUM-779).<br/><br/>The personas listing's \"+\" control posts here rather than PUT /personas/<id>,<br/>because `social_links` on that route is a *replace*: a caller holding only the<br/>one link it just collected would wipe every other link on the persona. Doing<br/>the read-modify-write server-side makes the append atomic and reuses the bulk<br/>importer's de-dupe and cap rules.<br/><br/>A recognized social host lands in `social_links`; anything else lands in<br/>`external_sources`. That split is deliberate and load-bearing, not tidiness:<br/>a non-empty `social_links` is a signal several readers act on. It trips<br/>`classify_persona_kind`'s \"has-public-source\" tiebreak, which would flip an<br/>archetype persona to organization (and switch its profile to the intelligence<br/>shell) just because someone pasted a magazine URL; and it satisfies the<br/>profile's \"Live activity & reach\" readiness row, which is measured only from<br/>x/bluesky/linkedin sources and so would sit permanently ready-but-empty.<br/>`external_sources` is inert for both.","operationId":"quick_link_persona_api_v1_personas__persona_id__quick_link_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Quick-add a persona link","tags":["personas"]}},"/api/v1/personas/{persona_id}/refinements":{"get":{"description":"List all active refinements (tuning notes) for a persona.","operationId":"list_persona_refinements_api_v1_personas__persona_id__refinements_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List persona refinements","tags":["personas"]},"post":{"description":"Manually add a refinement note to a persona profile.","operationId":"create_persona_refinement_api_v1_personas__persona_id__refinements_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Add manual persona refinement","tags":["personas"]}},"/api/v1/personas/{persona_id}/refinements/{refinement_id}":{"delete":{"description":"Delete a refinement note from a persona profile.","operationId":"delete_persona_refinement_api_v1_personas__persona_id__refinements__refinement_id__delete","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"refinement_id","required":true,"schema":{"title":"Refinement Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete persona refinement","tags":["personas"]},"patch":{"description":"Update content or active state of a refinement note.","operationId":"update_persona_refinement_api_v1_personas__persona_id__refinements__refinement_id__patch","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"refinement_id","required":true,"schema":{"title":"Refinement Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update persona refinement","tags":["personas"]}},"/api/v1/personas/{persona_id}/refresh":{"post":{"description":"Enqueue a PERSONA_REFRESH job for a single persona (re-crawl linked KBs,<br/>regenerate the voice/position summary, stamp the cadence).","operationId":"trigger_persona_refresh_api_v1_personas__persona_id__refresh_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Trigger a persona refresh now","tags":["personas"]}},"/api/v1/personas/{persona_id}/refresh-intelligence":{"post":{"description":"Enqueue a PERSONA_INTELLIGENCE job for a single persona.<br/><br/>The same job the refresh cadence chains, so the manual button and the<br/>schedule share exactly one synthesis path.","operationId":"trigger_persona_intelligence_api_v1_personas__persona_id__refresh_intelligence_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Trigger persona intelligence synthesis now","tags":["personas"]}},"/api/v1/personas/{persona_id}/refresh-policy":{"get":{"description":"Return the effective refresh cadence for a persona (override or workspace default).","operationId":"get_persona_refresh_policy_api_v1_personas__persona_id__refresh_policy_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get persona refresh cadence policy","tags":["personas"]},"put":{"description":"Set (or clear) the per-persona refresh cadence override.<br/><br/>Body: ``{\"frequency\": \"weekly|monthly|quarterly|manual\"}``. Pass ``null`` /<br/>empty / ``\"default\"`` to clear the override and inherit the workspace default.<br/>Recomputes ``next_refresh_at`` from the last refresh (or now) at the new cadence.","operationId":"set_persona_refresh_policy_api_v1_personas__persona_id__refresh_policy_put","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Set persona refresh cadence override","tags":["personas"]}},"/api/v1/personas/{persona_id}/relink-marketplace":{"post":{"description":"Point an existing workspace persona at a marketplace catalog row (KUM-1303).<br/><br/>Body: ``{\"source_persona_id\": \"<catalog persona id>\"}``.<br/><br/>This backs the grid's **Replace** action. A workspace can hold a persona that<br/>shares a catalog persona's name but was hand-authored, or was installed before<br/>KUM-1231 taught the install route to record linkage \u2014 either way it carries no<br/>``source_persona_id``, so it is not managed and never receives catalog updates.<br/><br/>Relink happens **in place**. The obvious implementation \u2014 delete the local row<br/>and re-install from the catalog \u2014 mints a new persona id, and everything that<br/>references a persona by id (document auto-tags, signals, audiences, report<br/>inclusion) would silently point at a row that no longer exists. So this only<br/>ever UPDATEs, and the id is part of the contract asserted by the tests.<br/><br/>Two deliberate choices:<br/><br/>* The source id is validated through ``_resolve_marketplace_source_persona`` \u2014<br/>  the same guard the install route applies \u2014 so a caller cannot name an<br/>  arbitrary uuid and pull a persona out of a workspace they cannot read.<br/>* The managed fields (links, grounded prompts, voice details) are<br/>  **overwritten** from the source, not gap-filled the way install does.<br/>  Install is gap-filling because the caller is posting a persona and may<br/>  have edited it in the modal first; here the caller is asking<br/>  to *become* the catalog version. Being precious about ``social_links`` while<br/>  the link sync goes on to clobber instructions/tone/avatar (see<br/>  ``_persona_config_inheritance_keys``) would be incoherent. A **blank** source<br/>  value still never overwrites \u2014 \"the catalog has no links yet\" is not a reason<br/>  to erase the ones the workspace already has, matching the same conservative<br/>  rule in ``_annotate_marketplace_managed``.<br/><br/>Workspace-local settings are not written here: the active flag, category and<br/>report inclusion live in ``persona_config`` and are carried over from the<br/>current row. Note this is **not** the same as promising they survive \u2014 this<br/>call sets ``is_linked_to_source``, and from the next full-mode<br/>``GET /personas`` the link sync overwrites everything in<br/>``_persona_config_inheritance_keys`` from the catalog, which includes<br/>``category``, ``is_active`` and ``include_in_audience``. Callers must say so;<br/>the grid's confirm dialog does.","operationId":"relink_persona_to_marketplace_api_v1_personas__persona_id__relink_marketplace_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Adopt a marketplace source into an existing persona","tags":["personas"]}},"/api/v1/personas/{persona_id}/self-heal-policy":{"get":{"description":"Return the per-persona self-healing auto-tune policy (KUM-1297).","operationId":"get_persona_self_heal_policy_api_v1_personas__persona_id__self_heal_policy_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get persona self-healing auto-tune policy","tags":["personas"]},"put":{"description":"Turn self-healing auto-tune on or off for one persona (KUM-1297).<br/><br/>Body: ``{\"enabled\": true|false}``. Off by default and off for every existing<br/>persona \u2014 auto-tune rewrites the customer's own persona instructions, so it<br/>only ever runs where someone opted in.<br/><br/>Returns the **read-back** policy rather than the requested one. New<br/>``persona_config`` keys are dropped unless allow-listed in<br/>``update_persona_template``, and that drop returns success, so echoing the<br/>request would report a write that did not happen.","operationId":"set_persona_self_heal_policy_api_v1_personas__persona_id__self_heal_policy_put","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Set persona self-healing auto-tune policy","tags":["personas"]}},"/api/v1/personas/{persona_id}/unlink-file":{"post":{"description":"Remove a linked file from a persona: detach the document from the<br/>persona's linked-files KB and soft-delete it (linked-file uploads exist<br/>only to ground this persona).","operationId":"unlink_file_from_persona_api_v1_personas__persona_id__unlink_file_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Unlink an uploaded file from persona","tags":["personas"]}},"/api/v1/personas/{persona_id}/voice-profiles":{"get":{"description":"Return all voice profiles for a persona.","operationId":"list_voice_profiles_api_v1_personas__persona_id__voice_profiles_get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List voice profiles for a persona","tags":["personas"]}},"/api/v1/personas/{persona_id}/voice-profiles/{profile_id}":{"delete":{"description":"Delete a voice profile. Cannot delete the last remaining profile.","operationId":"delete_voice_profile_api_v1_personas__persona_id__voice_profiles__profile_id__delete","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete a voice profile","tags":["personas"]},"get":{"description":"Return a single voice profile by ID.","operationId":"get_voice_profile_api_v1_personas__persona_id__voice_profiles__profile_id__get","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get a single voice profile","tags":["personas"]},"put":{"description":"Update an existing voice profile (name, adjective_tags, tone_pillars, etc.).","operationId":"update_voice_profile_api_v1_personas__persona_id__voice_profiles__profile_id__put","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update a voice profile","tags":["personas"]}},"/api/v1/personas/{persona_id}/voice-profiles/{profile_id}/set-default":{"post":{"description":"Set a voice profile as the default for content generation.","operationId":"set_default_voice_profile_api_v1_personas__persona_id__voice_profiles__profile_id__set_default_post","parameters":[{"in":"path","name":"persona_id","required":true,"schema":{"title":"Persona Id","type":"string"}},{"in":"path","name":"profile_id","required":true,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"default":null,"title":"Profile Id"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Set default voice profile","tags":["personas"]}},"/api/v1/reports":{"get":{"operationId":"list_custom_reports_api_v1_reports_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List custom reports for workspace","tags":["reports"]},"post":{"operationId":"create_custom_report_api_v1_reports_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create a custom report","tags":["reports"]}},"/api/v1/reports/{report_id}":{"delete":{"operationId":"delete_custom_report_api_v1_reports__report_id__delete","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete a custom report","tags":["reports"]},"get":{"operationId":"get_custom_report_api_v1_reports__report_id__get","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get custom report with sections","tags":["reports"]},"patch":{"operationId":"update_custom_report_api_v1_reports__report_id__patch","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update a custom report","tags":["reports"]}},"/api/v1/reports/{report_id}/customize-style":{"post":{"description":"Use LLM to translate a natural language style description into a layout_config JSON.","operationId":"customize_report_style_api_v1_reports__report_id__customize_style_post","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate layout_config from natural language style description","tags":["reports"]}},"/api/v1/reports/{report_id}/generate":{"post":{"description":"Regenerate all stale sections of a report. Returns cached output for fresh sections.","operationId":"generate_report_all_api_v1_reports__report_id__generate_post","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate all stale sections","tags":["reports"]}},"/api/v1/reports/{report_id}/pdf":{"get":{"description":"Generate and return a PDF of the report.","operationId":"download_report_pdf_api_v1_reports__report_id__pdf_get","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Download report as PDF","tags":["reports"]}},"/api/v1/reports/{report_id}/schedule":{"delete":{"description":"Remove the refresh schedule for a report.","operationId":"delete_report_schedule_api_v1_reports__report_id__schedule_delete","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete report schedule","tags":["reports"]},"get":{"description":"Get the current refresh schedule for a report (if any).","operationId":"get_report_schedule_api_v1_reports__report_id__schedule_get","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get report schedule","tags":["reports"]},"patch":{"description":"Update the refresh schedule for a report.","operationId":"update_report_schedule_api_v1_reports__report_id__schedule_patch","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update report schedule","tags":["reports"]},"post":{"description":"Create a recurring refresh schedule for a report.","operationId":"create_report_schedule_api_v1_reports__report_id__schedule_post","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create report refresh schedule","tags":["reports"]}},"/api/v1/reports/{report_id}/sections":{"post":{"operationId":"create_report_section_api_v1_reports__report_id__sections_post","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Add section to a report","tags":["reports"]}},"/api/v1/reports/{report_id}/sections/{section_id}":{"delete":{"operationId":"delete_report_section_api_v1_reports__report_id__sections__section_id__delete","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}},{"in":"path","name":"section_id","required":true,"schema":{"title":"Section Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete a report section","tags":["reports"]},"patch":{"operationId":"update_report_section_api_v1_reports__report_id__sections__section_id__patch","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}},{"in":"path","name":"section_id","required":true,"schema":{"title":"Section Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update a report section","tags":["reports"]}},"/api/v1/reports/{report_id}/sections/{section_id}/generate":{"post":{"description":"Force-generate (or regenerate) the LLM output for a single report section.","operationId":"generate_report_section_api_v1_reports__report_id__sections__section_id__generate_post","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}},{"in":"path","name":"section_id","required":true,"schema":{"title":"Section Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate output for a single section","tags":["reports"]}},"/api/v1/reports/{report_id}/send-email":{"post":{"description":"Send the report as an HTML email with optional PDF attachment.","operationId":"send_report_email_api_v1_reports__report_id__send_email_post","parameters":[{"in":"path","name":"report_id","required":true,"schema":{"title":"Report Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Send report via email","tags":["reports"]}},"/api/v1/signal-templates":{"post":{"description":"Create a new signal template","operationId":"create_signal_template_api_v1_signal_templates_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Create signal template","tags":["signals"]}},"/api/v1/signal-templates/bulk":{"post":{"description":"Bulk create signal templates for the current workspace.<br/>Supports optional row-level prompt/context guidance and optional draft autogeneration.","operationId":"bulk_create_signal_templates_api_v1_signal_templates_bulk_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Bulk create signal templates","tags":["signals"]}},"/api/v1/signal-templates/generate-draft":{"post":{"description":"Generate signal template fields from partial inputs.<br/>Name is required. By default, only missing fields are generated.","operationId":"generate_signal_template_draft_api_v1_signal_templates_generate_draft_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Generate signal template draft fields","tags":["signals"]}},"/api/v1/signal-templates/{template_id}":{"delete":{"description":"Delete a signal template","operationId":"delete_signal_template_endpoint_api_v1_signal_templates__template_id__delete","parameters":[{"in":"path","name":"template_id","required":true,"schema":{"title":"Template Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete signal template","tags":["signals"]},"put":{"description":"Update an existing signal template","operationId":"update_signal_template_endpoint_api_v1_signal_templates__template_id__put","parameters":[{"in":"path","name":"template_id","required":true,"schema":{"title":"Template Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Update signal template","tags":["signals"]}},"/api/v1/signals":{"get":{"description":"Get all signals with pagination","operationId":"get_all_signals_api_api_v1_signals_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get all signals","tags":["signals"]}},"/api/v1/signals/document/{document_id}":{"delete":{"description":"Soft-delete all non-deleted signals for a specific document in the current workspace.","operationId":"delete_document_signals_api_api_v1_signals_document__document_id__delete","parameters":[{"in":"path","name":"document_id","required":true,"schema":{"title":"Document Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Delete signals for a specific document","tags":["signals"]},"get":{"description":"Get all signals for a specific document with filtering","operationId":"get_document_signals_api_api_v1_signals_document__document_id__get","parameters":[{"in":"path","name":"document_id","required":true,"schema":{"title":"Document Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get signals for a specific document","tags":["signals"]}},"/api/v1/signals/execute-workspace-signals":{"post":{"description":"Execute all signal templates in the workspace against a specific document.<br/><br/>This endpoint is non-blocking - it immediately returns after queuing the signal<br/>execution to run in the background. Use this after document upload to automatically<br/>run all configured signals against the new document.","operationId":"execute_workspace_signals_api_v1_signals_execute_workspace_signals_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExecuteWorkspaceSignalsRequest"}}},"required":true},"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"ApiKeyAuth":[]}],"summary":"Execute all workspace signals on a document (async)","tags":["signals"]}},"/api/v1/signals/generate":{"post":{"description":"Generate signals from input","operationId":"generate_signals_api_v1_signals_generate_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"ApiKeyAuth":[]}],"summary":"Generate signals","tags":["signals"]}},"/api/v1/signals/runs":{"get":{"description":"Get all signal runs","operationId":"get_signal_runs_api_v1_signals_runs_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get all signal runs","tags":["signals"]}},"/api/v1/signals/runs/{run_id}":{"get":{"description":"Get signal run status and results","operationId":"get_signal_run_api_v1_signals_runs__run_id__get","parameters":[{"in":"path","name":"run_id","required":true,"schema":{"title":"Run Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"ApiKeyAuth":[]}],"summary":"Get signal run","tags":["signals"]}},"/api/v1/signals/templates":{"get":{"description":"Get all signal templates","operationId":"get_signal_templates_api_v1_signals_templates_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"ApiKeyAuth":[]}],"summary":"Get all signal templates","tags":["signals"]}},"/api/v1/signals/templates/{template_id}":{"get":{"description":"Get a specific signal template","operationId":"get_signal_template_api_v1_signals_templates__template_id__get","parameters":[{"in":"path","name":"template_id","required":true,"schema":{"title":"Template Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"security":[{"ApiKeyAuth":[]}],"summary":"Get signal template by ID","tags":["signals"]}},"/api/v1/signals/templates/{template_id}/signals":{"get":{"description":"Get all signals from a specific template","operationId":"get_signals_by_template_api_v1_signals_templates__template_id__signals_get","parameters":[{"in":"path","name":"template_id","required":true,"schema":{"title":"Template Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get signals by template","tags":["signals"]}},"/api/v1/signals/{signal_id}/feedback":{"post":{"description":"Submit feedback for a signal (thumbs up/down)","operationId":"submit_signal_feedback_api_v1_signals__signal_id__feedback_post","parameters":[{"in":"path","name":"signal_id","required":true,"schema":{"title":"Signal Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Submit signal feedback","tags":["signals"]}},"/api/v1/test":{"get":{"description":"Simple test endpoint that doesn't require authentication","operationId":"test_endpoint_api_v1_test_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Test endpoint","tags":["test"]}},"/api/v1/test-theme-filters":{"get":{"description":"Test theme filters endpoint without authentication","operationId":"test_theme_filters_api_v1_test_theme_filters_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Test theme filters without auth","tags":["test"]}},"/api/v1/theme-filters":{"get":{"description":"Get available themes and executives for insights analysis","operationId":"get_theme_filters_api_v1_theme_filters_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get available themes and executives for insights","tags":["documents"]}},"/api/v1/themes":{"get":{"description":"Get themes and extracted signals with document links and metadata","operationId":"get_themes_api_v1_themes_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get themes and extracted signals","tags":["documents"]}},"/api/v1/themes-for-executives":{"post":{"description":"Get available themes for selected executives","operationId":"get_themes_for_executives_api_v1_themes_for_executives_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get available themes for selected executives","tags":["documents"]}},"/api/v1/themes/debug":{"get":{"description":"Debug endpoint to check what signals exist","operationId":"debug_themes_api_v1_themes_debug_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Debug themes data","tags":["documents"]}},"/api/v1/themes/test":{"get":{"description":"Test endpoint to verify signal_generator is working","operationId":"test_themes_api_v1_themes_test_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Test themes endpoint","tags":["documents"]}},"/api/v1/translate":{"post":{"description":"Translate a persona reaction row, or a single string, for the operator.<br/><br/>Two modes, because the two surfaces have different storage:<br/><br/>- ``{\"reaction_insight_id\": ...}`` \u2014 object-scoped. The translation is<br/>  cached on the row at ``response_payload.translations.<tag>``, so every<br/>  repeat view is free. Audience Snapshot cards and narrative Stage A<br/>  responses are both ``persona_reaction_insights`` rows, so both are served<br/>  here.<br/>- ``{\"text\": ...}`` \u2014 stateless. Persona chat in the browser posts to<br/>  ``/api/v1/personas/interact``, which persists nothing, so there is no<br/>  parent object to cache on. The caller caches for the session instead.<br/><br/>``target_language`` resolves **explicit payload value -> the caller's own<br/>preference (``user_settings.ui_preferences.language``, global row) -><br/>the workspace operator language (``workspace.settings.language``) -><br/>English** (KUM-1447). An explicit value still wins, which is what lets a<br/>reader translate one message into something other than their default.","operationId":"translate_persona_output_api_v1_translate_post","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Translate persona output into the operator language","tags":["personas"]}},"/api/v1/user/workspaces":{"get":{"operationId":"get_user_workspaces_v1_api_v1_user_workspaces_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get all workspaces for the authenticated user","tags":["default"]}},"/api/v1/validation/runs":{"get":{"description":"Summaries (no payload) of every run of ``kind`` \u2014 the trend strip.","operationId":"list_validation_runs_api_v1_validation_runs_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Validation study runs, summaries only, newest first","tags":["personas"]}},"/api/v1/validation/runs/latest":{"get":{"description":"The Validation Center's study data (KUM-1387).<br/><br/>``kind`` is ``prediction_ledger`` (the retrospective Prediction Ledger:<br/>persona arms vs same-model baselines on real events, design/kum-1387-<br/>prediction-ledger) or ``voice_backtest`` (the V1 pairwise voice-fidelity<br/>study). Rows are written only by the study harness's exporter, so what this<br/>serves is exactly what RESULTS.md was generated from. Fleet-level evidence<br/>about the marketplace catalog, not workspace data \u2014 any authenticated key<br/>with persona.read may read it; the polarys page keeps its own gate.<br/>Missing run => 404 with a body the page can tell apart from an empty ledger.","operationId":"get_latest_validation_run_api_v1_validation_runs_latest_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Latest run of a pre-registered persona validation study","tags":["personas"]}},"/api/v1/workspace":{"get":{"operationId":"get_current_workspace_api_v1_workspace_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get the current workspace for the authenticated user","tags":["default"]}},"/api/v1/workspace/company-tags":{"get":{"description":"<br/>Admin key may pass ?workspace_id= to query another workspace.","operationId":"get_workspace_company_tags_api_v1_workspace_company_tags_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Return distinct company names extracted by company auto tags for this workspace.","tags":["default"]}},"/api/v1/workspace/content-type-tags":{"get":{"operationId":"get_workspace_content_type_tags_api_v1_workspace_content_type_tags_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Return distinct content/communication type values extracted by content-type auto tags.","tags":["default"]}},"/api/v1/workspace/health-check-families":{"get":{"description":"Return every check family, its declared cost, and this workspace's opt-in.<br/><br/>Ungated at the API for the same reason ``GET /personas/<id>/health`` is: the<br/>settings UI needs to know whether the feature is on in order to decide what<br/>to render, and a 403 is indistinguishable from \"no families exist\" at the<br/>fetch site. ``master_enabled`` in the payload is the honest answer; the write<br/>below is what is gated.","operationId":"get_workspace_health_check_families_api_v1_workspace_health_check_families_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get per-family health-check toggles + cost","tags":["personas"]},"put":{"description":"Enable or disable individual check families for this workspace.<br/><br/>Body: ``{\"families\": {\"drift\": true}}`` \u2014 a partial map. Families the body<br/>does not name keep their stored state, so a UI that persists one switch<br/>cannot silently reset the others.<br/><br/>Returns the **read-back** resolved policy rather than the requested state<br/>(the KUM-1297 convention): a settings write that lands nowhere still returns<br/>200, so the client must render what persisted, not what it asked for.","operationId":"set_workspace_health_check_families_api_v1_workspace_health_check_families_put","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Set per-family health-check toggles","tags":["personas"]}},"/api/v1/workspace/persona-refresh-default":{"get":{"description":"Return the workspace-level default refresh cadence (falls back to quarterly).","operationId":"get_workspace_persona_refresh_default_api_v1_workspace_persona_refresh_default_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get workspace default persona refresh cadence","tags":["personas"]},"put":{"description":"Set the workspace-level default refresh cadence (marquee/default personas<br/>inherit this when they have no per-persona override).","operationId":"set_workspace_persona_refresh_default_api_v1_workspace_persona_refresh_default_put","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Set workspace default persona refresh cadence","tags":["personas"]}},"/api/workspaces/{workspace_id}/members":{"get":{"description":"Return workspace members for sharing UI.","operationId":"list_workspace_members_api_workspaces__workspace_id__members_get","parameters":[{"in":"path","name":"workspace_id","required":true,"schema":{"title":"Workspace Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"List workspace members","tags":["documents"]}},"/api/workspaces/{workspace_id}/pull_through_priorities":{"get":{"description":"Return the workspace-scoped pull-through priorities list.","operationId":"get_pull_through_priorities_api_workspaces__workspace_id__pull_through_priorities_get","parameters":[{"in":"path","name":"workspace_id","required":true,"schema":{"title":"Workspace Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Get workspace pull-through priorities","tags":["documents"]},"put":{"description":"Atomically replace the workspace-scoped pull-through priorities list.","operationId":"update_pull_through_priorities_api_workspaces__workspace_id__pull_through_priorities_put","parameters":[{"in":"path","name":"workspace_id","required":true,"schema":{"title":"Workspace Id","type":"string"}}],"responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Replace workspace pull-through priorities","tags":["documents"]}},"/docs":{"get":{"operationId":"docs_alias_docs_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Backward-compatible docs URLs.","tags":["default"]}},"/openapi.json":{"get":{"operationId":"openapi_json_alias_openapi_json_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Backward-compatible OpenAPI JSON URL.","tags":["default"]}},"/redoc":{"get":{"operationId":"redoc_alias_redoc_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Backward-compatible ReDoc URL.","tags":["default"]}},"/swagger":{"get":{"operationId":"docs_alias_swagger_get","responses":{"422":{"content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ValidationErrorModel"},"type":"array"}}},"description":"Unprocessable Entity"}},"summary":"Backward-compatible docs URLs.","tags":["default"]}}},"tags":[{"description":"Test endpoints","name":"test"},{"description":"Document operations","name":"documents"},{"description":"Signal operations","name":"signals"},{"description":"Persona operations","name":"personas"},{"description":"Alert operations","name":"alerts"},{"description":"Auto tag operations","name":"auto_tags"},{"description":"Custom report operations","name":"reports"}]}
