openapi: 3.1.0 info: title: Amigo Account Settings API version: 0.1.0 servers: - url: https://api.amigo.ai - url: https://internal-api.amigo.ai - url: https://api-eu-central-1.amigo.ai - url: https://api-ap-southeast-2.amigo.ai - url: https://api-ca-central-1.amigo.ai security: - Bearer-Authorization: [] Bearer-Authorization-Organization: [] Basic: [] tags: - name: Settings paths: /v1/{workspace_id}/settings/retention: get: tags: - Settings summary: Get retention policy description: '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).' 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 put: tags: - Settings summary: Update retention policy description: '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 (``Workspace.update``).' 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 /v1/{workspace_id}/settings/gap-scanner: get: tags: - Settings summary: Get gap scanner settings description: 'Get the workspace gap scanner settings. Returns defaults when not configured. Gap scanner is disabled by default. Permissions: 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 put: tags: - Settings summary: Update gap scanner settings description: '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 (enforced via ``Workspace.update``, matching the outreach-settings sibling).' 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 /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. Proxies to connector-runner /internal/gap-scanner/preview. Permissions: admin, owner (enforced via ``Workspace.update``).' 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 '429': description: Rate limited '503': description: Connector runner unavailable '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' parameters: - name: workspace_id in: path required: true schema: type: string format: uuid title: Workspace Id /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. Proxies to connector-runner /internal/gap-scanner/scan. Permissions: admin, owner (enforced via ``Workspace.update`` — this creates patient-facing surfaces, so it must not be reachable below admin tier).' 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 /v1/{workspace_id}/settings/metrics: get: tags: - Settings summary: Get metric definitions description: 'Get the workspace metric definitions. Returns built-in defaults when not configured. Permissions: 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 put: tags: - Settings summary: Update metric definitions description: 'Update the workspace metric definitions. Partial updates supported — only provided fields are changed. The definitions list is replaced entirely when provided. Permissions: 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 /v1/{workspace_id}/settings/outreach: get: tags: - Settings summary: Get outreach settings description: 'Get the workspace outreach settings. Returns empty rules and templates when not configured. Permissions: 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 put: tags: - Settings summary: Update outreach settings description: '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.' 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 /v1/{workspace_id}/settings/branding: get: tags: - Settings summary: Get workspace branding description: 'Get the workspace default branding for surfaces. Returns empty branding when not configured. Permissions: 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 put: tags: - Settings summary: Update workspace branding description: 'Update the workspace default branding for surfaces. Surface-level branding takes precedence over workspace-level branding. Permissions: 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 /v1/{workspace_id}/settings/environments: get: tags: - Settings summary: Get environment overrides description: 'Get per-environment config overrides. Returns empty environments when not configured. Permissions: 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 put: tags: - Settings summary: Update environment overrides description: 'Update per-environment config overrides. Permissions: 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 /v1/{workspace_id}/settings/voice: get: tags: - Settings summary: Get voice settings description: '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).' 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 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**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 components: schemas: ChannelType: type: string enum: - email - web - sms title: ChannelType description: Delivery channels for surfaces. 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. 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. GapScannerPreviewRequest: properties: limit: type: integer maximum: 200.0 minimum: 1.0 title: Limit default: 50 type: object title: GapScannerPreviewRequest 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 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. BrandingSettingsResponse: properties: branding: $ref: '#/components/schemas/BrandingConfig' type: object required: - branding title: BrandingSettingsResponse MetricSettingsResponse: properties: definitions: items: $ref: '#/components/schemas/MetricDefinition' type: array title: Definitions type: object required: - definitions title: MetricSettingsResponse 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. 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. EnvironmentSettingsRequest: properties: environments: additionalProperties: $ref: '#/components/schemas/EnvironmentOverrides' type: object title: Environments type: object required: - environments title: EnvironmentSettingsRequest BrandingSettingsRequest: properties: branding: $ref: '#/components/schemas/BrandingConfig' type: object required: - branding title: BrandingSettingsRequest description: 'Update workspace branding. All fields are optional — only provided fields are changed.' 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 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 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 stt_provider: anyOf: - type: string enum: - deepgram - openai - cartesia - type: 'null' title: Stt Provider 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 - pronunciation_dict_id - sensitive_topics - post_call_analysis_enabled - transcript_correction_enabled - stt_provider - tts_provider - tts_config title: VoiceSettingsResponse description: Voice experience state — what the PM configured. 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. 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. EnvironmentSettingsResponse: properties: environments: additionalProperties: $ref: '#/components/schemas/EnvironmentOverrides' type: object title: Environments type: object title: EnvironmentSettingsResponse QuietHours: properties: enabled: type: boolean title: Enabled default: false start_hour: type: integer maximum: 23.0 minimum: 0.0 title: Start Hour default: 21 end_hour: type: integer maximum: 23.0 minimum: 0.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. HTTPValidationError: properties: detail: items: $ref: '#/components/schemas/ValidationError' type: array title: Detail type: object title: HTTPValidationError 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.0 minimum: 0.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. RetentionPolicyRequest: properties: call_recordings_days: anyOf: - type: integer maximum: 36500.0 minimum: 365.0 - type: 'null' title: Call Recordings Days call_transcripts_days: anyOf: - type: integer maximum: 36500.0 minimum: 365.0 - type: 'null' title: Call Transcripts Days audit_log_days: anyOf: - type: integer maximum: 36500.0 minimum: 365.0 - type: 'null' title: Audit Log Days world_events_days: anyOf: - type: integer maximum: 36500.0 minimum: 365.0 - type: 'null' title: World Events Days phi_data_days: anyOf: - type: integer maximum: 36500.0 minimum: 365.0 - 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 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 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 stt_provider: anyOf: - type: string enum: - deepgram - openai - cartesia - type: 'null' title: Stt Provider 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. Controls the caller experience without exposing engineering internals. Emotion detection, filler speech, model selection, and buffer tuning are always-on internals managed by engineering.' DescriptionString: type: string maxLength: 2000 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.0 minimum: 5.0 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." 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. NameString: type: string maxLength: 256 minLength: 1 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. GapScannerSettingsRequest: properties: enabled: anyOf: - type: boolean - type: 'null' title: Enabled scan_interval_seconds: anyOf: - type: integer maximum: 86400.0 minimum: 60.0 - type: 'null' title: Scan Interval Seconds appointment_lookahead_hours: anyOf: - type: integer maximum: 720.0 minimum: 1.0 - type: 'null' title: Appointment Lookahead Hours cooldown_hours: anyOf: - type: integer maximum: 8760.0 minimum: 1.0 - type: 'null' title: Cooldown Hours max_surfaces_per_tick: anyOf: - type: integer maximum: 100.0 minimum: 1.0 - type: 'null' title: Max Surfaces Per Tick max_pending_surfaces: anyOf: - type: integer maximum: 50.0 minimum: 0.0 - type: 'null' title: Max Pending Surfaces description: Max non-terminal surfaces per entity (0 = disabled) min_completion_rate: anyOf: - type: number maximum: 1.0 minimum: 0.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 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. The definitions list is replaced entirely when provided. Built-in metrics can be deactivated (active=false) or have their freshness_sla_minutes changed, but their key cannot be reused for custom metrics.' 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 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 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. 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. Rules and data_templates lists are replaced entirely when provided.' securitySchemes: Bearer-Authorization: type: http scheme: bearer bearerFormat: JWT description: Amigo issued JWT token that identifies an user. It's issued either after logging in through the frontend, or manually through the [`SignInWithAPIKey`](sign-in-with-api-key) endpoint. Bearer-Authorization-Organization: type: apiKey in: header name: X-ORG-ID description: An optional organization identifier that indicates from which organization the token is issued. This is used in rare cases where the user to authenticate is making a request for resources in another organization. Basic: type: http scheme: basic description: The username should be set to {org_id}_{user_id}, and the password should be the Amigo issued JWT token that identifies the user.