# Settings

## Get retention policy

> Get the workspace retention policy.\
> \
> Returns HIPAA-compliant defaults (2190 days / 6 years) for any field\
> not explicitly configured. Advisory in v1 — no automated deletion.\
> \
> Permissions: authenticated (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"RetentionPolicyResponse":{"properties":{"call_recordings_days":{"type":"integer","title":"Call Recordings Days"},"call_transcripts_days":{"type":"integer","title":"Call Transcripts Days"},"audit_log_days":{"type":"integer","title":"Audit Log Days"},"world_events_days":{"type":"integer","title":"World Events Days"},"phi_data_days":{"type":"integer","title":"Phi Data Days"},"legal_hold":{"type":"boolean","title":"Legal Hold"},"legal_hold_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Legal Hold Reason"}},"type":"object","required":["call_recordings_days","call_transcripts_days","audit_log_days","world_events_days","phi_data_days","legal_hold"],"title":"RetentionPolicyResponse"}}},"paths":{"/v1/{workspace_id}/settings/retention":{"get":{"tags":["Settings"],"summary":"Get retention policy","description":"Get the workspace retention policy.\n\nReturns HIPAA-compliant defaults (2190 days / 6 years) for any field\nnot explicitly configured. Advisory in v1 — no automated deletion.\n\nPermissions: authenticated (any role).","operationId":"get-retention-policy","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionPolicyResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update retention policy

> Update the workspace retention policy.\
> \
> Partial updates supported — only provided fields are changed.\
> Advisory in v1: policy is stored and displayed but no automated\
> deletion is performed. Legal hold overrides all retention.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"RetentionPolicyRequest":{"properties":{"call_recordings_days":{"anyOf":[{"type":"integer","maximum":36500,"minimum":365},{"type":"null"}],"title":"Call Recordings Days"},"call_transcripts_days":{"anyOf":[{"type":"integer","maximum":36500,"minimum":365},{"type":"null"}],"title":"Call Transcripts Days"},"audit_log_days":{"anyOf":[{"type":"integer","maximum":36500,"minimum":365},{"type":"null"}],"title":"Audit Log Days"},"world_events_days":{"anyOf":[{"type":"integer","maximum":36500,"minimum":365},{"type":"null"}],"title":"World Events Days"},"phi_data_days":{"anyOf":[{"type":"integer","maximum":36500,"minimum":365},{"type":"null"}],"title":"Phi Data Days"},"legal_hold":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Legal Hold"},"legal_hold_reason":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]}},"type":"object","title":"RetentionPolicyRequest"},"DescriptionString":{"type":"string","maxLength":2000},"RetentionPolicyResponse":{"properties":{"call_recordings_days":{"type":"integer","title":"Call Recordings Days"},"call_transcripts_days":{"type":"integer","title":"Call Transcripts Days"},"audit_log_days":{"type":"integer","title":"Audit Log Days"},"world_events_days":{"type":"integer","title":"World Events Days"},"phi_data_days":{"type":"integer","title":"Phi Data Days"},"legal_hold":{"type":"boolean","title":"Legal Hold"},"legal_hold_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Legal Hold Reason"}},"type":"object","required":["call_recordings_days","call_transcripts_days","audit_log_days","world_events_days","phi_data_days","legal_hold"],"title":"RetentionPolicyResponse"}}},"paths":{"/v1/{workspace_id}/settings/retention":{"put":{"tags":["Settings"],"summary":"Update retention policy","description":"Update the workspace retention policy.\n\nPartial updates supported — only provided fields are changed.\nAdvisory in v1: policy is stored and displayed but no automated\ndeletion is performed. Legal hold overrides all retention.\n\nPermissions: admin, owner.","operationId":"update-retention-policy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionPolicyRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RetentionPolicyResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get connector settings

> Get connector definitions for this workspace.\
> \
> Permissions: authenticated (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"ConnectorSettingsResponse":{"properties":{"connectors":{"items":{"$ref":"#/components/schemas/ConnectorDef"},"type":"array","title":"Connectors"}},"type":"object","required":["connectors"],"title":"ConnectorSettingsResponse","description":"Response for GET /v1/{ws}/settings/connectors."},"ConnectorDef":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","maxLength":256,"minLength":1,"title":"Name"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"source_type":{"type":"string","enum":["ehr","fhir_store","smart_fhir","rest_api","webhook","file_drop","lakebase_schema"],"title":"Source Type"},"connection_config":{"additionalProperties":true,"type":"object","title":"Connection Config"},"entity_types":{"items":{"type":"string"},"type":"array","title":"Entity Types"},"field_mappings":{"additionalProperties":true,"type":"object","title":"Field Mappings"},"sync_strategy":{"type":"string","enum":["manual","scheduled","webhook","continuous","polling"],"title":"Sync Strategy","default":"manual"},"sync_schedule":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sync Schedule"},"is_active":{"type":"boolean","title":"Is Active","default":true},"connector_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connector Type"},"outbound_entity_types":{"items":{"type":"string"},"type":"array","title":"Outbound Entity Types"}},"type":"object","required":["name","source_type"],"title":"ConnectorDef","description":"A single connector definition stored in platform.connector_configs."}}},"paths":{"/v1/{workspace_id}/settings/connectors":{"get":{"tags":["Settings"],"summary":"Get connector settings","description":"Get connector definitions for this workspace.\n\nPermissions: authenticated (any role).","operationId":"get-connector-settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSettingsResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update connector settings

> Replace all connector definitions for this workspace.\
> \
> Validates connection\_config per source\_type. Syncs world.data\_sources\
> index for FK compatibility.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"ConnectorSettingsRequest":{"properties":{"connectors":{"items":{"$ref":"#/components/schemas/ConnectorDef"},"type":"array","maxItems":100,"title":"Connectors"}},"type":"object","required":["connectors"],"title":"ConnectorSettingsRequest","description":"Request for PUT /v1/{ws}/settings/connectors.\n\nReplaces the entire connector list."},"ConnectorDef":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","maxLength":256,"minLength":1,"title":"Name"},"display_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Display Name"},"source_type":{"type":"string","enum":["ehr","fhir_store","smart_fhir","rest_api","webhook","file_drop","lakebase_schema"],"title":"Source Type"},"connection_config":{"additionalProperties":true,"type":"object","title":"Connection Config"},"entity_types":{"items":{"type":"string"},"type":"array","title":"Entity Types"},"field_mappings":{"additionalProperties":true,"type":"object","title":"Field Mappings"},"sync_strategy":{"type":"string","enum":["manual","scheduled","webhook","continuous","polling"],"title":"Sync Strategy","default":"manual"},"sync_schedule":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sync Schedule"},"is_active":{"type":"boolean","title":"Is Active","default":true},"connector_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connector Type"},"outbound_entity_types":{"items":{"type":"string"},"type":"array","title":"Outbound Entity Types"}},"type":"object","required":["name","source_type"],"title":"ConnectorDef","description":"A single connector definition stored in platform.connector_configs."},"ConnectorSettingsResponse":{"properties":{"connectors":{"items":{"$ref":"#/components/schemas/ConnectorDef"},"type":"array","title":"Connectors"}},"type":"object","required":["connectors"],"title":"ConnectorSettingsResponse","description":"Response for GET /v1/{ws}/settings/connectors."}}},"paths":{"/v1/{workspace_id}/settings/connectors":{"put":{"tags":["Settings"],"summary":"Update connector settings","description":"Replace all connector definitions for this workspace.\n\nValidates connection_config per source_type. Syncs world.data_sources\nindex for FK compatibility.\n\nPermissions: admin, owner.","operationId":"update-connector-settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectorSettingsResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get gap scanner settings

> Get the workspace gap scanner settings.\
> \
> Returns defaults when not configured. Gap scanner is disabled by default.\
> \
> Permissions: authenticated (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"GapScannerSettingsResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"scan_interval_seconds":{"type":"integer","title":"Scan Interval Seconds"},"appointment_lookahead_hours":{"type":"integer","title":"Appointment Lookahead Hours"},"cooldown_hours":{"type":"integer","title":"Cooldown Hours"},"max_surfaces_per_tick":{"type":"integer","title":"Max Surfaces Per Tick"},"max_pending_surfaces":{"type":"integer","title":"Max Pending Surfaces"},"min_completion_rate":{"type":"number","title":"Min Completion Rate"},"channel_optimization":{"type":"boolean","title":"Channel Optimization"},"requirements":{"items":{"$ref":"#/components/schemas/GapRequirement-Output"},"type":"array","title":"Requirements"}},"type":"object","required":["enabled","scan_interval_seconds","appointment_lookahead_hours","cooldown_hours","max_surfaces_per_tick","max_pending_surfaces","min_completion_rate","channel_optimization","requirements"],"title":"GapScannerSettingsResponse"},"GapRequirement-Output":{"properties":{"name":{"$ref":"#/components/schemas/NameString"},"entity_type":{"type":"string","const":"person","title":"Entity Type","default":"person"},"trigger":{"type":"string","enum":["upcoming_appointment","recent_interaction"],"title":"Trigger","default":"upcoming_appointment"},"required_fields":{"items":{"$ref":"#/components/schemas/GapRequiredField"},"type":"array","maxItems":50,"minItems":1,"title":"Required Fields"},"channel":{"$ref":"#/components/schemas/ChannelType","default":"email"},"priority":{"type":"string","enum":["low","normal","high"],"title":"Priority","default":"normal"},"surface_title":{"anyOf":[{"$ref":"#/components/schemas/NameString"},{"type":"null"}],"description":"Title for generated surfaces. Defaults to requirement name."},"surface_description":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]}},"type":"object","required":["name","required_fields"],"title":"GapRequirement","description":"A named gap detection rule."},"NameString":{"type":"string","maxLength":256,"minLength":1},"GapRequiredField":{"properties":{"path":{"type":"string","maxLength":256,"minLength":1,"title":"Path","description":"Dot-notation path into entity state"},"label":{"$ref":"#/components/schemas/NameString"},"field_type":{"$ref":"#/components/schemas/FieldType","default":"text"},"min_items":{"anyOf":[{"type":"integer","maximum":100,"minimum":0},{"type":"null"}],"title":"Min Items","description":"For list fields, minimum items required"}},"type":"object","required":["path","label"],"title":"GapRequiredField","description":"A field that must be present in entity state."},"FieldType":{"type":"string","enum":["text","textarea","date","phone","email","number","select","multiselect","checkbox","photo","signature","file","heading","info"],"title":"FieldType","description":"Input field types for surface data collection."},"ChannelType":{"type":"string","enum":["email","web","sms"],"title":"ChannelType","description":"Delivery channels for surfaces."},"DescriptionString":{"type":"string","maxLength":2000}}},"paths":{"/v1/{workspace_id}/settings/gap-scanner":{"get":{"tags":["Settings"],"summary":"Get gap scanner settings","description":"Get the workspace gap scanner settings.\n\nReturns defaults when not configured. Gap scanner is disabled by default.\n\nPermissions: authenticated (any role).","operationId":"get-gap-scanner-settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GapScannerSettingsResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update gap scanner settings

> Update the workspace gap scanner settings.\
> \
> Partial updates supported — only provided fields are changed.\
> Requirements list is replaced entirely when provided (not merged).\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"GapScannerSettingsRequest":{"properties":{"enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Enabled"},"scan_interval_seconds":{"anyOf":[{"type":"integer","maximum":86400,"minimum":60},{"type":"null"}],"title":"Scan Interval Seconds"},"appointment_lookahead_hours":{"anyOf":[{"type":"integer","maximum":720,"minimum":1},{"type":"null"}],"title":"Appointment Lookahead Hours"},"cooldown_hours":{"anyOf":[{"type":"integer","maximum":8760,"minimum":1},{"type":"null"}],"title":"Cooldown Hours"},"max_surfaces_per_tick":{"anyOf":[{"type":"integer","maximum":100,"minimum":1},{"type":"null"}],"title":"Max Surfaces Per Tick"},"max_pending_surfaces":{"anyOf":[{"type":"integer","maximum":50,"minimum":0},{"type":"null"}],"title":"Max Pending Surfaces","description":"Max non-terminal surfaces per entity (0 = disabled)"},"min_completion_rate":{"anyOf":[{"type":"number","maximum":1,"minimum":0},{"type":"null"}],"title":"Min Completion Rate","description":"Min historical completion rate to create new surfaces (0.0 = disabled)"},"channel_optimization":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Channel Optimization","description":"Use entity preferred channel over static requirement channel"},"requirements":{"anyOf":[{"items":{"$ref":"#/components/schemas/GapRequirement-Input"},"type":"array","maxItems":100},{"type":"null"}],"title":"Requirements"}},"type":"object","title":"GapScannerSettingsRequest"},"GapRequirement-Input":{"properties":{"name":{"$ref":"#/components/schemas/NameString"},"entity_type":{"type":"string","const":"person","title":"Entity Type","default":"person"},"trigger":{"type":"string","enum":["upcoming_appointment","recent_interaction"],"title":"Trigger","default":"upcoming_appointment"},"required_fields":{"items":{"$ref":"#/components/schemas/GapRequiredField"},"type":"array","maxItems":50,"minItems":1,"title":"Required Fields"},"channel":{"$ref":"#/components/schemas/ChannelType","default":"email"},"priority":{"type":"string","enum":["low","normal","high"],"title":"Priority","default":"normal"},"surface_title":{"anyOf":[{"$ref":"#/components/schemas/NameString"},{"type":"null"}],"description":"Title for generated surfaces. Defaults to requirement name."},"surface_description":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]}},"type":"object","required":["name","required_fields"],"title":"GapRequirement","description":"A named gap detection rule."},"NameString":{"type":"string","maxLength":256,"minLength":1},"GapRequiredField":{"properties":{"path":{"type":"string","maxLength":256,"minLength":1,"title":"Path","description":"Dot-notation path into entity state"},"label":{"$ref":"#/components/schemas/NameString"},"field_type":{"$ref":"#/components/schemas/FieldType","default":"text"},"min_items":{"anyOf":[{"type":"integer","maximum":100,"minimum":0},{"type":"null"}],"title":"Min Items","description":"For list fields, minimum items required"}},"type":"object","required":["path","label"],"title":"GapRequiredField","description":"A field that must be present in entity state."},"FieldType":{"type":"string","enum":["text","textarea","date","phone","email","number","select","multiselect","checkbox","photo","signature","file","heading","info"],"title":"FieldType","description":"Input field types for surface data collection."},"ChannelType":{"type":"string","enum":["email","web","sms"],"title":"ChannelType","description":"Delivery channels for surfaces."},"DescriptionString":{"type":"string","maxLength":2000},"GapScannerSettingsResponse":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"scan_interval_seconds":{"type":"integer","title":"Scan Interval Seconds"},"appointment_lookahead_hours":{"type":"integer","title":"Appointment Lookahead Hours"},"cooldown_hours":{"type":"integer","title":"Cooldown Hours"},"max_surfaces_per_tick":{"type":"integer","title":"Max Surfaces Per Tick"},"max_pending_surfaces":{"type":"integer","title":"Max Pending Surfaces"},"min_completion_rate":{"type":"number","title":"Min Completion Rate"},"channel_optimization":{"type":"boolean","title":"Channel Optimization"},"requirements":{"items":{"$ref":"#/components/schemas/GapRequirement-Output"},"type":"array","title":"Requirements"}},"type":"object","required":["enabled","scan_interval_seconds","appointment_lookahead_hours","cooldown_hours","max_surfaces_per_tick","max_pending_surfaces","min_completion_rate","channel_optimization","requirements"],"title":"GapScannerSettingsResponse"},"GapRequirement-Output":{"properties":{"name":{"$ref":"#/components/schemas/NameString"},"entity_type":{"type":"string","const":"person","title":"Entity Type","default":"person"},"trigger":{"type":"string","enum":["upcoming_appointment","recent_interaction"],"title":"Trigger","default":"upcoming_appointment"},"required_fields":{"items":{"$ref":"#/components/schemas/GapRequiredField"},"type":"array","maxItems":50,"minItems":1,"title":"Required Fields"},"channel":{"$ref":"#/components/schemas/ChannelType","default":"email"},"priority":{"type":"string","enum":["low","normal","high"],"title":"Priority","default":"normal"},"surface_title":{"anyOf":[{"$ref":"#/components/schemas/NameString"},{"type":"null"}],"description":"Title for generated surfaces. Defaults to requirement name."},"surface_description":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]}},"type":"object","required":["name","required_fields"],"title":"GapRequirement","description":"A named gap detection rule."}}},"paths":{"/v1/{workspace_id}/settings/gap-scanner":{"put":{"tags":["Settings"],"summary":"Update gap scanner settings","description":"Update the workspace gap scanner settings.\n\nPartial updates supported — only provided fields are changed.\nRequirements list is replaced entirely when provided (not merged).\n\nPermissions: admin, owner.","operationId":"update-gap-scanner-settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GapScannerSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GapScannerSettingsResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Preview gap detection (dry run)

> Dry-run gap detection — returns entities with missing fields without creating surfaces.\
> \
> Proxies to connector-runner /internal/gap-scanner/preview.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"GapScannerPreviewRequest":{"properties":{"limit":{"type":"integer","maximum":200,"minimum":1,"title":"Limit","default":50}},"type":"object","title":"GapScannerPreviewRequest"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"}}},"paths":{"/v1/{workspace_id}/settings/gap-scanner/preview":{"post":{"tags":["Settings"],"summary":"Preview gap detection (dry run)","description":"Dry-run gap detection — returns entities with missing fields without creating surfaces.\n\nProxies to connector-runner /internal/gap-scanner/preview.\n\nPermissions: admin, owner.","operationId":"gap-scanner-preview","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/GapScannerPreviewRequest"},{"type":"null"}],"title":"Body"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Gap-Scanner-Preview"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"429":{"description":"Rate limited"},"503":{"description":"Connector runner unavailable"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Trigger one scan tick

> Trigger one scan tick immediately — creates surfaces for detected gaps.\
> \
> Proxies to connector-runner /internal/gap-scanner/scan.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}}},"paths":{"/v1/{workspace_id}/settings/gap-scanner/scan":{"post":{"tags":["Settings"],"summary":"Trigger one scan tick","description":"Trigger one scan tick immediately — creates surfaces for detected gaps.\n\nProxies to connector-runner /internal/gap-scanner/scan.\n\nPermissions: admin, owner.","operationId":"gap-scanner-scan","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Gap-Scanner-Scan"}}}},"429":{"description":"Rate limited"},"503":{"description":"Connector runner unavailable"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get memory dimension settings

> Get the workspace memory dimension settings.\
> \
> Returns built-in defaults when not configured.\
> \
> Permissions: authenticated (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"MemorySettingsResponse":{"properties":{"dimensions":{"items":{"$ref":"#/components/schemas/MemoryDimension"},"type":"array","title":"Dimensions"},"backfill_requested":{"type":"boolean","title":"Backfill Requested"}},"type":"object","required":["dimensions","backfill_requested"],"title":"MemorySettingsResponse"},"MemoryDimension":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$","title":"Key","description":"Lowercase slug used as column key (e.g. 'clinical', 'cosmetic_preference')"},"name":{"$ref":"#/components/schemas/NameString"},"description":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]},"event_types":{"items":{"type":"string"},"type":"array","maxItems":100,"minItems":1,"title":"Event Types","description":"Event types to scan (e.g. 'patient.created', 'condition.created', 'surface.submitted')"},"extract_paths":{"items":{"type":"string"},"type":"array","maxItems":50,"title":"Extract Paths","description":"JSONB paths for static extraction (e.g. '$.active_conditions'). Ignored when extraction_mode='llm'."},"extraction_mode":{"type":"string","enum":["static","llm"],"title":"Extraction Mode","description":"'static' uses extract_paths (fast, free). 'llm' uses ai_extract with description as prompt (semantic, incremental).","default":"static"},"weight":{"type":"number","maximum":10,"minimum":0,"title":"Weight","description":"Relative importance for scoring (higher = more important)","default":1},"active":{"type":"boolean","title":"Active","default":true},"builtin":{"type":"boolean","title":"Builtin","description":"True for platform-provided dimensions (read-only key)","default":false}},"type":"object","required":["key","name","event_types"],"title":"MemoryDimension","description":"A single memory dimension — defines what facts to extract from events.\n\nTwo extraction modes:\n- static: uses extract_paths (JSONPath) for fast, free extraction\n- llm: uses ai_extract with the dimension description as prompt\n  for semantic extraction. Only runs on new events (incremental MV refresh)."},"NameString":{"type":"string","maxLength":256,"minLength":1},"DescriptionString":{"type":"string","maxLength":2000}}},"paths":{"/v1/{workspace_id}/settings/memory":{"get":{"tags":["Settings"],"summary":"Get memory dimension settings","description":"Get the workspace memory dimension settings.\n\nReturns built-in defaults when not configured.\n\nPermissions: authenticated (any role).","operationId":"get-memory-settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemorySettingsResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update memory dimension settings

> Update the workspace memory dimension settings.\
> \
> Partial updates supported — only provided fields are changed.\
> The dimensions list is replaced entirely when provided.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"MemorySettingsRequest":{"properties":{"dimensions":{"anyOf":[{"items":{"$ref":"#/components/schemas/MemoryDimension"},"type":"array"},{"type":"null"}],"title":"Dimensions"},"backfill_requested":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Backfill Requested"}},"type":"object","title":"MemorySettingsRequest","description":"Partial update — only provided fields are changed.\n\nThe dimensions list is replaced entirely when provided.\nBuilt-in dimensions can be deactivated (active=false) or have their\nweight changed, but their key cannot be reused for custom dimensions."},"MemoryDimension":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$","title":"Key","description":"Lowercase slug used as column key (e.g. 'clinical', 'cosmetic_preference')"},"name":{"$ref":"#/components/schemas/NameString"},"description":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]},"event_types":{"items":{"type":"string"},"type":"array","maxItems":100,"minItems":1,"title":"Event Types","description":"Event types to scan (e.g. 'patient.created', 'condition.created', 'surface.submitted')"},"extract_paths":{"items":{"type":"string"},"type":"array","maxItems":50,"title":"Extract Paths","description":"JSONB paths for static extraction (e.g. '$.active_conditions'). Ignored when extraction_mode='llm'."},"extraction_mode":{"type":"string","enum":["static","llm"],"title":"Extraction Mode","description":"'static' uses extract_paths (fast, free). 'llm' uses ai_extract with description as prompt (semantic, incremental).","default":"static"},"weight":{"type":"number","maximum":10,"minimum":0,"title":"Weight","description":"Relative importance for scoring (higher = more important)","default":1},"active":{"type":"boolean","title":"Active","default":true},"builtin":{"type":"boolean","title":"Builtin","description":"True for platform-provided dimensions (read-only key)","default":false}},"type":"object","required":["key","name","event_types"],"title":"MemoryDimension","description":"A single memory dimension — defines what facts to extract from events.\n\nTwo extraction modes:\n- static: uses extract_paths (JSONPath) for fast, free extraction\n- llm: uses ai_extract with the dimension description as prompt\n  for semantic extraction. Only runs on new events (incremental MV refresh)."},"NameString":{"type":"string","maxLength":256,"minLength":1},"DescriptionString":{"type":"string","maxLength":2000},"MemorySettingsResponse":{"properties":{"dimensions":{"items":{"$ref":"#/components/schemas/MemoryDimension"},"type":"array","title":"Dimensions"},"backfill_requested":{"type":"boolean","title":"Backfill Requested"}},"type":"object","required":["dimensions","backfill_requested"],"title":"MemorySettingsResponse"}}},"paths":{"/v1/{workspace_id}/settings/memory":{"put":{"tags":["Settings"],"summary":"Update memory dimension settings","description":"Update the workspace memory dimension settings.\n\nPartial updates supported — only provided fields are changed.\nThe dimensions list is replaced entirely when provided.\n\nPermissions: admin, owner.","operationId":"update-memory-settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemorySettingsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemorySettingsResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get metric definitions

> Get the workspace metric definitions.\
> \
> Returns built-in defaults when not configured.\
> \
> Permissions: authenticated (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"MetricSettingsResponse":{"properties":{"definitions":{"items":{"$ref":"#/components/schemas/MetricDefinition"},"type":"array","title":"Definitions"}},"type":"object","required":["definitions"],"title":"MetricSettingsResponse"},"MetricDefinition":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$","title":"Key","description":"Lowercase slug used as metric key (e.g. 'voice_quality_score')"},"name":{"$ref":"#/components/schemas/NameString"},"description":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]},"metric_type":{"type":"string","enum":["numerical","categorical","boolean"],"title":"Metric Type"},"latency_tier":{"type":"string","enum":["streaming","near_realtime","batch"],"title":"Latency Tier","description":"'streaming' — seconds-latency via ZeroBus streaming ingestion (continuous pipeline). 'near_realtime' — minutes-latency via triggered pipeline refresh. 'batch' — hourly/daily scheduled refresh (default, cheapest).","default":"batch"},"period_granularity":{"type":"string","enum":["hourly","daily"],"title":"Period Granularity","description":"'hourly' — one row per workspace per hour. Use for near_realtime metrics where shift-level visibility matters (voice quality, latency). 'daily' — one row per workspace per day (default, cheapest).","default":"daily"},"source":{"type":"string","enum":["call_intelligence","world_events","surface_events","emotion_events","connector_events","zerobus_events","voice_judge_results","custom"],"title":"Source","description":"Source key for the producer that supplies this metric. Built-ins include 'call_intelligence', 'world_events', and 'surface_events'. Use 'custom' with custom_source_key for extension producers."},"custom_source_key":{"anyOf":[{"type":"string","maxLength":128,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$"},{"type":"null"}],"title":"Custom Source Key","description":"Extension source key used only when source='custom'."},"event_types":{"items":{"type":"string"},"type":"array","maxItems":100,"minItems":1,"title":"Event Types","description":"Event types to scan (e.g. 'call.outcome', 'surface.submitted'). For call_intelligence source, use pseudo-types: 'call_intelligence.row'."},"source_filter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Filter","description":"Optional SQL WHERE fragment for additional filtering (e.g. \"source = 'voice_agent'\"). Applied after event_type filter."},"extraction_mode":{"type":"string","enum":["static","ai_classify","ai_extract","ai_query","sql_expr"],"title":"Extraction Mode","description":"'static' — JSONB path extraction (fast, free). 'ai_classify' — AI classification into user-defined labels (free). 'ai_extract' — AI field extraction from text (free). 'ai_query' — LLM-powered extraction with custom prompt (uses model_tier). 'sql_expr' — Raw SQL expression for computed metrics.","default":"static"},"extract_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Extract Path","description":"JSON path for static extraction (e.g. `$.quality_score`, `$.risk_level`). For `call_intelligence` and `world_events`, single-segment paths resolve to typed columns when available and fall back to JSONB extraction otherwise. Used when `extraction_mode='static'`."},"ai_labels":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":500},{"type":"null"}],"title":"Ai Labels","description":"Labels for ai_classify (categories) or ai_extract (field names). Required when extraction_mode='ai_classify' or 'ai_extract'. Examples: ['positive', 'negative', 'neutral'] or ['diagnosis', 'medication']."},"ai_schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Ai Schema","description":"Extraction schema for ai_extract. Required when extraction_mode='ai_extract'."},"ai_query_endpoint":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Ai Query Endpoint","description":"Model serving endpoint for ai_query. Optional — if omitted, platform resolves from model_tier automatically. Override for custom endpoints."},"ai_query_prompt":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}],"title":"Ai Query Prompt","description":"Prompt template for ai_query. Use {data} placeholder for event data. Example: 'Classify this call transcript into one of: {labels}. Transcript: {data}'. Budgeted at 8KB to hold the full rubric + output spec for standard quality judges (longest authored rubric — conversational_naturalness — is ~5KB)."},"sql_expression":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Sql Expression","description":"Raw SQL expression evaluated in pipeline context. Has access to all columns in the source table. Example: 'CASE WHEN duration_seconds > 120 THEN 1.0 ELSE 0.0 END'. Required when extraction_mode='sql_expr'."},"aggregation":{"type":"string","enum":["count","sum","avg","min","max","count_distinct","ratio","rate"],"title":"Aggregation","description":"How to aggregate extracted values per workspace per period. 'ratio' requires ratio_numerator_event and ratio_denominator_event. 'rate' computes count(true) / count(all) for boolean metrics.","default":"count"},"ratio_numerator_event":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ratio Numerator Event","description":"Event type for numerator when aggregation='ratio'."},"ratio_denominator_event":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ratio Denominator Event","description":"Event type for denominator when aggregation='ratio'."},"valid_range_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valid Range Min","description":"Minimum valid value for numerical metrics. Pipeline drops values outside range."},"valid_range_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valid Range Max","description":"Maximum valid value for numerical metrics."},"freshness_sla_minutes":{"type":"integer","maximum":1440,"minimum":5,"title":"Freshness Sla Minutes","description":"Max acceptable staleness in minutes before alerting. Default: 60 (1 hour).","default":60},"unit":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Unit","description":"Display unit (e.g. 'score', 'minutes', '%', 'count')."},"categories":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":100},{"type":"null"}],"title":"Categories","description":"Allowed values for categorical metrics. Pipeline drops values not in this list when set."},"model_tier":{"type":"string","enum":["free","fast","balanced","max","custom"],"title":"Model Tier","description":"AI model tier for extraction quality/cost tradeoff. 'free' — platform managed models (ai_classify, ai_extract). 'fast' — optimized for simple classification, low latency. 'balanced' — quality scoring, moderate reasoning. 'max' — complex analysis, multi-step reasoning. 'custom' — use ai_query_endpoint directly. When extraction_mode='ai_query' and ai_query_endpoint is not set, platform resolves model_tier to the optimal model automatically.","default":"free"},"channel_scope":{"type":"string","enum":["all","voice","text","surface","inbound","outbound"],"title":"Channel Scope","description":"Business-logic channel filter. 'voice' — voice calls only. 'text' — SMS/text sessions. 'surface' — form submissions. 'inbound'/'outbound' — by direction. 'all' — no channel filter (default). Pipeline translates to appropriate source + event_type filters.","default":"all"},"applies_to_product_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Applies To Product Types","description":"Product types this metric applies to (matches service tags, e.g. 'scheduling', 'outbound', 'coaching', 'intake', 'triage', 'support'). When set, the metric only computes for calls belonging to services whose config.tags include one of these keys. When None (default), the metric applies to every service regardless of product type."},"prompt":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Prompt","description":"Rubric prompt for LLM judge evaluation with {$.path} context variables. Each {$.path} reference is extracted from the entity's projected state and substituted before sending to ai_query. The prompt is both the evaluation criteria and the context specification."},"granularity":{"type":"string","enum":["aggregate","per_entity"],"title":"Granularity","description":"'aggregate' groups by (workspace, period) — one value per time bucket. 'per_entity' keeps entity_id — one value per entity (call, encounter). Judge metrics are typically per_entity. Computed metrics are typically aggregate.","default":"aggregate"},"active":{"type":"boolean","title":"Active","default":true},"builtin":{"type":"boolean","title":"Builtin","description":"True for platform-provided metrics (read-only key).","default":false}},"type":"object","required":["key","name","metric_type","source","event_types"],"title":"MetricDefinition","description":"A single metric definition — what to extract and how.\n\nTwo broad modes:\n- Built-in metrics: extraction is handled by hardcoded pipeline logic\n  (extract_path + aggregation). Shipped with every workspace.\n- Custom metrics: extraction uses AI functions or static JSONB paths.\n  Defined per-workspace via settings API.\n\nFrozen: builtins are process-wide singletons exposed via the\n``BUILTIN_METRICS`` list. A mutable list field (e.g.\n``applies_to_product_types``) could otherwise be mutated by one caller\nand leak into every subsequent call in the same process."},"NameString":{"type":"string","maxLength":256,"minLength":1},"DescriptionString":{"type":"string","maxLength":2000}}},"paths":{"/v1/{workspace_id}/settings/metrics":{"get":{"tags":["Settings"],"summary":"Get metric definitions","description":"Get the workspace metric definitions.\n\nReturns built-in defaults when not configured.\n\nPermissions: authenticated (any role).","operationId":"get-metric-settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricSettingsResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update metric definitions

> Update the workspace metric definitions.\
> \
> Partial updates supported — only provided fields are changed.\
> The definitions list is replaced entirely when provided.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"MetricSettingsRequest":{"properties":{"definitions":{"anyOf":[{"items":{"$ref":"#/components/schemas/MetricDefinition"},"type":"array"},{"type":"null"}],"title":"Definitions"}},"type":"object","title":"MetricSettingsRequest","description":"Partial update — only provided fields are changed.\n\nThe definitions list is replaced entirely when provided.\nBuilt-in metrics can be deactivated (active=false) or have their\nfreshness_sla_minutes changed, but their key cannot be reused\nfor custom metrics."},"MetricDefinition":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","maxLength":64,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$","title":"Key","description":"Lowercase slug used as metric key (e.g. 'voice_quality_score')"},"name":{"$ref":"#/components/schemas/NameString"},"description":{"anyOf":[{"$ref":"#/components/schemas/DescriptionString"},{"type":"null"}]},"metric_type":{"type":"string","enum":["numerical","categorical","boolean"],"title":"Metric Type"},"latency_tier":{"type":"string","enum":["streaming","near_realtime","batch"],"title":"Latency Tier","description":"'streaming' — seconds-latency via ZeroBus streaming ingestion (continuous pipeline). 'near_realtime' — minutes-latency via triggered pipeline refresh. 'batch' — hourly/daily scheduled refresh (default, cheapest).","default":"batch"},"period_granularity":{"type":"string","enum":["hourly","daily"],"title":"Period Granularity","description":"'hourly' — one row per workspace per hour. Use for near_realtime metrics where shift-level visibility matters (voice quality, latency). 'daily' — one row per workspace per day (default, cheapest).","default":"daily"},"source":{"type":"string","enum":["call_intelligence","world_events","surface_events","emotion_events","connector_events","zerobus_events","voice_judge_results","custom"],"title":"Source","description":"Source key for the producer that supplies this metric. Built-ins include 'call_intelligence', 'world_events', and 'surface_events'. Use 'custom' with custom_source_key for extension producers."},"custom_source_key":{"anyOf":[{"type":"string","maxLength":128,"minLength":1,"pattern":"^[a-z][a-z0-9_]*$"},{"type":"null"}],"title":"Custom Source Key","description":"Extension source key used only when source='custom'."},"event_types":{"items":{"type":"string"},"type":"array","maxItems":100,"minItems":1,"title":"Event Types","description":"Event types to scan (e.g. 'call.outcome', 'surface.submitted'). For call_intelligence source, use pseudo-types: 'call_intelligence.row'."},"source_filter":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Filter","description":"Optional SQL WHERE fragment for additional filtering (e.g. \"source = 'voice_agent'\"). Applied after event_type filter."},"extraction_mode":{"type":"string","enum":["static","ai_classify","ai_extract","ai_query","sql_expr"],"title":"Extraction Mode","description":"'static' — JSONB path extraction (fast, free). 'ai_classify' — AI classification into user-defined labels (free). 'ai_extract' — AI field extraction from text (free). 'ai_query' — LLM-powered extraction with custom prompt (uses model_tier). 'sql_expr' — Raw SQL expression for computed metrics.","default":"static"},"extract_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Extract Path","description":"JSON path for static extraction (e.g. `$.quality_score`, `$.risk_level`). For `call_intelligence` and `world_events`, single-segment paths resolve to typed columns when available and fall back to JSONB extraction otherwise. Used when `extraction_mode='static'`."},"ai_labels":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":500},{"type":"null"}],"title":"Ai Labels","description":"Labels for ai_classify (categories) or ai_extract (field names). Required when extraction_mode='ai_classify' or 'ai_extract'. Examples: ['positive', 'negative', 'neutral'] or ['diagnosis', 'medication']."},"ai_schema":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Ai Schema","description":"Extraction schema for ai_extract. Required when extraction_mode='ai_extract'."},"ai_query_endpoint":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Ai Query Endpoint","description":"Model serving endpoint for ai_query. Optional — if omitted, platform resolves from model_tier automatically. Override for custom endpoints."},"ai_query_prompt":{"anyOf":[{"type":"string","maxLength":8000},{"type":"null"}],"title":"Ai Query Prompt","description":"Prompt template for ai_query. Use {data} placeholder for event data. Example: 'Classify this call transcript into one of: {labels}. Transcript: {data}'. Budgeted at 8KB to hold the full rubric + output spec for standard quality judges (longest authored rubric — conversational_naturalness — is ~5KB)."},"sql_expression":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Sql Expression","description":"Raw SQL expression evaluated in pipeline context. Has access to all columns in the source table. Example: 'CASE WHEN duration_seconds > 120 THEN 1.0 ELSE 0.0 END'. Required when extraction_mode='sql_expr'."},"aggregation":{"type":"string","enum":["count","sum","avg","min","max","count_distinct","ratio","rate"],"title":"Aggregation","description":"How to aggregate extracted values per workspace per period. 'ratio' requires ratio_numerator_event and ratio_denominator_event. 'rate' computes count(true) / count(all) for boolean metrics.","default":"count"},"ratio_numerator_event":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ratio Numerator Event","description":"Event type for numerator when aggregation='ratio'."},"ratio_denominator_event":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ratio Denominator Event","description":"Event type for denominator when aggregation='ratio'."},"valid_range_min":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valid Range Min","description":"Minimum valid value for numerical metrics. Pipeline drops values outside range."},"valid_range_max":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Valid Range Max","description":"Maximum valid value for numerical metrics."},"freshness_sla_minutes":{"type":"integer","maximum":1440,"minimum":5,"title":"Freshness Sla Minutes","description":"Max acceptable staleness in minutes before alerting. Default: 60 (1 hour).","default":60},"unit":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Unit","description":"Display unit (e.g. 'score', 'minutes', '%', 'count')."},"categories":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":100},{"type":"null"}],"title":"Categories","description":"Allowed values for categorical metrics. Pipeline drops values not in this list when set."},"model_tier":{"type":"string","enum":["free","fast","balanced","max","custom"],"title":"Model Tier","description":"AI model tier for extraction quality/cost tradeoff. 'free' — platform managed models (ai_classify, ai_extract). 'fast' — optimized for simple classification, low latency. 'balanced' — quality scoring, moderate reasoning. 'max' — complex analysis, multi-step reasoning. 'custom' — use ai_query_endpoint directly. When extraction_mode='ai_query' and ai_query_endpoint is not set, platform resolves model_tier to the optimal model automatically.","default":"free"},"channel_scope":{"type":"string","enum":["all","voice","text","surface","inbound","outbound"],"title":"Channel Scope","description":"Business-logic channel filter. 'voice' — voice calls only. 'text' — SMS/text sessions. 'surface' — form submissions. 'inbound'/'outbound' — by direction. 'all' — no channel filter (default). Pipeline translates to appropriate source + event_type filters.","default":"all"},"applies_to_product_types":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Applies To Product Types","description":"Product types this metric applies to (matches service tags, e.g. 'scheduling', 'outbound', 'coaching', 'intake', 'triage', 'support'). When set, the metric only computes for calls belonging to services whose config.tags include one of these keys. When None (default), the metric applies to every service regardless of product type."},"prompt":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Prompt","description":"Rubric prompt for LLM judge evaluation with {$.path} context variables. Each {$.path} reference is extracted from the entity's projected state and substituted before sending to ai_query. The prompt is both the evaluation criteria and the context specification."},"granularity":{"type":"string","enum":["aggregate","per_entity"],"title":"Granularity","description":"'aggregate' groups by (workspace, period) — one value per time bucket. 'per_entity' keeps entity_id — one value per entity (call, encounter). Judge metrics are typically per_entity. Computed metrics are typically aggregate.","default":"aggregate"},"active":{"type":"boolean","title":"Active","default":true},"builtin":{"type":"boolean","title":"Builtin","description":"True for platform-provided metrics (read-only key).","default":false}},"type":"object","required":["key","name","metric_type","source","event_types"],"title":"MetricDefinition","description":"A single metric definition — what to extract and how.\n\nTwo broad modes:\n- Built-in metrics: extraction is handled by hardcoded pipeline logic\n  (extract_path + aggregation). Shipped with every workspace.\n- Custom metrics: extraction uses AI functions or static JSONB paths.\n  Defined per-workspace via settings API.\n\nFrozen: builtins are process-wide singletons exposed via the\n``BUILTIN_METRICS`` list. A mutable list field (e.g.\n``applies_to_product_types``) could otherwise be mutated by one caller\nand leak into every subsequent call in the same process."},"NameString":{"type":"string","maxLength":256,"minLength":1},"DescriptionString":{"type":"string","maxLength":2000},"MetricSettingsResponse":{"properties":{"definitions":{"items":{"$ref":"#/components/schemas/MetricDefinition"},"type":"array","title":"Definitions"}},"type":"object","required":["definitions"],"title":"MetricSettingsResponse"}}},"paths":{"/v1/{workspace_id}/settings/metrics":{"put":{"tags":["Settings"],"summary":"Update metric definitions","description":"Update the workspace metric definitions.\n\nPartial updates supported — only provided fields are changed.\nThe definitions list is replaced entirely when provided.\n\nPermissions: admin, owner.","operationId":"update-metric-settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MetricSettingsResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get outreach settings

> Get the workspace outreach settings.\
> \
> Returns empty rules and templates when not configured.\
> \
> Permissions: authenticated (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"OutreachSettingsResponse":{"properties":{"rules":{"items":{"$ref":"#/components/schemas/OutreachRule"},"type":"array","title":"Rules"},"data_templates":{"items":{"$ref":"#/components/schemas/DataTemplate-Output"},"type":"array","title":"Data Templates"}},"type":"object","required":["rules","data_templates"],"title":"OutreachSettingsResponse"},"OutreachRule":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"$ref":"#/components/schemas/NameString"},"trigger":{"type":"string","enum":["appointment_window","post_visit","gap_detected","form_intake","manual"],"title":"Trigger","default":"appointment_window"},"trigger_config":{"additionalProperties":true,"type":"object","title":"Trigger Config","description":"Trigger-specific config (hours_before, hours_after, etc.)"},"channel":{"$ref":"#/components/schemas/ChannelType","default":"email"},"consent_required":{"type":"boolean","title":"Consent Required","default":true},"quiet_hours":{"$ref":"#/components/schemas/QuietHours"},"review_required":{"type":"boolean","title":"Review Required","default":false},"message_template":{"type":"string","maxLength":1600,"title":"Message Template","default":"Hi {first_name}, please complete your form: {surface_url}"},"data_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Data Template Id"},"form_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Form Template Id"},"active":{"type":"boolean","title":"Active","default":true}},"type":"object","required":["name"],"title":"OutreachRule","description":"A single outreach rule — defines WHEN, WHAT, and HOW to reach a patient."},"NameString":{"type":"string","maxLength":256,"minLength":1},"ChannelType":{"type":"string","enum":["email","web","sms"],"title":"ChannelType","description":"Delivery channels for surfaces."},"QuietHours":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":false},"start_hour":{"type":"integer","maximum":23,"minimum":0,"title":"Start Hour","default":21},"end_hour":{"type":"integer","maximum":23,"minimum":0,"title":"End Hour","default":8},"timezone":{"type":"string","maxLength":64,"title":"Timezone","default":"America/New_York"}},"type":"object","title":"QuietHours","description":"Quiet hours — no outbound outreach during this window."},"DataTemplate-Output":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"$ref":"#/components/schemas/NameString"},"fields":{"items":{"$ref":"#/components/schemas/DataTemplateField"},"type":"array","maxItems":50,"minItems":1,"title":"Fields"}},"type":"object","required":["name","fields"],"title":"DataTemplate","description":"Named field template — reusable across multiple outreach rules."},"DataTemplateField":{"properties":{"key":{"type":"string","maxLength":128,"minLength":1,"title":"Key"},"label":{"$ref":"#/components/schemas/NameString"},"field_type":{"$ref":"#/components/schemas/FieldType","default":"text"},"required":{"type":"boolean","title":"Required","default":true},"sensitive":{"type":"boolean","title":"Sensitive","default":false},"path":{"type":"string","maxLength":256,"minLength":1,"title":"Path","description":"Dot-notation path into entity state (e.g. demographics.date_of_birth)"}},"type":"object","required":["key","label","path"],"title":"DataTemplateField","description":"A field in a data template — maps to entity state path for gap detection."},"FieldType":{"type":"string","enum":["text","textarea","date","phone","email","number","select","multiselect","checkbox","photo","signature","file","heading","info"],"title":"FieldType","description":"Input field types for surface data collection."}}},"paths":{"/v1/{workspace_id}/settings/outreach":{"get":{"tags":["Settings"],"summary":"Get outreach settings","description":"Get the workspace outreach settings.\n\nReturns empty rules and templates when not configured.\n\nPermissions: authenticated (any role).","operationId":"get-outreach-settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutreachSettingsResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update outreach settings

