{"openapi":"3.1.0","info":{"title":"Colony Segmentation","description":"\nBehaviour-led listener segmentation for Colony LIVE radio stations.\n\n## Documentation\n- [API Guide](/docs/api-guide)\n- [ReDoc](/redoc)\n\n## What it does\nAutomatically segments radio station listeners into named behavioural\ngroups based on their engagement history — no manual tagging required.\nCombines RFM scoring, semantic vector search and AI inference to build\na complete audience intelligence layer.\n\n## Segments\n- **new_listener** — First interaction within the last 7 days\n- **super_fan** — Recent, frequent, multi-channel, growing\n- **show_loyalist** — Consistent same-show engagement\n- **competition_chaser** — 70%+ competition entries\n- **occasional_engager** — Active within 30 days\n- **at_risk** — Was active, now declining\n- **dormant** — No recent engagement\n\n## Quick links\n- [Filter listeners](/api/v1/segments/{company_id}/filter)\n- [Segment insights](/api/v1/segments/{company_id}/insights)\n- [Tag distribution](/api/v1/segments/{company_id}/tags)\n- [Semantic search](/api/v1/segments/{company_id}/search)\n- [AI segment insights](/api/v1/ai/segments/{company_id}/insights)\n- [AI listener profile](/api/v1/ai/listeners/{company_id}/{originator})\n- [AI custom segment](/api/v1/ai/segments/{company_id}/custom-segment)\n- [Promote demographics](/api/v1/ai/listeners/{company_id}/{originator}/promote-demographics)\n- [Churn risk](/api/v1/intelligence/listeners/{company_id}/{originator}/churn-risk)\n- [Similar listeners](/api/v1/intelligence/listeners/{company_id}/{originator}/similar)\n- [Segment audience profile](/api/v1/intelligence/segments/{company_id}/{segment_key}/profile)\n- [Campaign recommendation](/api/v1/agent/{company_id}/recommend)\n- [Parse advertiser brief](/api/v1/agent/{company_id}/parse-brief)\n- [Aggregate listeners](/api/v1/segments/{company_id}/aggregate)\n- [Profile completeness](/api/v1/segments/{company_id}/completeness)\n- [Export listeners](/api/v1/segments/{company_id}/export)\n- [Cross channel engagement](/api/v1/segments/{company_id}/cross-channel)\n","version":"2.0.0"},"paths":{"/health":{"get":{"tags":["health"],"summary":"Health Check","description":"Health check endpoint.\nConfirms the API is running, MongoDB and Qdrant are reachable.","operationId":"health_check_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}}}}},"/api/v1/segments/{company_id}/summary":{"get":{"tags":["segments"],"summary":"Station Summary","description":"Aggregated summary for the producer dashboard.\nShows total listeners and counts per segment.","operationId":"station_summary_api_v1_segments__company_id__summary_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}":{"get":{"tags":["segments"],"summary":"List Segments","description":"Full segment breakdown with average stats per segment.","operationId":"list_segments_api_v1_segments__company_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}/insights":{"get":{"tags":["segments"],"summary":"Station Insights","description":"Segment distribution with percentages and plain English\nexplanations for the producer dashboard.","operationId":"station_insights_api_v1_segments__company_id__insights_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}/tags":{"get":{"tags":["segments"],"summary":"Segment Tags","description":"Returns all tags and their counts per segment.","operationId":"segment_tags_api_v1_segments__company_id__tags_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}/aggregate":{"get":{"tags":["analytics"],"summary":"Aggregate Listeners","description":"Breakdown counts for the filtered dataset. No pagination.\n\ntimeslot_counts is {title, count} per ID, not a plain number —\nthe filter chip needs the real show name.","operationId":"aggregate_listeners_api_v1_segments__company_id__aggregate_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"segment","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Segment"}},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Gender"}},{"name":"age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Age Group"}},{"name":"ethnicity","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Ethnicity"}},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Language"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"channel_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Channel Type"}},{"name":"inferred_lsm","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Inferred Lsm"}},{"name":"campaign_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Campaign Type"}},{"name":"peak_time_of_day","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Peak Time Of Day"}},{"name":"primary_day_of_week","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Primary Day Of Week"}},{"name":"peak_month","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Peak Month"}},{"name":"public_holiday","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Public Holiday"}},{"name":"timeslot_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Timeslot Id"}},{"name":"missing_fields","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Missing Fields"}},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags"}},{"name":"originator","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Originator"}},{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},{"name":"income_bracket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Income Bracket"}},{"name":"education","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Education"}},{"name":"employment_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Employment Status"}},{"name":"inferred_gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Gender"}},{"name":"inferred_age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Age Group"}},{"name":"inferred_location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Location"}},{"name":"inferred_language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Language"}},{"name":"inferred_interests","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Interests"}},{"name":"has_channel","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Has Channel"}},{"name":"peak_hour","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Peak Hour"}},{"name":"last_interaction_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction After"}},{"name":"last_interaction_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction Before"}},{"name":"permission","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Permission"}},{"name":"opt_in","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Opt In"}},{"name":"profile_complete","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Profile Complete"}},{"name":"weekday_pattern","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Weekday Pattern"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}/completeness":{"get":{"tags":["analytics"],"summary":"Profile Completeness","description":"Declared-profile completeness stats, scoped to active filters.\n\n\"Complete\" means all 9 declared fields are filled — mobile\nnumber, gender, age, location, language, ethnicity, name, email,\nID number. Declared only, never falls back to inferred values.","operationId":"profile_completeness_api_v1_segments__company_id__completeness_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"segment","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Segment"}},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Gender"}},{"name":"age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Age Group"}},{"name":"ethnicity","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Ethnicity"}},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Language"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"channel_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Channel Type"}},{"name":"inferred_lsm","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Inferred Lsm"}},{"name":"campaign_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Campaign Type"}},{"name":"peak_time_of_day","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Peak Time Of Day"}},{"name":"primary_day_of_week","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Primary Day Of Week"}},{"name":"peak_month","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Peak Month"}},{"name":"public_holiday","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Public Holiday"}},{"name":"timeslot_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Timeslot Id"}},{"name":"missing_fields","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Missing Fields"}},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags"}},{"name":"originator","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Originator"}},{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},{"name":"income_bracket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Income Bracket"}},{"name":"education","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Education"}},{"name":"employment_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Employment Status"}},{"name":"inferred_gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Gender"}},{"name":"inferred_age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Age Group"}},{"name":"inferred_location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Location"}},{"name":"inferred_language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Language"}},{"name":"inferred_interests","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Interests"}},{"name":"has_channel","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Has Channel"}},{"name":"peak_hour","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Peak Hour"}},{"name":"last_interaction_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction After"}},{"name":"last_interaction_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction Before"}},{"name":"permission","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Permission"}},{"name":"opt_in","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Opt In"}},{"name":"profile_complete","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Profile Complete"}},{"name":"weekday_pattern","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Weekday Pattern"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}/cross-channel":{"get":{"tags":["analytics"],"summary":"Cross Channel Engagement","description":"Cross-channel co-engagement matrix — how many listeners are\nactive on each pair of channels, with uniques and percentages.","operationId":"cross_channel_engagement_api_v1_segments__company_id__cross_channel_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"segment","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Segment"}},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Gender"}},{"name":"age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Age Group"}},{"name":"ethnicity","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Ethnicity"}},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Language"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"channel_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Channel Type"}},{"name":"inferred_lsm","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Inferred Lsm"}},{"name":"campaign_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Campaign Type"}},{"name":"peak_time_of_day","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Peak Time Of Day"}},{"name":"primary_day_of_week","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Primary Day Of Week"}},{"name":"peak_month","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Peak Month"}},{"name":"public_holiday","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Public Holiday"}},{"name":"timeslot_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Timeslot Id"}},{"name":"missing_fields","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Missing Fields"}},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags"}},{"name":"originator","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Originator"}},{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},{"name":"income_bracket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Income Bracket"}},{"name":"education","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Education"}},{"name":"employment_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Employment Status"}},{"name":"inferred_gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Gender"}},{"name":"inferred_age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Age Group"}},{"name":"inferred_location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Location"}},{"name":"inferred_language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Language"}},{"name":"inferred_interests","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Interests"}},{"name":"has_channel","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Has Channel"}},{"name":"peak_hour","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Peak Hour"}},{"name":"last_interaction_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction After"}},{"name":"last_interaction_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction Before"}},{"name":"permission","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Permission"}},{"name":"opt_in","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Opt In"}},{"name":"profile_complete","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Profile Complete"}},{"name":"weekday_pattern","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Weekday Pattern"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}/export":{"get":{"tags":["export"],"summary":"Export Listeners","description":"All matching listener records for a filter set. No pagination.\n\nchannel_pair: comma-separated pair of channel_type ints — only\nreturns listeners active on BOTH channels.","operationId":"export_listeners_api_v1_segments__company_id__export_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"channel_pair","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Channel Pair"}},{"name":"segment","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Segment"}},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Gender"}},{"name":"age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Age Group"}},{"name":"ethnicity","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Ethnicity"}},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Language"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"channel_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Channel Type"}},{"name":"inferred_lsm","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Inferred Lsm"}},{"name":"campaign_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Campaign Type"}},{"name":"peak_time_of_day","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Peak Time Of Day"}},{"name":"primary_day_of_week","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Primary Day Of Week"}},{"name":"peak_month","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Peak Month"}},{"name":"public_holiday","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Public Holiday"}},{"name":"timeslot_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Timeslot Id"}},{"name":"missing_fields","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Missing Fields"}},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags"}},{"name":"originator","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Originator"}},{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},{"name":"income_bracket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Income Bracket"}},{"name":"education","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Education"}},{"name":"employment_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Employment Status"}},{"name":"inferred_gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Gender"}},{"name":"inferred_age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Age Group"}},{"name":"inferred_location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Location"}},{"name":"inferred_language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Language"}},{"name":"inferred_interests","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Interests"}},{"name":"has_channel","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Has Channel"}},{"name":"peak_hour","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Peak Hour"}},{"name":"last_interaction_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction After"}},{"name":"last_interaction_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction Before"}},{"name":"permission","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Permission"}},{"name":"opt_in","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Opt In"}},{"name":"profile_complete","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Profile Complete"}},{"name":"weekday_pattern","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Weekday Pattern"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}/filter":{"get":{"tags":["filter"],"summary":"Filter Listeners","description":"Filter listeners by any combination of segment, tags,\ndeclared demographics, AI-inferred demographics, contact\ndetails, channel usage, engagement recency, and show/timeslot.\n\nFilter groups:\n    Segment       segment, tags\n    Declared      gender, age_group, ethnicity, language,\n                  income_bracket, education, employment_status,\n                  location\n    Contact       email, name\n    Inferred      inferred_gender, inferred_age_group,\n                  inferred_language, inferred_ethnicity,\n                  inferred_income_bracket, inferred_lsm,\n                  inferred_location, inferred_interests\n    Channel       channel_type (primary only),\n                  has_channel (used at any point, not just primary)\n    Engagement    peak_time_of_day, permission, opt_in,\n                  last_interaction_after, last_interaction_before\n    Show          timeslot_id\n\nExamples:\n    /filter?segment=show_loyalist&tags=morning_listener,whatsapp_preferred\n    /filter?gender=Female&age_group=25-34&language=isiZulu\n    /filter?inferred_gender=Male&inferred_interests=automotive,sport\n    /filter?inferred_lsm=upper-middle&opt_in=true\n    /filter?has_channel=9&segment=super_fan\n    /filter?timeslot_id=14\n    /filter?last_interaction_after=2026-06-01T00:00:00\n    /filter?email=john&name=Smith","operationId":"filter_listeners_api_v1_segments__company_id__filter_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"page","in":"query","required":false,"schema":{"type":"integer","minimum":1,"default":1,"title":"Page"}},{"name":"page_size","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Page Size"}},{"name":"segment","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Segment"}},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Gender"}},{"name":"age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Age Group"}},{"name":"ethnicity","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Ethnicity"}},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Language"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Location"}},{"name":"channel_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Channel Type"}},{"name":"inferred_lsm","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Inferred Lsm"}},{"name":"campaign_type","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Campaign Type"}},{"name":"peak_time_of_day","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Peak Time Of Day"}},{"name":"primary_day_of_week","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Primary Day Of Week"}},{"name":"peak_month","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Peak Month"}},{"name":"public_holiday","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Public Holiday"}},{"name":"timeslot_id","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"integer"}},{"type":"null"}],"title":"Timeslot Id"}},{"name":"missing_fields","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"type":"string"}},{"type":"null"}],"title":"Missing Fields"}},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags"}},{"name":"originator","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Originator"}},{"name":"email","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"}},{"name":"name","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"}},{"name":"income_bracket","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Income Bracket"}},{"name":"education","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Education"}},{"name":"employment_status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Employment Status"}},{"name":"inferred_gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Gender"}},{"name":"inferred_age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Age Group"}},{"name":"inferred_location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Location"}},{"name":"inferred_language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Language"}},{"name":"inferred_interests","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Interests"}},{"name":"has_channel","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Has Channel"}},{"name":"peak_hour","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Peak Hour"}},{"name":"last_interaction_after","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction After"}},{"name":"last_interaction_before","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction Before"}},{"name":"permission","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Permission"}},{"name":"opt_in","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Opt In"}},{"name":"profile_complete","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Profile Complete"}},{"name":"weekday_pattern","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Weekday Pattern"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/listeners/{company_id}/{originator}":{"get":{"tags":["listeners"],"summary":"Get Listener Profile","description":"Returns the full behavioural profile and current segment\nfor one listener at a station.","operationId":"get_listener_profile_api_v1_listeners__company_id___originator__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"originator","in":"path","required":true,"schema":{"type":"string","title":"Originator"}},{"name":"db","in":"query","required":false,"schema":{"title":"Db"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["listeners"],"summary":"Erase Listener Profile","description":"POPIA erasure request — pseudonymises a listener profile.\n\nClears all personally identifiable information while preserving\nanonymised behavioural data for station analytics.\n\nCannot be undone.","operationId":"erase_listener_profile_api_v1_listeners__company_id___originator__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"originator","in":"path","required":true,"schema":{"type":"string","title":"Originator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/segments/{company_id}/search":{"get":{"tags":["search"],"summary":"Semantic Search","description":"Search for listeners using a natural language query.\n\nCombines semantic similarity with optional filters.\nResults are sorted by relevance score (highest first).\n\nParameters:\n    q           Natural language search query (required)\n    min_score   Minimum similarity score 0.0–1.0 (default: 0.68)\n                Higher = stricter matching, fewer but more confident results\n                Lower = broader matching, more results with less certainty\n    limit       Max listeners to return (default: 100, max: 1000)\n    segment     Filter by segment key (e.g. dormant, super_fan)\n    tags        Comma-separated tags - listener must have ALL (e.g. whatsapp_preferred,morning_listener)\n    gender      Filter by gender (e.g. Female, Male)\n    age_group   Filter by age group (e.g. 25-34, 35-49)\n    location    Filter by location - partial match, case-insensitive\n    language    Filter by language (e.g. isiZulu, English)\n\nExamples:\n    /search?q=listeners who love soccer\n    /search?q=people interested in buying a car&segment=occasional_engager\n    /search?q=insurance shoppers&gender=Female&age_group=25-34&limit=200\n    /search?q=music lovers&min_score=0.65","operationId":"semantic_search_api_v1_segments__company_id__search_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"q","in":"query","required":true,"schema":{"type":"string","title":"Q"}},{"name":"min_score","in":"query","required":false,"schema":{"type":"number","default":0.68,"title":"Min Score"}},{"name":"segment","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Segment"}},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags"}},{"name":"gender","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Gender"}},{"name":"age_group","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Age Group"}},{"name":"location","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location"}},{"name":"language","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/segments/{company_id}/insights":{"get":{"tags":["ai"],"summary":"Ai Segment Insights","description":"Generates AI-powered plain English insights for all segments.\nExplains what each segment means and recommends actions.","operationId":"ai_segment_insights_api_v1_ai_segments__company_id__insights_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/listeners/{company_id}/{originator}":{"get":{"tags":["ai"],"summary":"Ai Listener Profile","description":"Returns AI-powered demographic inference and interest tagging\nfor a single listener.\n\nCaching strategy:\n    - First call: runs AI inference, saves to MongoDB\n    - Subsequent calls within 30 days: returns cached result\n    - After 30 days: re-runs inference and updates cache\n\nThis keeps OpenAI costs low — only pays per unique listener view,\nnot per profile in bulk.","operationId":"ai_listener_profile_api_v1_ai_listeners__company_id___originator__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"originator","in":"path","required":true,"schema":{"type":"string","title":"Originator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/segments/{company_id}/custom-segment":{"post":{"tags":["ai"],"summary":"Custom Segment","description":"Build a custom audience segment using plain English.\n\nAI interprets the request, generates search queries,\nruns them against Qdrant and returns matching listeners.\n\nExample:\n    POST /api/v1/ai/segments/8/custom-segment\n    {\n        \"theme\": \"pet lovers\",\n        \"description\": \"listeners who own dogs or cats\",\n        \"limit\": 200\n    }","operationId":"custom_segment_api_v1_ai_segments__company_id__custom_segment_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomSegmentRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/ai/listeners/{company_id}/{originator}/promote-demographics":{"put":{"tags":["ai"],"summary":"Promote Demographics","description":"Promotes AI-inferred demographics to declared demographics.\n\nOnly promotes fields where:\n- The inferred value exists (not None)\n- The declared field is currently None (never overwrites declared data)\n- Confidence score is >= 0.70\n\nCannot be undone — use with care.","operationId":"promote_demographics_api_v1_ai_listeners__company_id___originator__promote_demographics_put","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"originator","in":"path","required":true,"schema":{"type":"string","title":"Originator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/audiences/{company_id}":{"post":{"tags":["audiences"],"summary":"Create Custom Audience","description":"Creates a named custom audience using AI-powered semantic search.\n\nAI interprets the theme, generates search queries and finds\nmatching listeners. Results are saved and can be refreshed\nany time to pick up new listeners.\n\nExample:\n    POST /api/v1/audiences/8\n    {\n        \"name\": \"Colony FM Pet Lovers\",\n        \"theme\": \"pet lovers\",\n        \"description\": \"listeners who own dogs or cats\",\n        \"limit\": 500,\n        \"expiry_days\": 30\n    }","operationId":"create_custom_audience_api_v1_audiences__company_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAudienceRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"get":{"tags":["audiences"],"summary":"List Custom Audiences","description":"Lists all custom audiences for a company.\nMember lists are excluded for performance — use the detail endpoint.","operationId":"list_custom_audiences_api_v1_audiences__company_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/audiences/{company_id}/{audience_id}":{"get":{"tags":["audiences"],"summary":"Get Custom Audience","description":"Returns a single audience with its full member list\nenriched with profile data from MongoDB.","operationId":"get_custom_audience_api_v1_audiences__company_id___audience_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"audience_id","in":"path","required":true,"schema":{"type":"string","title":"Audience Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}},"delete":{"tags":["audiences"],"summary":"Delete Custom Audience","description":"Deletes a custom audience. Cannot be undone.","operationId":"delete_custom_audience_api_v1_audiences__company_id___audience_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"audience_id","in":"path","required":true,"schema":{"type":"string","title":"Audience Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/audiences/{company_id}/{audience_id}/refresh":{"put":{"tags":["audiences"],"summary":"Refresh Custom Audience","description":"Re-runs the original search strategy and updates the member list.\n\nCall this to pick up new listeners who match the audience criteria\nsince it was last created or refreshed.","operationId":"refresh_custom_audience_api_v1_audiences__company_id___audience_id__refresh_put","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"audience_id","in":"path","required":true,"schema":{"type":"string","title":"Audience Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligence/listeners/{company_id}/{originator}/churn-risk":{"get":{"tags":["intelligence"],"summary":"Listener Churn Risk","description":"Computes churn risk for a single listener.\n\nReturns a risk level (low/medium/high), a score (0-100)\nand the signals that drove the prediction.","operationId":"listener_churn_risk_api_v1_intelligence_listeners__company_id___originator__churn_risk_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"originator","in":"path","required":true,"schema":{"type":"string","title":"Originator"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligence/listeners/{company_id}/{originator}/similar":{"get":{"tags":["intelligence"],"summary":"Similar Listeners","description":"Finds listeners who behave similarly to the given listener.\n\nUses Qdrant vector similarity — listeners with similar\ncampaign history, messages and engagement patterns\nare returned ranked by similarity score.\n\nUse cases:\n    - Find more listeners like your super fans\n    - Expand a high-value audience\n    - Discover lookalike audiences for advertisers","operationId":"similar_listeners_api_v1_intelligence_listeners__company_id___originator__similar_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"originator","in":"path","required":true,"schema":{"type":"string","title":"Originator"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":20,"title":"Limit"}},{"name":"min_score","in":"query","required":false,"schema":{"type":"number","default":0.75,"title":"Min Score"}},{"name":"exclude_segment","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Exclude Segment"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/intelligence/segments/{company_id}/{segment_key}/profile":{"get":{"tags":["intelligence"],"summary":"Segment Audience Profile","description":"Builds a composite demographic and behavioural profile\nfor all listeners in a segment.\n\nAggregates declared and inferred demographics, channel\npreferences, interests and engagement patterns.\n\nUse cases:\n    - \"Who are my dormant listeners as a group?\"\n    - \"What channels does my super_fan segment prefer?\"\n    - \"What are the top interests in this segment?\"","operationId":"segment_audience_profile_api_v1_intelligence_segments__company_id___segment_key__profile_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"segment_key","in":"path","required":true,"schema":{"type":"string","title":"Segment Key"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":500,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/{company_id}/recommend":{"post":{"tags":["agent"],"summary":"Recommend Campaign","description":"Generates a campaign recommendation based on an advertiser brief\nand the station's actual audience data.\n\nUses the same shared filter system as /filter and /aggregate, so\nthe recommendation respects every active filter — segment, gender,\ncampaign type, time patterns, public holidays, completeness, etc.\n\nCaching:\n    Same brief + filter combination returns a cached result for 24 hours.\n\nThe AI:\n    1. Parses the advertiser brief into targeting criteria\n    2. Profiles the filtered station audience\n    3. Synthesises a specific, actionable campaign recommendation\n\nExample:\n    POST /api/v1/agent/184/recommend\n    {\n        \"brief\": \"Insurance advertiser targeting homeowners aged 35-49 in Gauteng\",\n        \"segment\": [\"dormant\"]\n    }","operationId":"recommend_campaign_api_v1_agent__company_id__recommend_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/{company_id}/parse-brief":{"post":{"tags":["agent"],"summary":"Parse Advertiser Brief","description":"Parses an advertiser brief into structured targeting criteria.\n\nUse this to understand what the system extracted from a brief\nbefore running a full recommendation.\n\nExample:\n    POST /api/v1/agent/184/parse-brief\n    {\n        \"brief\": \"FMCG brand targeting female listeners aged 25-34 in Gauteng\"\n    }","operationId":"parse_advertiser_brief_api_v1_agent__company_id__parse_brief_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParseBriefRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/{company_id}/credits/load":{"post":{"tags":["credits"],"summary":"Load Credits","description":"Loads credits onto a company account.\nAdmin only — requires X-Admin-Key header.\n\nExample:\n    POST /api/v1/agent/184/credits/load\n    X-Admin-Key: your-secret-key\n    { \"credits\": 1000, \"note\": \"Invoice #INV-2026-001 — R100 top-up\" }","operationId":"load_credits_api_v1_agent__company_id__credits_load_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoadCreditsRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/{company_id}/credits":{"get":{"tags":["credits"],"summary":"Get Credits","description":"Returns the current credit balance for a company.\n\nExample:\n    GET /api/v1/agent/184/credits","operationId":"get_credits_api_v1_agent__company_id__credits_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/{company_id}/credits/usage":{"get":{"tags":["credits"],"summary":"Get Usage","description":"Returns AI usage history for a company.\nOptionally filtered by date range.\n\nExample:\n    GET /api/v1/agent/184/credits/usage?from_date=2026-08-01&to_date=2026-08-31","operationId":"get_usage_api_v1_agent__company_id__credits_usage_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}},{"name":"from_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO date e.g. 2026-08-01","title":"From Date"},"description":"ISO date e.g. 2026-08-01"},{"name":"to_date","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"ISO date e.g. 2026-08-31","title":"To Date"},"description":"ISO date e.g. 2026-08-31"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/api/v1/agent/{company_id}/credits/pause":{"patch":{"tags":["credits"],"summary":"Pause Credits","description":"Pauses or unpauses AI usage for a company.\nAdmin only — requires X-Admin-Key header.\n\nExample:\n    PATCH /api/v1/agent/184/credits/pause\n    X-Admin-Key: your-secret-key\n    { \"paused\": true, \"reason\": \"Credits exhausted — top up required.\" }","operationId":"pause_credits_api_v1_agent__company_id__credits_pause_patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"integer","title":"Company Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PauseRequest"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"CreateAudienceRequest":{"properties":{"name":{"type":"string","title":"Name"},"theme":{"type":"string","title":"Theme"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"limit":{"type":"integer","title":"Limit","default":500},"min_score":{"type":"number","title":"Min Score","default":0.68},"expiry_days":{"type":"integer","title":"Expiry Days","default":30}},"type":"object","required":["name","theme"],"title":"CreateAudienceRequest"},"CustomSegmentRequest":{"properties":{"theme":{"type":"string","title":"Theme"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"limit":{"type":"integer","title":"Limit","default":100},"min_score":{"type":"number","title":"Min Score","default":0.68}},"type":"object","required":["theme"],"title":"CustomSegmentRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"LoadCreditsRequest":{"properties":{"credits":{"type":"number","title":"Credits"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["credits"],"title":"LoadCreditsRequest","description":"Request body for loading credits onto a company account."},"ParseBriefRequest":{"properties":{"brief":{"type":"string","title":"Brief"}},"type":"object","required":["brief"],"title":"ParseBriefRequest"},"PauseRequest":{"properties":{"paused":{"type":"boolean","title":"Paused"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["paused"],"title":"PauseRequest","description":"Request body for pausing or unpausing AI for a company."},"RecommendRequest":{"properties":{"brief":{"type":"string","title":"Brief"},"sample_size":{"type":"integer","title":"Sample Size","default":50},"segment":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Segment"},"gender":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Gender"},"age_group":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Age Group"},"ethnicity":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Ethnicity"},"language":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Language"},"location":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Location"},"channel_type":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Channel Type"},"campaign_type":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Campaign Type"},"tags":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tags"},"inferred_lsm":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Inferred Lsm"},"inferred_gender":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Gender"},"inferred_age_group":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Age Group"},"inferred_ethnicity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Ethnicity"},"inferred_location":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Location"},"inferred_language":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Language"},"inferred_interests":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Inferred Interests"},"peak_time_of_day":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Peak Time Of Day"},"primary_day_of_week":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Primary Day Of Week"},"peak_hour":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Peak Hour"},"peak_month":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Peak Month"},"timeslot_id":{"anyOf":[{"items":{"type":"integer"},"type":"array"},{"type":"null"}],"title":"Timeslot Id"},"public_holiday":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Public Holiday"},"weekday_pattern":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Weekday Pattern"},"permission":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Permission"},"opt_in":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Opt In"},"last_interaction_after":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction After"},"last_interaction_before":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Interaction Before"},"profile_complete":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Profile Complete"},"missing_fields":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Missing Fields"}},"type":"object","required":["brief"],"title":"RecommendRequest","description":"Request body for AI campaign recommendation.\n\nFilter fields scope the listener sample before the AI analyses it —\nso the recommendation reflects the actual target audience."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","in":"header","name":"X-Segmentation-Key"}}},"tags":[{"name":"health","description":"Service health — MongoDB, Qdrant and Ollama status"},{"name":"segments","description":"Segment summaries, insights and tag distribution"},{"name":"filter","description":"Retargeting filter — query by segment, tags, declared and inferred demographics"},{"name":"listeners","description":"Individual listener behavioural profiles and POPIA erasure"},{"name":"search","description":"Semantic listener search powered by Qdrant vector similarity"},{"name":"ai","description":"AI-powered insights —   demographic inference, custom segment builder and demographic promotion"},{"name":"audiences","description":"Custom audience segments — create, manage and refresh named audiences"},{"name":"intelligence","description":"Predictive intelligence — churn risk, lookalike audiences, audience profiling"},{"name":"agent","description":"AI agent — campaign recommendations and advertiser brief parsing"},{"name":"analytics","description":"Analytics and reporting — segment counts, completeness, cross-channel engagement and export"},{"name":"export","description":"Data export functionality — export all matching listeners for a filter set"},{"name":"credits","description":"AI credit management — load, balance, usage history and pause/unpause AI usage"}]}