> Update the workspace outreach settings.\
> \
> Partial updates supported — only provided fields are changed.\
> Rules and data\_templates lists are replaced entirely when provided.\
> \
> Validates that data\_template\_id references in rules point to\
> templates that exist in the same payload or current settings.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"OutreachSettingsRequest":{"properties":{"rules":{"anyOf":[{"items":{"$ref":"#/components/schemas/OutreachRule"},"type":"array"},{"type":"null"}],"title":"Rules"},"data_templates":{"anyOf":[{"items":{"$ref":"#/components/schemas/DataTemplate-Input"},"type":"array"},{"type":"null"}],"title":"Data Templates"}},"type":"object","title":"OutreachSettingsRequest","description":"Partial update — only provided fields are changed.\n\nRules and data_templates lists are replaced entirely when provided."},"OutreachRule":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"$ref":"#/components/schemas/NameString"},"trigger":{"type":"string","enum":["appointment_window","post_visit","gap_detected","form_intake","manual"],"title":"Trigger","default":"appointment_window"},"trigger_config":{"additionalProperties":true,"type":"object","title":"Trigger Config","description":"Trigger-specific config (hours_before, hours_after, etc.)"},"channel":{"$ref":"#/components/schemas/ChannelType","default":"email"},"consent_required":{"type":"boolean","title":"Consent Required","default":true},"quiet_hours":{"$ref":"#/components/schemas/QuietHours"},"review_required":{"type":"boolean","title":"Review Required","default":false},"message_template":{"type":"string","maxLength":1600,"title":"Message Template","default":"Hi {first_name}, please complete your form: {surface_url}"},"data_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Data Template Id"},"form_template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Form Template Id"},"active":{"type":"boolean","title":"Active","default":true}},"type":"object","required":["name"],"title":"OutreachRule","description":"A single outreach rule — defines WHEN, WHAT, and HOW to reach a patient."},"NameString":{"type":"string","maxLength":256,"minLength":1},"ChannelType":{"type":"string","enum":["email","web","sms"],"title":"ChannelType","description":"Delivery channels for surfaces."},"QuietHours":{"properties":{"enabled":{"type":"boolean","title":"Enabled","default":false},"start_hour":{"type":"integer","maximum":23,"minimum":0,"title":"Start Hour","default":21},"end_hour":{"type":"integer","maximum":23,"minimum":0,"title":"End Hour","default":8},"timezone":{"type":"string","maxLength":64,"title":"Timezone","default":"America/New_York"}},"type":"object","title":"QuietHours","description":"Quiet hours — no outbound outreach during this window."},"DataTemplate-Input":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"$ref":"#/components/schemas/NameString"},"fields":{"items":{"$ref":"#/components/schemas/DataTemplateField"},"type":"array","maxItems":50,"minItems":1,"title":"Fields"}},"type":"object","required":["name","fields"],"title":"DataTemplate","description":"Named field template — reusable across multiple outreach rules."},"DataTemplateField":{"properties":{"key":{"type":"string","maxLength":128,"minLength":1,"title":"Key"},"label":{"$ref":"#/components/schemas/NameString"},"field_type":{"$ref":"#/components/schemas/FieldType","default":"text"},"required":{"type":"boolean","title":"Required","default":true},"sensitive":{"type":"boolean","title":"Sensitive","default":false},"path":{"type":"string","maxLength":256,"minLength":1,"title":"Path","description":"Dot-notation path into entity state (e.g. demographics.date_of_birth)"}},"type":"object","required":["key","label","path"],"title":"DataTemplateField","description":"A field in a data template — maps to entity state path for gap detection."},"FieldType":{"type":"string","enum":["text","textarea","date","phone","email","number","select","multiselect","checkbox","photo","signature","file","heading","info"],"title":"FieldType","description":"Input field types for surface data collection."},"OutreachSettingsResponse":{"properties":{"rules":{"items":{"$ref":"#/components/schemas/OutreachRule"},"type":"array","title":"Rules"},"data_templates":{"items":{"$ref":"#/components/schemas/DataTemplate-Output"},"type":"array","title":"Data Templates"}},"type":"object","required":["rules","data_templates"],"title":"OutreachSettingsResponse"},"DataTemplate-Output":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"$ref":"#/components/schemas/NameString"},"fields":{"items":{"$ref":"#/components/schemas/DataTemplateField"},"type":"array","maxItems":50,"minItems":1,"title":"Fields"}},"type":"object","required":["name","fields"],"title":"DataTemplate","description":"Named field template — reusable across multiple outreach rules."}}},"paths":{"/v1/{workspace_id}/settings/outreach":{"put":{"tags":["Settings"],"summary":"Update outreach settings","description":"Update the workspace outreach settings.\n\nPartial updates supported — only provided fields are changed.\nRules and data_templates lists are replaced entirely when provided.\n\nValidates that data_template_id references in rules point to\ntemplates that exist in the same payload or current settings.\n\nPermissions: admin, owner.","operationId":"update-outreach-settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutreachSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutreachSettingsResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get workspace branding

> Get the workspace default branding for surfaces.\
> \
> Returns empty branding when not configured.\
> \
> Permissions: authenticated (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"BrandingSettingsResponse":{"properties":{"branding":{"$ref":"#/components/schemas/BrandingConfig"}},"type":"object","required":["branding"],"title":"BrandingSettingsResponse"},"BrandingConfig":{"properties":{"logo_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Logo Url"},"primary_color":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Primary Color"},"background_color":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Background Color"},"font_family":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Font Family"}},"type":"object","title":"BrandingConfig","description":"Visual branding for patient-facing surfaces."}}},"paths":{"/v1/{workspace_id}/settings/branding":{"get":{"tags":["Settings"],"summary":"Get workspace branding","description":"Get the workspace default branding for surfaces.\n\nReturns empty branding when not configured.\n\nPermissions: authenticated (any role).","operationId":"get-branding-settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingSettingsResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update workspace branding

> Update the workspace default branding for surfaces.\
> \
> Surface-level branding takes precedence over workspace-level branding.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"BrandingSettingsRequest":{"properties":{"branding":{"$ref":"#/components/schemas/BrandingConfig"}},"type":"object","required":["branding"],"title":"BrandingSettingsRequest","description":"Update workspace branding. All fields are optional — only provided\nfields are changed."},"BrandingConfig":{"properties":{"logo_url":{"anyOf":[{"type":"string","maxLength":2048},{"type":"null"}],"title":"Logo Url"},"primary_color":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Primary Color"},"background_color":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Background Color"},"font_family":{"anyOf":[{"type":"string","maxLength":256},{"type":"null"}],"title":"Font Family"}},"type":"object","title":"BrandingConfig","description":"Visual branding for patient-facing surfaces."},"BrandingSettingsResponse":{"properties":{"branding":{"$ref":"#/components/schemas/BrandingConfig"}},"type":"object","required":["branding"],"title":"BrandingSettingsResponse"}}},"paths":{"/v1/{workspace_id}/settings/branding":{"put":{"tags":["Settings"],"summary":"Update workspace branding","description":"Update the workspace default branding for surfaces.\n\nSurface-level branding takes precedence over workspace-level branding.\n\nPermissions: admin, owner.","operationId":"update-branding-settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BrandingSettingsResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get environment overrides

> Get per-environment config overrides.\
> \
> Returns empty environments when not configured.\
> \
> Permissions: authenticated (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"EnvironmentSettingsResponse":{"properties":{"environments":{"additionalProperties":{"$ref":"#/components/schemas/EnvironmentOverrides"},"type":"object","title":"Environments"}},"type":"object","title":"EnvironmentSettingsResponse"},"EnvironmentOverrides":{"properties":{"data_source_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Data Source Id"},"tool_overrides":{"additionalProperties":true,"type":"object","title":"Tool Overrides"},"data_source_overrides":{"additionalProperties":true,"type":"object","title":"Data Source Overrides"}},"type":"object","title":"EnvironmentOverrides","description":"Per-environment config overrides merged at runtime."}}},"paths":{"/v1/{workspace_id}/settings/environments":{"get":{"tags":["Settings"],"summary":"Get environment overrides","description":"Get per-environment config overrides.\n\nReturns empty environments when not configured.\n\nPermissions: authenticated (any role).","operationId":"get-environment-settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentSettingsResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update environment overrides

> Update per-environment config overrides.\
> \
> Permissions: admin, owner.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"EnvironmentSettingsRequest":{"properties":{"environments":{"additionalProperties":{"$ref":"#/components/schemas/EnvironmentOverrides"},"type":"object","title":"Environments"}},"type":"object","required":["environments"],"title":"EnvironmentSettingsRequest"},"EnvironmentOverrides":{"properties":{"data_source_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Data Source Id"},"tool_overrides":{"additionalProperties":true,"type":"object","title":"Tool Overrides"},"data_source_overrides":{"additionalProperties":true,"type":"object","title":"Data Source Overrides"}},"type":"object","title":"EnvironmentOverrides","description":"Per-environment config overrides merged at runtime."},"EnvironmentSettingsResponse":{"properties":{"environments":{"additionalProperties":{"$ref":"#/components/schemas/EnvironmentOverrides"},"type":"object","title":"Environments"}},"type":"object","title":"EnvironmentSettingsResponse"}}},"paths":{"/v1/{workspace_id}/settings/environments":{"put":{"tags":["Settings"],"summary":"Update environment overrides","description":"Update per-environment config overrides.\n\nPermissions: admin, owner.","operationId":"update-environment-settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnvironmentSettingsResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Get voice settings

> Get the voice experience settings for a workspace.\
> \
> Returns voice identity, domain vocabulary, and post-call intelligence\
> configuration. These settings shape how the AI agent sounds and what\
> domain-specific terms it recognizes accurately.\
> \
> \#### Permissions\
> \* Requires authenticated API key (any role).

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"VoiceSettingsResponse":{"properties":{"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice Id"},"tone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tone"},"speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Speed"},"volume":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Volume"},"language":{"type":"string","title":"Language"},"keyterms":{"items":{"type":"string"},"type":"array","title":"Keyterms"},"correction_categories":{"items":{"type":"string"},"type":"array","title":"Correction Categories"},"pronunciation_dict_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pronunciation Dict Id"},"sensitive_topics":{"items":{"type":"string"},"type":"array","title":"Sensitive Topics"},"post_call_analysis_enabled":{"type":"boolean","title":"Post Call Analysis Enabled"},"transcript_correction_enabled":{"type":"boolean","title":"Transcript Correction Enabled"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object"},{"type":"null"}],"title":"Language Providers"}},"type":"object","required":["voice_id","tone","speed","volume","language","keyterms","correction_categories","pronunciation_dict_id","sensitive_topics","post_call_analysis_enabled","transcript_correction_enabled","tts_provider","tts_config"],"title":"VoiceSettingsResponse","description":"Voice experience state — what the PM configured."},"LanguageProviderEntry":{"properties":{"provider":{"type":"string","enum":["cartesia","elevenlabs","groq"],"title":"Provider"},"config":{"additionalProperties":true,"type":"object","maxProperties":20,"title":"Config"}},"type":"object","required":["provider"],"title":"LanguageProviderEntry","description":"Per-language TTS provider configuration."}}},"paths":{"/v1/{workspace_id}/settings/voice":{"get":{"tags":["Settings"],"summary":"Get voice settings","description":"Get the voice experience settings for a workspace.\n\nReturns voice identity, domain vocabulary, and post-call intelligence\nconfiguration. These settings shape how the AI agent sounds and what\ndomain-specific terms it recognizes accurately.\n\n#### Permissions\n* Requires authenticated API key (any role).","operationId":"get-voice-settings","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceSettingsResponse"}}}},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```

## Update voice settings

> Update the voice experience settings for a workspace.\
> \
> Only provided fields are updated; omitted fields retain their current\
> values. Set a field to \`\`null\`\` to reset it to default.\
> \
> \*\*Voice Identity & Style\*\*\
> \- \*\*voice\_id\*\*: Voice identity UUID — determines the agent's voice persona\
> \- \*\*tone\*\*: Emotional baseline (\`\`calm\`\`, \`\`sympathetic\`\`,\
> &#x20; \`\`enthusiastic\`\`, \`\`content\`\`, \`\`curious\`\`, \`\`cheerful\`\`,\
> &#x20; \`\`serious\`\`, \`\`friendly\`\`). The system also adapts tone dynamically\
> &#x20; based on real-time caller emotion analysis; this setting provides\
> &#x20; the baseline when no strong emotional signal is detected.\
> \- \*\*speed\*\*: Speech rate multiplier (0.5-2.0)\
> \- \*\*volume\*\*: Volume multiplier (0.0-1.0)\
> \- \*\*language\*\*: BCP-47 language tag (default \`\`en\`\`)\
> \
> \*\*Speech Recognition Boost\*\*\
> \- \*\*keyterms\*\*: Exact words the speech recognition engine should\
> &#x20; prioritize. Use for specific names, drug names, and org jargon.\
> &#x20; Example: \`\`\["Dr. Ramirez", "metformin", "HIPAA"]\`\`\
> \
> \*\*Audio Correction Hints\*\*\
> \- \*\*correction\_categories\*\*: Broad categories of things callers\
> &#x20; commonly say that speech-to-text gets wrong. Not exact words —\
> &#x20; just what \*kinds\* of things to watch for. Example:\
> &#x20; \`\`\["medication names", "insurance carriers", "doctor last names"]\`\`\
> \
> \*\*Post-Call Intelligence\*\*\
> \- \*\*post\_call\_analysis\_enabled\*\*: Run automated quality scoring after\
> &#x20; each call ends (default \`\`true\`\`)\
> \- \*\*transcript\_correction\_enabled\*\*: Re-verify transcripts with a\
> &#x20; high-accuracy batch model after call ends (default \`\`true\`\`)\
> \
> \#### Permissions\
> \* Requires admin or owner role.

```json
{"openapi":"3.1.0","info":{"title":"Platform API","version":"1.0.0"},"servers":[{"url":"https://api.platform.amigo.ai","description":"Production"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"type":"http","scheme":"bearer","description":"API key issued via `POST /v1/{workspace_id}/api-keys`. Pass the returned `api_key` value as a Bearer token."}},"schemas":{"VoiceSettingsRequest":{"properties":{"voice_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Voice Id"},"tone":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Tone"},"speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Speed"},"volume":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Volume"},"language":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Language"},"keyterms":{"anyOf":[{"items":{"type":"string","maxLength":128,"minLength":1},"type":"array","maxItems":200},{"type":"null"}],"title":"Keyterms"},"correction_categories":{"anyOf":[{"items":{"type":"string","maxLength":128,"minLength":1},"type":"array","maxItems":50},{"type":"null"}],"title":"Correction Categories"},"pronunciation_dict_id":{"anyOf":[{"type":"string","maxLength":128},{"type":"null"}],"title":"Pronunciation Dict Id"},"sensitive_topics":{"anyOf":[{"items":{"type":"string","maxLength":128,"minLength":1},"type":"array","maxItems":50},{"type":"null"}],"title":"Sensitive Topics"},"post_call_analysis_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Post Call Analysis Enabled"},"transcript_correction_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Transcript Correction Enabled"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object"},{"type":"null"}],"title":"Language Providers"}},"type":"object","title":"VoiceSettingsRequest","description":"Voice experience control plane — PM-facing, high-level controls.\n\nControls the caller experience without exposing engineering internals.\nEmotion detection, filler speech, model selection, and buffer tuning\nare always-on internals managed by engineering."},"LanguageProviderEntry":{"properties":{"provider":{"type":"string","enum":["cartesia","elevenlabs","groq"],"title":"Provider"},"config":{"additionalProperties":true,"type":"object","maxProperties":20,"title":"Config"}},"type":"object","required":["provider"],"title":"LanguageProviderEntry","description":"Per-language TTS provider configuration."},"VoiceSettingsResponse":{"properties":{"voice_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Voice Id"},"tone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tone"},"speed":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Speed"},"volume":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Volume"},"language":{"type":"string","title":"Language"},"keyterms":{"items":{"type":"string"},"type":"array","title":"Keyterms"},"correction_categories":{"items":{"type":"string"},"type":"array","title":"Correction Categories"},"pronunciation_dict_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pronunciation Dict Id"},"sensitive_topics":{"items":{"type":"string"},"type":"array","title":"Sensitive Topics"},"post_call_analysis_enabled":{"type":"boolean","title":"Post Call Analysis Enabled"},"transcript_correction_enabled":{"type":"boolean","title":"Transcript Correction Enabled"},"tts_provider":{"anyOf":[{"type":"string","enum":["cartesia","elevenlabs","groq"]},{"type":"null"}],"title":"Tts Provider"},"tts_config":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Tts Config"},"language_providers":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/LanguageProviderEntry"},"type":"object"},{"type":"null"}],"title":"Language Providers"}},"type":"object","required":["voice_id","tone","speed","volume","language","keyterms","correction_categories","pronunciation_dict_id","sensitive_topics","post_call_analysis_enabled","transcript_correction_enabled","tts_provider","tts_config"],"title":"VoiceSettingsResponse","description":"Voice experience state — what the PM configured."}}},"paths":{"/v1/{workspace_id}/settings/voice":{"put":{"tags":["Settings"],"summary":"Update voice settings","description":"Update the voice experience settings for a workspace.\n\nOnly provided fields are updated; omitted fields retain their current\nvalues. Set a field to ``null`` to reset it to default.\n\n**Voice Identity & Style**\n- **voice_id**: Voice identity UUID — determines the agent's voice persona\n- **tone**: Emotional baseline (``calm``, ``sympathetic``,\n  ``enthusiastic``, ``content``, ``curious``, ``cheerful``,\n  ``serious``, ``friendly``). The system also adapts tone dynamically\n  based on real-time caller emotion analysis; this setting provides\n  the baseline when no strong emotional signal is detected.\n- **speed**: Speech rate multiplier (0.5-2.0)\n- **volume**: Volume multiplier (0.0-1.0)\n- **language**: BCP-47 language tag (default ``en``)\n\n**Speech Recognition Boost**\n- **keyterms**: Exact words the speech recognition engine should\n  prioritize. Use for specific names, drug names, and org jargon.\n  Example: ``[\"Dr. Ramirez\", \"metformin\", \"HIPAA\"]``\n\n**Audio Correction Hints**\n- **correction_categories**: Broad categories of things callers\n  commonly say that speech-to-text gets wrong. Not exact words —\n  just what *kinds* of things to watch for. Example:\n  ``[\"medication names\", \"insurance carriers\", \"doctor last names\"]``\n\n**Post-Call Intelligence**\n- **post_call_analysis_enabled**: Run automated quality scoring after\n  each call ends (default ``true``)\n- **transcript_correction_enabled**: Re-verify transcripts with a\n  high-accuracy batch model after call ends (default ``true``)\n\n#### Permissions\n* Requires admin or owner role.","operationId":"update-voice-settings","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceSettingsRequest"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VoiceSettingsResponse"}}}},"404":{"description":"Workspace not found"},"422":{"description":"Validation error"},"429":{"description":"Rate limited"}},"parameters":[{"name":"workspace_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Workspace Id"}}]}}}}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.amigo.ai/api-reference/readme/platform/settings.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
