diff --git a/fern/apis/signalwire-rest/openapi.yaml b/fern/apis/signalwire-rest/openapi.yaml index 2a8a898f6..2837ae8f5 100644 --- a/fern/apis/signalwire-rest/openapi.yaml +++ b/fern/apis/signalwire-rest/openapi.yaml @@ -428,6 +428,8 @@ paths: codecs: - PCMU - PCMA + timeout: 30 + max_price_per_minute: 0.05 update: summary: update description: Modify an existing call's parameters in real-time @@ -445,20 +447,24 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: reason: hangup + async: false calling.ai_hold: summary: calling.ai_hold description: Put an active AI call on hold, pausing the conversation value: command: calling.ai_hold id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 - params: {} + params: + timeout: '300' + async: false calling.ai_unhold: summary: calling.ai_unhold description: Resume an AI call that was previously put on hold value: command: calling.ai_unhold id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 - params: {} + params: + async: false calling.ai_message: summary: calling.ai_message description: Send a message to the AI conversation to modify behavior or add context @@ -468,6 +474,7 @@ paths: params: role: system message_text: You are now in expert mode. Provide detailed technical responses and use industry terminology. + async: false calling.live_transcribe: summary: calling.live_transcribe description: Start real-time speech-to-text transcription on an active call @@ -515,13 +522,15 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: dest: sip:destination@example.com + async: false calling.disconnect: summary: calling.disconnect description: Disconnect a call leg value: command: calling.disconnect id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 - params: {} + params: + async: false calling.play: summary: calling.play description: Play media on an active call @@ -535,7 +544,9 @@ paths: params: url: https://example.com/audio.mp3 volume: 0 - direction: both + direction: listen + loop: 1 + async: false calling.play.pause: summary: calling.play.pause description: Pause an active play operation @@ -544,6 +555,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: play-control-1 + async: false calling.play.resume: summary: calling.play.resume description: Resume a paused play operation @@ -552,6 +564,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: play-control-1 + async: false calling.play.stop: summary: calling.play.stop description: Stop an active play operation @@ -560,6 +573,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: play-control-1 + async: false calling.play.volume: summary: calling.play.volume description: Adjust the volume of an active play operation @@ -569,6 +583,7 @@ paths: params: control_id: play-control-1 volume: 5 + async: false calling.record: summary: calling.record description: Start recording an active call @@ -577,10 +592,11 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: record-control-1 - audio: - format: mp3 - direction: both - stereo: false + record: + audio: + format: mp3 + direction: speak + stereo: false calling.record.pause: summary: calling.record.pause description: Pause an active recording @@ -617,6 +633,12 @@ paths: digits: max: 4 terminators: '#' + continuous: false + partial_results: false + send_start_of_input: false + start_input_timers: false + status_url: https://example.com/collect_callback + async: false calling.collect.stop: summary: calling.collect.stop description: Stop an active collect operation @@ -625,6 +647,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: collect-control-1 + async: false calling.collect.start_input_timers: summary: calling.collect.start_input_timers description: Start input timers for an active collect operation @@ -633,6 +656,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: collect-control-1 + async: false calling.detect: summary: calling.detect description: Start detection (machine, fax, or digit) on an active call @@ -643,7 +667,11 @@ paths: control_id: detect-control-1 detect: type: machine + params: + initial_timeout: 4.5 + end_silence_timeout: 1 timeout: 30 + async: false calling.detect.stop: summary: calling.detect.stop description: Stop an active detection operation @@ -652,6 +680,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: detect-control-1 + async: false calling.tap: summary: calling.tap description: Start tapping (capturing audio) on an active call @@ -667,8 +696,9 @@ paths: device: type: rtp params: - addr: 192.168.1.100 + addr: 198.51.100.42 port: 5060 + async: false calling.tap.stop: summary: calling.tap.stop description: Stop an active tap operation @@ -677,6 +707,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: tap-control-1 + async: false calling.stream: summary: calling.stream description: Start streaming call audio to a WebSocket endpoint @@ -686,7 +717,8 @@ paths: params: control_id: stream-control-1 url: wss://example.com/stream - track: both_tracks + track: inbound_track + async: false calling.stream.stop: summary: calling.stream.stop description: Stop an active audio stream @@ -695,20 +727,23 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: stream-control-1 + async: false calling.denoise: summary: calling.denoise description: Enable noise reduction on an active call value: command: calling.denoise id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 - params: {} + params: + async: false calling.denoise.stop: summary: calling.denoise.stop description: Disable noise reduction on an active call value: command: calling.denoise.stop id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 - params: {} + params: + async: false calling.ai.stop: summary: calling.ai.stop description: Stop an active AI session on the call @@ -717,6 +752,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: ai-control-1 + async: false calling.send_fax.stop: summary: calling.send_fax.stop description: Stop an active fax send operation @@ -725,6 +761,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: fax-send-control-1 + async: false calling.receive_fax.stop: summary: calling.receive_fax.stop description: Stop an active fax receive operation @@ -733,6 +770,7 @@ paths: id: 3fa85f64-5717-4562-b3fc-2c963f66afa6 params: control_id: fax-receive-control-1 + async: false calling.refer: summary: calling.refer description: Perform a SIP REFER on an active call @@ -744,6 +782,7 @@ paths: type: sip params: to: sip:destination@example.com + async: false calling.user_event: summary: calling.user_event description: Fire a custom user event on an active call @@ -754,6 +793,7 @@ paths: event: action: custom_action data: example + async: false /api/chat/tokens: post: operationId: create_chat_token @@ -17518,21 +17558,21 @@ components: - user - assistant description: |- - The role that the message is from. Required when `reset` is not provided. Each role type has a different purpose and will influence how the AI will interpret the message. - - `system`: Inject instructions or context that modify the AI's behavior mid-conversation without the caller hearing it. This could change the AI's personality, add new constraints, provide context about the conversation, or give the AI information it should know going forward. - - `user`: Inject a message as if the caller said it. This would appear in the conversation history as coming from the caller, and the AI would respond to it as if the caller just spoke it. - - `assistant`: Inject a message as if the AI said it. This would appear as an AI response in the conversation history. The AI would treat this as its own previous response when generating future replies. + The role that the message is from. By convention pair with `message_text` (the validator itself does not enforce this). + - `system`: Inject instructions or context that modify the AI's behavior mid-conversation without the caller hearing it. + - `user`: Inject a message as if the caller said it. The AI will respond as if the caller spoke it. + - `assistant`: Inject a message as if the AI said it. Appears as an AI response in the conversation history. examples: - system message_text: type: string - description: The text content that will be sent to the AI. Required when `reset` is not provided. + description: The text content sent to the AI. Typically required unless `reset` is provided. examples: - You are now in expert mode. Provide detailed technical responses. reset: allOf: - $ref: '#/components/schemas/Calling.CallAIMessageResetParams' - description: Parameters for resetting the AI conversation state. When provided, `role` and `message_text` are optional. + description: Parameters for resetting the AI conversation state. examples: - full_reset: true system_prompt: You are a helpful assistant. @@ -17543,6 +17583,12 @@ components: examples: - customer_tier: premium language: en + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the message to be delivered. + examples: + - false + default: false description: An object of parameters that will be utilized by the active command. title: calling.ai_message Calling.CallAIMessageResetParams: @@ -17592,6 +17638,12 @@ components: description: The control ID of the AI session to stop. examples: - ai-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stop to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -17691,40 +17743,79 @@ components: properties: control_id: type: string - description: Unique identifier for this collect operation, used to control it later. + description: Unique identifier for this collect operation, used to control it later. Must be unique per active collect on this call. examples: - collect-control-1 initial_timeout: type: number format: double - description: Maximum time in seconds to wait for initial input. + description: Maximum time in seconds to wait for initial input. Must be positive. Defaults to the server-configured no-input timeout when omitted. examples: - 5 digits: allOf: - $ref: '#/components/schemas/Calling.CollectDigitsParams' - description: Configuration for collecting DTMF digit input. + description: Configuration for collecting DTMF digit input. Provide `digits`, `speech`, or both. examples: - max: 4 terminators: '#' speech: allOf: - $ref: '#/components/schemas/Calling.CollectSpeechParams' - description: Configuration for collecting speech input. + description: Configuration for collecting speech input. Provide `digits`, `speech`, or both. examples: - end_silence_timeout: 3 language: en-US continuous: type: boolean - description: Whether to continuously collect input (restart after each result). + description: If `true`, the collect restarts after each result until `calling.collect.stop` is called. Continuous events include a `state` field indicating collect state. examples: - false + default: false partial_results: type: boolean - description: Whether to send partial results as speech is recognized. + description: If `true`, partial results are delivered as they are recognized, and events include a `final` field (`false` for partial, `true` for final). + examples: + - false + default: false + send_start_of_input: + type: boolean + description: If `true`, a `start_of_input` webhook event is fired when input is first detected. + examples: + - false + default: false + start_input_timers: + type: boolean + description: If `false`, the initial-timeout clock does not start until `calling.collect.start_input_timers` is called for this `control_id`. + examples: + - false + default: false + status_url: + type: string + format: uri + description: HTTP or HTTPS URL that receives collect result webhooks. + examples: + - https://example.com/collect_callback + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the collect to be set up. examples: - false + default: false + required: + - control_id description: An object of parameters that will be utilized by the active command. + description: |- + Collect user input (DTMF digits, speech, or both) on an active call. + + At least one of `digits` or `speech` must be provided; requests missing + both return 400. Results are delivered asynchronously via the `status_url` + webhook. Digit events have the shape `{control_id, call_id, node_id, result: {type:"digit", params: {digits, terminator}}}` + and speech events `{..., result: {type:"speech", params: {text, confidence}}}`. + + When `start_input_timers` is `false`, the `initial_timeout` clock does not + start until you send `calling.collect.start_input_timers` for the same + `control_id`. title: calling.collect Calling.CallCollectStartInputTimersRequest: type: object @@ -17754,6 +17845,12 @@ components: description: The control ID of the collect operation to start input timers for. examples: - collect-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the timers to start. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -17786,6 +17883,12 @@ components: description: The control ID of the collect operation to stop. examples: - collect-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stop to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -17813,32 +17916,38 @@ components: type: object required: - from - - to properties: from: type: string - description: The address that initiated the call. Can be either a E.164 formatted number (`+xxxxxxxxxxx`), or a SIP endpoint (`sip:xxx@yyy.zzz`). + description: The address that initiates the call. For PSTN destinations, must be an E.164 number; for SIP/Verto destinations may also be a SIP URI (`sip:user@host`) or a short caller-id token. examples: - sip:from-sip@example-112233445566.sip.signalwire.com to: type: string - description: The address that received the call. Can be either a E.164 formatted number (`+xxxxxxxxxxx`), or a SIP endpoint (`sip:xxx@yyy.zzz`). + description: Destination address. Accepts E.164 (`+xxxxxxxxxxx`), SIP URI (`sip:` / `sips:`), Verto URI (`verto:`), client address (`client:`), or a fabric address. Required unless `to_script` is provided. examples: - sip:from-sip@example-112233445567.sip.signalwire.com + to_script: + anyOf: + - type: string + - $ref: '#/components/schemas/SWMLObject' + description: Inline SWML document (JSON or YAML string), or an `http(s)://` URL that returns one, executed at the destination end. Useful for directing the call to a RelayBin / external SWML handler. When present, `to` may be omitted. + examples: + - https://example.com/destination.swml.json caller_id: type: string - description: The number, in E.164 format, or identifier of the caller. + description: Caller ID displayed to the destination. E.164 for PSTN; short caller-id token or SIP URI for SIP/Verto. examples: - '+1234567890' fallback_url: type: string - description: The Fallback URL to handle the call. This parameter allows you to specify a backup webhook or different route in your code containing SWML instructions for handling the call. + description: Fallback URL that returns SWML if the primary `url` fails. examples: - https://example.com/fallback status_url: type: string format: uri - description: A URL that will recieve status updates of the current call. Any call events defined in `status_events` will be delivered to the defined URL. + description: HTTP or HTTPS URL that receives call lifecycle webhooks for events listed in `status_events`. examples: - https://example.com/status_callback status_events: @@ -17846,13 +17955,13 @@ components: items: type: string enum: - - answered - queued - initiated - ringing + - answered - ending - ended - description: The call events that will be monitored and sent to the `status_url` when active. + description: Call lifecycle events that will be delivered to `status_url`. examples: - - answered - ended @@ -17860,7 +17969,10 @@ components: - ended url_method: type: string - description: The HTTP method to use when requesting the URL. + enum: + - GET + - POST + description: HTTP method used when requesting the `url`. Defaults to `POST`. examples: - POST default: POST @@ -17870,43 +17982,79 @@ components: items: type: string - type: string - description: 'A list of codecs to use for the call. Can be an array of codec strings or a comma-separated string. Valid codecs are: `PCMU`, `PCMA`, `G722`, `G729`, `OPUS`, `VP8`, `H264`. For PSTN calls, `PCMA` and `PCMU` are recommended as many other codecs are not supported by PSTN gateways. If a SIP URI with included codecs is passed in the `to` field along with this parameter, the SIP URI codecs will be prioritized.' + description: 'Codecs to offer on the outbound call. May be provided as an array or a comma-separated string. Allowed values: `PCMU`, `PCMA`, `G722`, `G729`, `OPUS`, `AMR-WB`, `VP8`, `H264`. For PSTN, `PCMU`/`PCMA` are widely supported. If the `to` value is a SIP URI containing `codecs=...`, those take precedence.' examples: - - OPUS - G729 - VP8 - PCMA + timeout: + type: integer + format: int32 + minimum: 1 + maximum: 600 + description: Ring timeout in seconds. Must be between 1 and 600. + examples: + - 30 + max_price_per_minute: + type: number + format: double + minimum: 0 + description: Maximum per-minute price (in dollars). If the computed billing route exceeds this value, the call is rejected. + examples: + - 0.05 + send_digits: + type: string + description: 'DTMF digits to send after the call is answered. Allowed characters: `0-9`, `A-D`, `*`, `#`, `w` (wait), `,` (pause).' + examples: + - 1234# + region: + anyOf: + - type: string + - type: array + items: + type: string + description: Preferred FreeSWITCH region(s) for call routing. Must be drawn from the project's available regions. Accepts a single region or a priority-ordered array. + examples: + - - us-east-1 + - us-west-2 Calling.CallCreateParamsSWML: type: object required: - from - - to - swml properties: from: type: string - description: The address that initiated the call. Can be either a E.164 formatted number (`+xxxxxxxxxxx`), or a SIP endpoint (`sip:xxx@yyy.zzz`). + description: The address that initiates the call. For PSTN destinations, must be an E.164 number; for SIP/Verto destinations may also be a SIP URI (`sip:user@host`) or a short caller-id token. examples: - sip:from-sip@example-112233445566.sip.signalwire.com to: type: string - description: The address that received the call. Can be either a E.164 formatted number (`+xxxxxxxxxxx`), or a SIP endpoint (`sip:xxx@yyy.zzz`). + description: Destination address. Accepts E.164 (`+xxxxxxxxxxx`), SIP URI (`sip:` / `sips:`), Verto URI (`verto:`), client address (`client:`), or a fabric address. Required unless `to_script` is provided. examples: - sip:from-sip@example-112233445567.sip.signalwire.com + to_script: + anyOf: + - type: string + - $ref: '#/components/schemas/SWMLObject' + description: Inline SWML document (JSON or YAML string), or an `http(s)://` URL that returns one, executed at the destination end. Useful for directing the call to a RelayBin / external SWML handler. When present, `to` may be omitted. + examples: + - https://example.com/destination.swml.json caller_id: type: string - description: The number, in E.164 format, or identifier of the caller. + description: Caller ID displayed to the destination. E.164 for PSTN; short caller-id token or SIP URI for SIP/Verto. examples: - '+1234567890' fallback_url: type: string - description: The Fallback URL to handle the call. This parameter allows you to specify a backup webhook or different route in your code containing SWML instructions for handling the call. + description: Fallback URL that returns SWML if the primary `url` fails. examples: - https://example.com/fallback status_url: type: string format: uri - description: A URL that will recieve status updates of the current call. Any call events defined in `status_events` will be delivered to the defined URL. + description: HTTP or HTTPS URL that receives call lifecycle webhooks for events listed in `status_events`. examples: - https://example.com/status_callback status_events: @@ -17914,13 +18062,13 @@ components: items: type: string enum: - - answered - queued - initiated - ringing + - answered - ending - ended - description: The call events that will be monitored and sent to the `status_url` when active. + description: Call lifecycle events that will be delivered to `status_url`. examples: - - answered - ended @@ -17928,7 +18076,10 @@ components: - ended url_method: type: string - description: The HTTP method to use when requesting the URL. + enum: + - GET + - POST + description: HTTP method used when requesting the `url`. Defaults to `POST`. examples: - POST default: POST @@ -17938,12 +18089,42 @@ components: items: type: string - type: string - description: 'A list of codecs to use for the call. Can be an array of codec strings or a comma-separated string. Valid codecs are: `PCMU`, `PCMA`, `G722`, `G729`, `OPUS`, `VP8`, `H264`. For PSTN calls, `PCMA` and `PCMU` are recommended as many other codecs are not supported by PSTN gateways. If a SIP URI with included codecs is passed in the `to` field along with this parameter, the SIP URI codecs will be prioritized.' + description: 'Codecs to offer on the outbound call. May be provided as an array or a comma-separated string. Allowed values: `PCMU`, `PCMA`, `G722`, `G729`, `OPUS`, `AMR-WB`, `VP8`, `H264`. For PSTN, `PCMU`/`PCMA` are widely supported. If the `to` value is a SIP URI containing `codecs=...`, those take precedence.' examples: - - OPUS - G729 - VP8 - PCMA + timeout: + type: integer + format: int32 + minimum: 1 + maximum: 600 + description: Ring timeout in seconds. Must be between 1 and 600. + examples: + - 30 + max_price_per_minute: + type: number + format: double + minimum: 0 + description: Maximum per-minute price (in dollars). If the computed billing route exceeds this value, the call is rejected. + examples: + - 0.05 + send_digits: + type: string + description: 'DTMF digits to send after the call is answered. Allowed characters: `0-9`, `A-D`, `*`, `#`, `w` (wait), `,` (pause).' + examples: + - 1234# + region: + anyOf: + - type: string + - type: array + items: + type: string + description: Preferred FreeSWITCH region(s) for call routing. Must be drawn from the project's available regions. Accepts a single region or a priority-ordered array. + examples: + - - us-east-1 + - us-west-2 swml: allOf: - $ref: '#/components/schemas/SWMLObject' @@ -17953,33 +18134,39 @@ components: type: object required: - from - - to - url properties: from: type: string - description: The address that initiated the call. Can be either a E.164 formatted number (`+xxxxxxxxxxx`), or a SIP endpoint (`sip:xxx@yyy.zzz`). + description: The address that initiates the call. For PSTN destinations, must be an E.164 number; for SIP/Verto destinations may also be a SIP URI (`sip:user@host`) or a short caller-id token. examples: - sip:from-sip@example-112233445566.sip.signalwire.com to: type: string - description: The address that received the call. Can be either a E.164 formatted number (`+xxxxxxxxxxx`), or a SIP endpoint (`sip:xxx@yyy.zzz`). + description: Destination address. Accepts E.164 (`+xxxxxxxxxxx`), SIP URI (`sip:` / `sips:`), Verto URI (`verto:`), client address (`client:`), or a fabric address. Required unless `to_script` is provided. examples: - sip:from-sip@example-112233445567.sip.signalwire.com + to_script: + anyOf: + - type: string + - $ref: '#/components/schemas/SWMLObject' + description: Inline SWML document (JSON or YAML string), or an `http(s)://` URL that returns one, executed at the destination end. Useful for directing the call to a RelayBin / external SWML handler. When present, `to` may be omitted. + examples: + - https://example.com/destination.swml.json caller_id: type: string - description: The number, in E.164 format, or identifier of the caller. + description: Caller ID displayed to the destination. E.164 for PSTN; short caller-id token or SIP URI for SIP/Verto. examples: - '+1234567890' fallback_url: type: string - description: The Fallback URL to handle the call. This parameter allows you to specify a backup webhook or different route in your code containing SWML instructions for handling the call. + description: Fallback URL that returns SWML if the primary `url` fails. examples: - https://example.com/fallback status_url: type: string format: uri - description: A URL that will recieve status updates of the current call. Any call events defined in `status_events` will be delivered to the defined URL. + description: HTTP or HTTPS URL that receives call lifecycle webhooks for events listed in `status_events`. examples: - https://example.com/status_callback status_events: @@ -17987,13 +18174,13 @@ components: items: type: string enum: - - answered - queued - initiated - ringing + - answered - ending - ended - description: The call events that will be monitored and sent to the `status_url` when active. + description: Call lifecycle events that will be delivered to `status_url`. examples: - - answered - ended @@ -18001,7 +18188,10 @@ components: - ended url_method: type: string - description: The HTTP method to use when requesting the URL. + enum: + - GET + - POST + description: HTTP method used when requesting the `url`. Defaults to `POST`. examples: - POST default: POST @@ -18011,12 +18201,42 @@ components: items: type: string - type: string - description: 'A list of codecs to use for the call. Can be an array of codec strings or a comma-separated string. Valid codecs are: `PCMU`, `PCMA`, `G722`, `G729`, `OPUS`, `VP8`, `H264`. For PSTN calls, `PCMA` and `PCMU` are recommended as many other codecs are not supported by PSTN gateways. If a SIP URI with included codecs is passed in the `to` field along with this parameter, the SIP URI codecs will be prioritized.' + description: 'Codecs to offer on the outbound call. May be provided as an array or a comma-separated string. Allowed values: `PCMU`, `PCMA`, `G722`, `G729`, `OPUS`, `AMR-WB`, `VP8`, `H264`. For PSTN, `PCMU`/`PCMA` are widely supported. If the `to` value is a SIP URI containing `codecs=...`, those take precedence.' examples: - - OPUS - G729 - VP8 - PCMA + timeout: + type: integer + format: int32 + minimum: 1 + maximum: 600 + description: Ring timeout in seconds. Must be between 1 and 600. + examples: + - 30 + max_price_per_minute: + type: number + format: double + minimum: 0 + description: Maximum per-minute price (in dollars). If the computed billing route exceeds this value, the call is rejected. + examples: + - 0.05 + send_digits: + type: string + description: 'DTMF digits to send after the call is answered. Allowed characters: `0-9`, `A-D`, `*`, `#`, `w` (wait), `,` (pause).' + examples: + - 1234# + region: + anyOf: + - type: string + - type: array + items: + type: string + description: Preferred FreeSWITCH region(s) for call routing. Must be drawn from the project's available regions. Accepts a single region or a priority-ordered array. + examples: + - - us-east-1 + - us-west-2 url: type: string description: |- @@ -18066,7 +18286,18 @@ components: - calling.denoise params: type: object + properties: + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the filter to be set up. + examples: + - false + default: false description: An object of parameters that will be utilized by the active command. + description: |- + Enable noise reduction on an active call. Denoise is per-call (no + `control_id`); a call has at most one active denoise filter. Use + `calling.denoise.stop` to disable it. title: calling.denoise Calling.CallDenoiseStopRequest: type: object @@ -18090,6 +18321,13 @@ components: - calling.denoise.stop params: type: object + properties: + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the filter to be torn down. + examples: + - false + default: false description: An object of parameters that will be utilized by the active command. title: calling.denoise.stop Calling.CallDetectRequest: @@ -18117,24 +18355,46 @@ components: properties: control_id: type: string - description: Unique identifier for this detect operation, used to control it later. + description: Unique identifier for this detect operation, used to control it later. Must be unique per active detect on this call. examples: - detect-control-1 detect: - allOf: - - $ref: '#/components/schemas/Calling.DetectConfig' + anyOf: + - $ref: '#/components/schemas/Calling.DetectMachineConfig' + - $ref: '#/components/schemas/Calling.DetectFaxConfig' + - $ref: '#/components/schemas/Calling.DetectDigitConfig' description: Detection configuration specifying what to detect. examples: - type: machine timeout: type: number format: double - description: Maximum time in seconds to run the detection. + minimum: 0 + description: Maximum time in seconds the detection may run before timing out. examples: - 30 + default: 30 + status_url: + type: string + format: uri + description: HTTP or HTTPS URL that receives detection result webhooks. + examples: + - https://example.com/detect_callback + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the detect to be set up. + examples: + - false + default: false required: + - control_id - detect description: An object of parameters that will be utilized by the active command. + description: |- + Start detection (answering machine, fax tone, or DTMF digits) on an active call. + + Detection runs asynchronously up to `timeout` seconds. Results are delivered + via the `status_url` webhook. title: calling.detect Calling.CallDetectStopRequest: type: object @@ -18164,6 +18424,12 @@ components: description: The control ID of the detect operation to stop. examples: - detect-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stop to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -18197,6 +18463,13 @@ components: - calling.disconnect params: type: object + properties: + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the disconnect to take effect. + examples: + - false + default: false description: An object of parameters that will be utilized by the active command. title: calling.disconnect Calling.CallHangupRequest: @@ -18228,6 +18501,12 @@ components: description: Set the reason why the call was hung up. examples: - hangup + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the hangup to complete. + examples: + - false + default: false description: An object of parameters that will be utilized by the active command. title: calling.end Calling.CallHoldRequest: @@ -18254,14 +18533,10 @@ components: type: object properties: timeout: - type: integer - format: int32 - minimum: 1 - maximum: 300 - description: The duration to hold the caller in seconds. + type: string + description: 'Hold timeout, expressed as a numeric string of seconds. Note: must be sent as a string — integer payloads are rejected.' examples: - - 300 - default: 300 + - '300' prompt: type: string description: |- @@ -18269,7 +18544,12 @@ components: The AI will speak this message to the caller before hold music begins. examples: - Please hold while I transfer you to a specialist. - default: Tell the user you are putting them on hold. + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the hold to take effect. + examples: + - false + default: false description: An object of parameters that will be utilized by the active command. title: calling.ai_hold Calling.CallLeg: @@ -18427,6 +18707,12 @@ components: - $ref: '#/components/schemas/Calling.LiveTranscribeSummarizeAction' - $ref: '#/components/schemas/Calling.LiveTranscribeStopAction' description: 'The transcription action to perform: start, stop, or summarize.' + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the action to take effect. + examples: + - false + default: false required: - action description: An object of parameters that will be utilized by the active command. @@ -18464,9 +18750,15 @@ components: status_url: type: string format: uri - description: A URL to receive status update callbacks for the translation session. + description: HTTP or HTTPS URL that receives translation-session webhooks. examples: - https://example.com/status_callback + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the action to take effect. + examples: + - false + default: false required: - action description: An object of parameters that will be utilized by the active command. @@ -18499,6 +18791,12 @@ components: description: The control ID of the play operation to pause. examples: - play-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the pause to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -18528,14 +18826,18 @@ components: properties: control_id: type: string - description: Unique identifier for this play operation, used to control it later. + description: Unique identifier for this play operation, used to control it later. Must be unique per active play on this call. examples: - play-control-1 play: type: array items: - $ref: '#/components/schemas/Calling.PlayMediaItem' - description: Array of media objects to play. + anyOf: + - $ref: '#/components/schemas/Calling.PlayAudioItem' + - $ref: '#/components/schemas/Calling.PlayTtsItem' + - $ref: '#/components/schemas/Calling.PlaySilenceItem' + - $ref: '#/components/schemas/Calling.PlayRingtoneItem' + description: Ordered list of media items to play. Items play sequentially. examples: - - type: audio params: @@ -18545,32 +18847,66 @@ components: format: double minimum: -40 maximum: 40 - description: Volume adjustment in dB (-40 to 40). + description: Volume adjustment in dB. Must be between -40 and 40. examples: - 0 default: 0 direction: allOf: - $ref: '#/components/schemas/Calling.PlayDirection' - description: The direction of audio playback. + description: The direction of audio playback relative to the call participants. examples: - - both - default: both + - listen + default: listen loop: type: integer format: int32 - description: Number of times to loop playback. 0 for infinite loop. + minimum: 0 + description: Number of times the full `play` sequence is repeated. `0` loops forever; `N > 0` plays a total of N times. examples: - 1 + default: 1 + language: + type: string + description: Default BCP-47 language tag applied to any TTS item that does not set its own `language`. + examples: + - en-US + default: en-US + voice: + type: string + description: Default voice applied to any TTS item that does not set its own `voice`. Defaults to the request-level `gender` when unset. + examples: + - en-US-Wavenet-C + gender: + allOf: + - $ref: '#/components/schemas/Calling.TtsGender' + description: Default voice gender applied to any TTS item that does not set its own `gender`. + examples: + - female + default: female status_url: type: string format: uri - description: A URL to receive status update callbacks for the play operation. + description: HTTP or HTTPS URL that receives playback lifecycle webhooks (`playing`, `paused`, `finished`, `error`). examples: - https://example.com/status_callback + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for playback to start. + examples: + - false + default: false required: + - control_id - play description: An object of parameters that will be utilized by the active command. + description: |- + Play media (audio files, text-to-speech, silence, or ringtones) on an active call. + + The HTTP response confirms the command was accepted. Playback lifecycle + is delivered asynchronously via the `status_url` webhook, with payloads + of the form `{control_id, call_id, node_id, state}` where `state` is one + of `playing`, `paused`, `finished`, or `error`. title: calling.play Calling.CallPlayResumeRequest: type: object @@ -18600,6 +18936,12 @@ components: description: The control ID of the play operation to resume. examples: - play-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the resume to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -18632,6 +18974,12 @@ components: description: The control ID of the play operation to stop. examples: - play-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stop to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -18669,9 +19017,15 @@ components: format: double minimum: -40 maximum: 40 - description: Volume adjustment in dB (-40 to 40). + description: Volume adjustment in dB. Must be between -40 and 40. examples: - 5 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the volume change to take effect. + examples: + - false + default: false required: - control_id - volume @@ -18705,6 +19059,12 @@ components: description: The control ID of the fax receive operation to stop. examples: - fax-receive-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stop to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -18737,6 +19097,21 @@ components: description: The control ID of the recording to pause. examples: - record-control-1 + behavior: + type: string + enum: + - skip + - silence + description: How the paused audio is handled. `skip` omits paused audio from the output file; `silence` replaces it with silence, preserving timing. + examples: + - skip + default: skip + async: + type: boolean + description: If `true`, the request returns immediately. Defaults to `false`. + examples: + - true + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -18766,24 +19141,38 @@ components: properties: control_id: type: string - description: Unique identifier for this record operation, used to control it later. + description: Unique identifier for this record operation, used to control it later. Must be unique among active recordings on the call. examples: - record-control-1 - audio: + record: allOf: - - $ref: '#/components/schemas/Calling.RecordAudioParams' - description: Audio recording configuration parameters. + - $ref: '#/components/schemas/Calling.RecordParams' + description: Recording configuration. Wraps the media-type-specific parameters (currently only `audio`). + examples: + - audio: + format: mp3 + direction: speak + stereo: false + async: + type: boolean + description: If `true`, the request returns immediately without waiting for the recording to start. Defaults to `false`. examples: - - format: mp3 - direction: both - stereo: false + - true + default: false status_url: type: string format: uri - description: A URL to receive status update callbacks for the record operation. + description: Webhook URL invoked with recording events — including a `finished` event that contains the final recording URL. Must begin with `http://` or `https://`. examples: - https://example.com/status_callback + required: + - control_id + - record description: An object of parameters that will be utilized by the active command. + description: |- + Starts recording an active call. The HTTP response returns the call leg — the recording URL + is not included. Recording runs asynchronously; provide `status_url` to receive a webhook when + the recording finishes (with the final URL), or query the call's events endpoint. title: calling.record Calling.CallRecordResumeRequest: type: object @@ -18813,7 +19202,13 @@ components: description: The control ID of the recording to resume. examples: - record-control-1 - required: + async: + type: boolean + description: If `true`, the request returns immediately. Defaults to `false`. + examples: + - true + default: false + required: - control_id description: An object of parameters that will be utilized by the active command. title: calling.record.resume @@ -18845,6 +19240,12 @@ components: description: The control ID of the recording to stop. examples: - record-control-1 + async: + type: boolean + description: If `true`, the request returns immediately. Defaults to `false`. + examples: + - true + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -18883,9 +19284,15 @@ components: status_url: type: string format: uri - description: A URL to receive status update callbacks for the refer operation. + description: HTTP or HTTPS URL that receives refer lifecycle webhooks. examples: - https://example.com/status_callback + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the refer to be sent. + examples: + - false + default: false required: - device description: An object of parameters that will be utilized by the active command. @@ -19017,6 +19424,12 @@ components: description: The control ID of the fax send operation to stop. examples: - fax-send-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stop to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -19046,18 +19459,23 @@ components: properties: control_id: type: string - description: Unique identifier for this stream operation, used to control it later. + description: Unique identifier for this stream operation, used to control it later. Must be unique per active stream on this call. examples: - stream-control-1 url: type: string format: uri - description: The WebSocket URL to stream audio to. + description: WebSocket URL to stream audio to. Must start with `wss://` (TLS is required; plain `ws://` is rejected). examples: - wss://example.com/stream + name: + type: string + description: Optional human-readable name to identify the stream at the endpoint. + examples: + - customer-support-recording codec: type: string - description: The audio codec to use for streaming. + description: Audio codec to request. Freeform; endpoint-specific. Common values include `PCMU`, `PCMA`, `OPUS`. examples: - PCMU track: @@ -19065,21 +19483,49 @@ components: - $ref: '#/components/schemas/Calling.StreamTrack' description: The audio track to stream. examples: - - both_tracks + - inbound_track + default: inbound_track authorization_bearer_token: type: string - description: Bearer token for WebSocket authentication. + description: 'Bearer token included as `Authorization: Bearer ` when establishing the WebSocket connection.' examples: - my-secret-token custom_parameters: type: object unevaluatedProperties: {} - description: Custom parameters to include in the WebSocket connection. + description: Arbitrary JSON object passed through to the WebSocket endpoint as connection metadata. examples: - session_id: abc123 + status_url: + type: string + format: uri + description: HTTP or HTTPS URL that receives stream lifecycle webhooks. + examples: + - https://example.com/stream_callback + status_url_method: + allOf: + - $ref: '#/components/schemas/Calling.StreamStatusUrlMethod' + description: HTTP method used for the `status_url` webhook. + examples: + - POST + default: POST + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stream to be set up. + examples: + - false + default: false required: + - control_id - url description: An object of parameters that will be utilized by the active command. + description: |- + Stream call audio to an external WebSocket endpoint. + + Audio is sent to a `wss://` URL; `custom_parameters` pass through to the + endpoint as connection metadata. Stream lifecycle webhooks are delivered to + `status_url` (default method `POST`). Stop the stream with + `calling.stream.stop` using the same `control_id`. title: calling.stream Calling.CallStreamStopRequest: type: object @@ -19109,6 +19555,12 @@ components: description: The control ID of the stream operation to stop. examples: - stream-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stop to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -19138,7 +19590,7 @@ components: properties: control_id: type: string - description: Unique identifier for this tap operation, used to control it later. + description: Unique identifier for this tap operation, used to control it later. Must be unique per active tap on this call. examples: - tap-control-1 tap: @@ -19150,18 +19602,37 @@ components: params: direction: both device: - allOf: - - $ref: '#/components/schemas/Calling.TapDevice' + anyOf: + - $ref: '#/components/schemas/Calling.TapDeviceRtp' + - $ref: '#/components/schemas/Calling.TapDeviceWs' description: Device configuration specifying where to stream captured audio. examples: - type: rtp params: - addr: 192.168.1.100 + addr: 198.51.100.42 port: 5060 + status_url: + type: string + format: uri + description: HTTP or HTTPS URL that receives tap lifecycle webhooks. + examples: + - https://example.com/tap_callback + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the tap to be set up. + examples: + - false + default: false required: + - control_id - tap - device description: An object of parameters that will be utilized by the active command. + description: |- + Capture audio from an active call and stream it to an external destination. + + Audio is streamed via RTP (to a public IP/port) or WebSocket (to a `ws://`/`wss://` URI). + Stop the tap with `calling.tap.stop` using the same `control_id`. title: calling.tap Calling.CallTapStopRequest: type: object @@ -19191,6 +19662,12 @@ components: description: The control ID of the tap operation to stop. examples: - tap-control-1 + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the stop to take effect. + examples: + - false + default: false required: - control_id description: An object of parameters that will be utilized by the active command. @@ -19222,9 +19699,15 @@ components: anyOf: - type: string - $ref: '#/components/schemas/SWMLObject' - description: The destination to transfer the call to. Can be a SIP URI, phone number, or an inline SWML object. + description: The destination to transfer the call to. Can be a SIP URI, phone number, SWML URL, or an inline SWML object. examples: - sip:destination@example.com + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the transfer to complete. + examples: + - false + default: false required: - dest description: An object of parameters that will be utilized by the active command. @@ -19260,14 +19743,12 @@ components: params: type: object properties: - prompt: - type: string - description: |- - A system message added to the AI conversation when taking the caller off hold. - The AI will use this context when resuming the conversation. + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the unhold to take effect. examples: - - The user has been connected to a specialist. - default: The user has been taken off hold. + - false + default: false description: An object of parameters that will be utilized by the active command. title: calling.ai_unhold Calling.CallUpdateCurrentCallRequest: @@ -19288,6 +19769,14 @@ components: - $ref: '#/components/schemas/Calling.CallUpdateParamsURL' - $ref: '#/components/schemas/Calling.CallUpdateParamsSWML' description: An object of parameters that will be utilized by the active command. + description: |- + Update a call in progress — cancel, complete, or redirect the SWML flow. + + State-transition rules: + - `status: canceled` is only valid while the leg is `queued` or `ringing`. + - `status: completed` is only valid while the leg is `answered` (or in-progress). + - Supplying `url` or `swml` (redirect) is only valid while the leg is `answered`. + - Calls in terminal states (`busy`, `failed`, `no-answer`, `canceled`, `completed`) cannot be updated. title: update Calling.CallUpdateParamsBase: type: object @@ -19431,6 +19920,12 @@ components: examples: - action: custom_action data: example + async: + type: boolean + description: If `true`, the HTTP response returns immediately without waiting for the event to fire. + examples: + - false + default: false required: - event description: An object of parameters that will be utilized by the active command. @@ -19454,43 +19949,52 @@ components: - 0.121176 Calling.CollectDigitsParams: type: object + required: + - max properties: max: type: integer format: int32 - description: Maximum number of digits to collect. + description: Maximum number of digits to collect. Must be positive. examples: - 4 terminators: type: string - description: DTMF digits that signal the end of input. + description: 'DTMF digits that terminate input when pressed. Allowed: `0-9`, `A-D` (case insensitive), `*`, `#`. Empty string disables terminators.' examples: - '#' digit_timeout: type: number format: double - description: Time in seconds to wait between digit presses. + description: Time in seconds to wait between digit presses. Must be positive. Defaults to the server-configured digit timeout when omitted. examples: - 5 description: Parameters for collecting DTMF digit input. + Calling.CollectSpeechEngine: + type: string + enum: + - Google + - Google.V2 + - Deepgram + description: 'Speech recognition engine for `calling.collect`. Note: values are case-sensitive and differ from the SWML engine names.' Calling.CollectSpeechParams: type: object properties: end_silence_timeout: type: number format: double - description: Time in seconds of silence after speech to consider input complete. + description: Time in seconds of silence after speech to consider input complete. Must be positive. examples: - 3 speech_timeout: type: number format: double - description: Maximum time in seconds to wait for speech input. + description: Maximum time in seconds to wait for speech input. Must be positive. examples: - 30 language: type: string - description: The language for speech recognition (e.g., 'en-US'). + description: Speech recognition language. Accepts a BCP-47 tag (e.g. `en-US`) or an `engine:tag` override (e.g. `Deepgram:en-US`) to pick a specific engine. Defaults to the server-configured ASR language when omitted. examples: - en-US hints: @@ -19502,11 +20006,17 @@ components: - - 'yes' - 'no' - maybe - engine: + model: type: string - description: The speech recognition engine to use. + description: Provider-specific ASR model name (e.g. Deepgram `nova-3`). Freeform string; validation is performed by the selected engine. examples: - - default + - nova-3 + engine: + allOf: + - $ref: '#/components/schemas/Calling.CollectSpeechEngine' + description: Speech recognition engine to use. + examples: + - Deepgram description: Parameters for collecting speech input. Calling.DetectConfig: type: object @@ -19519,68 +20029,144 @@ components: description: The type of detection to perform. examples: - machine + discriminator: + propertyName: type + mapping: + fax: '#/components/schemas/Calling.DetectFaxConfig' + digit: '#/components/schemas/Calling.DetectDigitConfig' + description: Detection configuration. The shape of `params` depends on `type`. + Calling.DetectDigitConfig: + type: object + required: + - type + properties: + type: + type: string + enum: + - digit + params: + allOf: + - $ref: '#/components/schemas/Calling.DetectDigitParams' + description: Digit-detection parameters. + examples: + - digits: 0123456789#* + allOf: + - $ref: '#/components/schemas/Calling.DetectConfig' + description: DTMF-digit detection configuration. + Calling.DetectDigitParams: + type: object + properties: + digits: + type: string + description: 'Set of DTMF digits to match. Allowed: `0-9`, `A-D` (case insensitive), `*`, `#`. Empty string matches any digit.' + examples: + - 0123456789#* + description: DTMF-digit detection parameters. Applies only when `detect.type` is `digit`. + Calling.DetectFaxConfig: + type: object + required: + - type + properties: + type: + type: string + enum: + - fax params: allOf: - - $ref: '#/components/schemas/Calling.DetectParams' - description: Type-specific detection parameters. + - $ref: '#/components/schemas/Calling.DetectFaxParams' + description: Fax-detection parameters. examples: - - initial_timeout: 5 - end_silence_timeout: 3 - description: Detection configuration specifying what to detect and how. - Calling.DetectParams: + - tone: CNG + allOf: + - $ref: '#/components/schemas/Calling.DetectConfig' + description: Fax-tone detection configuration. + Calling.DetectFaxParams: + type: object + properties: + tone: + allOf: + - $ref: '#/components/schemas/Calling.DetectFaxTone' + description: The fax tone to detect. Omitted means either tone matches. + examples: + - CNG + description: Fax-tone detection parameters. Applies only when `detect.type` is `fax`. + Calling.DetectFaxTone: + type: string + enum: + - CNG + - CED + - cng + - ced + description: Fax tone to detect. + Calling.DetectMachineConfig: + type: object + required: + - type + properties: + type: + type: string + enum: + - machine + params: + allOf: + - $ref: '#/components/schemas/Calling.DetectMachineParams' + description: Machine-detection parameters. + examples: + - initial_timeout: 4.5 + end_silence_timeout: 1 + allOf: + - $ref: '#/components/schemas/Calling.DetectConfig' + description: Answering-machine detection configuration. + Calling.DetectMachineParams: type: object properties: initial_timeout: type: number format: double - description: Maximum time in seconds to wait for initial detection. + description: Maximum time in seconds to wait for initial speech/voice. examples: - - 5 + - 4.5 + default: 4.5 end_silence_timeout: type: number format: double - description: Time in seconds of silence after detection to finalize the result. + description: Time in seconds of silence after voice ends to finalize the result. examples: - - 3 + - 1 + default: 1 machine_ready_timeout: type: number format: double - description: Time in seconds to wait for the machine to be ready (machine detection only). + description: Time in seconds to wait for the machine greeting to be ready. Defaults to `end_silence_timeout`. examples: - - 5 + - 1 machine_voice_threshold: type: number format: double - description: Voice duration threshold in seconds for machine vs. human detection. + description: Voice duration threshold in seconds distinguishing machine from human. examples: - 1.25 + default: 1.25 machine_words_threshold: type: integer format: int32 - description: Number of words threshold for machine vs. human detection. + description: Word-count threshold distinguishing machine greetings from human speech. examples: - 6 + default: 6 detect_interruptions: type: boolean - description: Whether to detect interruptions during machine greeting playback. + description: If `true`, detect the caller interrupting during the machine greeting playback. examples: - false + default: false detect_message_end: type: boolean - description: Whether to detect the end of a machine message. + description: If `true`, detect when a machine message has finished. examples: - - false - tone: - type: string - description: The DTMF tone to detect (digit detection only). - examples: - - '1' - digits: - type: string - description: The DTMF digits to detect (digit detection only). - examples: - - 0123456789#* - description: Parameters for call detection configuration. + - true + default: true + description: Answering-machine detection parameters. Applies only when `detect.type` is `machine`. Calling.DetectType: type: string enum: @@ -19949,6 +20535,37 @@ components: - Summarize the key agreements reached in both languages. description: Request an on-demand AI summary of the translated conversation. title: summarize Action + Calling.PlayAudioItem: + type: object + required: + - type + - params + properties: + type: + type: string + enum: + - audio + params: + allOf: + - $ref: '#/components/schemas/Calling.PlayAudioParams' + description: Audio playback parameters. + examples: + - url: https://example.com/audio.mp3 + allOf: + - $ref: '#/components/schemas/Calling.PlayMediaItem' + description: Play an audio file from a URL. + Calling.PlayAudioParams: + type: object + required: + - url + properties: + url: + type: string + format: uri + description: HTTP or HTTPS URL of the audio file to play. + examples: + - https://example.com/audio.mp3 + description: Audio file playback parameters. Calling.PlayDirection: type: string enum: @@ -19967,21 +20584,192 @@ components: description: The type of media to play. examples: - audio - params: - type: object - unevaluatedProperties: {} - description: Type-specific parameters for the media item. - examples: - - url: https://example.com/audio.mp3 - description: A media item to play on the call. + discriminator: + propertyName: type + mapping: + tts: '#/components/schemas/Calling.PlayTtsItem' + silence: '#/components/schemas/Calling.PlaySilenceItem' + ringtone: '#/components/schemas/Calling.PlayRingtoneItem' + description: A media item to play on the call. The shape of `params` is determined by `type`. Calling.PlayMediaType: type: string enum: - audio - tts - silence - - ring + - ringtone description: The type of media to play. + Calling.PlayRingtoneItem: + type: object + required: + - type + - params + properties: + type: + type: string + enum: + - ringtone + params: + allOf: + - $ref: '#/components/schemas/Calling.PlayRingtoneParams' + description: Ringtone parameters. + examples: + - name: us + duration: 10 + allOf: + - $ref: '#/components/schemas/Calling.PlayMediaItem' + description: Play a country-coded ringtone cadence. + Calling.PlayRingtoneName: + type: string + enum: + - au + - be + - ca + - cn + - cy + - cz + - de + - dk + - dz + - eg + - es + - fi + - fr + - hu + - il + - in + - jp + - ko + - pk + - pl + - ro + - rs + - ru + - sa + - tr + - uk + - us + - at + - bg + - br + - ch + - cl + - ee + - gr + - it + - lt + - mx + - my + - nl + - 'no' + - nz + - ph + - pt + - se + - sg + - th + - za + - tw + - ve + - bong + description: Ringtone name. Two-letter country code selects a country-specific ringtone cadence. + Calling.PlayRingtoneParams: + type: object + required: + - name + properties: + name: + allOf: + - $ref: '#/components/schemas/Calling.PlayRingtoneName' + description: Country code identifying the ringtone cadence. + examples: + - us + duration: + type: number + format: double + description: Maximum ringtone duration in seconds. If omitted, the ringtone plays until stopped. + examples: + - 10 + description: Ringtone playback parameters. + Calling.PlaySilenceItem: + type: object + required: + - type + - params + properties: + type: + type: string + enum: + - silence + params: + allOf: + - $ref: '#/components/schemas/Calling.PlaySilenceParams' + description: Silence parameters. + examples: + - duration: 2 + allOf: + - $ref: '#/components/schemas/Calling.PlayMediaItem' + description: Play silence for a fixed duration. + Calling.PlaySilenceParams: + type: object + required: + - duration + properties: + duration: + type: number + format: double + description: Duration of silence in seconds (must be positive). + examples: + - 2 + description: Silence playback parameters. + Calling.PlayTtsItem: + type: object + required: + - type + - params + properties: + type: + type: string + enum: + - tts + params: + allOf: + - $ref: '#/components/schemas/Calling.PlayTtsParams' + description: TTS parameters. + examples: + - text: Hello from SignalWire. + language: en-US + gender: female + allOf: + - $ref: '#/components/schemas/Calling.PlayMediaItem' + description: Play text-to-speech. Per-item `language`/`voice`/`gender` override the request-level fallbacks. + Calling.PlayTtsParams: + type: object + required: + - text + properties: + text: + type: string + description: The text to speak. + examples: + - Hello from SignalWire. + language: + type: string + description: BCP-47 language tag. Falls back to the request-level `language`, then `en-US`. + examples: + - en-US + gender: + allOf: + - $ref: '#/components/schemas/Calling.TtsGender' + description: Voice gender. Falls back to the request-level `gender`, then `female`. + examples: + - female + voice: + type: string + description: Specific voice name (provider-dependent, 1-60 chars, no special characters except `.` and `-`). Falls back to the request-level `voice`, then to `gender`. + examples: + - en-US-Wavenet-C + description: Text-to-speech playback parameters. Calling.RecordAudioParams: type: object properties: @@ -19992,8 +20780,11 @@ components: - false default: false format: - allOf: - - $ref: '#/components/schemas/Calling.RecordFormat' + type: string + enum: + - mp3 + - wav + - mp4 description: The audio format for the recording. examples: - mp3 @@ -20009,40 +20800,62 @@ components: - $ref: '#/components/schemas/Calling.PlayDirection' description: The direction of audio to record. examples: - - both - default: both + - speak + default: speak initial_timeout: type: number format: double - description: Maximum time in seconds to wait for speech before stopping. + minimum: 0 + description: Maximum time in seconds to wait for initial speech before stopping. examples: - 5 + default: 4 end_silence_timeout: type: number format: double + minimum: 0 description: Time in seconds of silence after speech to stop recording. examples: - 3 + default: 0.5 + max_length: + type: integer + format: int32 + minimum: 0 + description: Maximum recording duration in seconds. Set to `0` for no limit. + examples: + - 0 + default: 0 terminators: type: string - description: DTMF digits that will stop the recording when pressed. + description: DTMF digits that terminate the recording when pressed. Accepts `0-9`, `A-D` (case insensitive), `*`, and `#`. examples: - - '#*' + - '#' + default: '#' input_sensitivity: type: number format: double minimum: 0 maximum: 100 - description: Input sensitivity for voice detection (0-100). + description: Input sensitivity for voice detection (0.0-100.0). examples: - 50 + default: 44 description: Audio recording parameters. - Calling.RecordFormat: - type: string - enum: - - mp3 - - wav - description: The audio format for recording. + Calling.RecordParams: + type: object + required: + - audio + properties: + audio: + allOf: + - $ref: '#/components/schemas/Calling.RecordAudioParams' + description: Audio recording configuration parameters. + examples: + - format: mp3 + direction: speak + stereo: false + description: Recording configuration wrapper. Currently only audio recording is supported. Calling.ReferDevice: type: object required: @@ -20070,9 +20883,14 @@ components: properties: to: type: string - description: The SIP URI to refer the call to. + description: SIP URI to refer the call to (must start with `sip:`). examples: - sip:destination@example.com + from: + type: string + description: Optional SIP From URI (must start with `sip:` when provided). + examples: + - sip:operator@example.com username: type: string description: Optional SIP authentication username. @@ -20084,6 +20902,12 @@ components: examples: - password description: SIP REFER device parameters. + Calling.StreamStatusUrlMethod: + type: string + enum: + - GET + - POST + description: HTTP method used when invoking the `status_url` webhook. Calling.StreamTrack: type: string enum: @@ -20091,16 +20915,27 @@ components: - outbound_track - both_tracks description: The audio track to stream. + Calling.TapCodec: + type: string + enum: + - PCMA + - PCMU + - pcma + - pcmu + - OPUS + - opus + description: RTP/WebSocket audio codec. Case-sensitive; accepted in both upper and lower case. Calling.TapConfig: type: object required: - type + - params properties: type: type: string enum: - audio - description: The type of media to tap. Currently only 'audio' is supported. + description: Currently only `audio` is supported. examples: - audio params: @@ -20112,10 +20947,12 @@ components: description: The direction of audio to tap. examples: - both - description: Tap parameters including audio direction. + required: + - direction + description: Audio tap parameters. examples: - direction: both - description: Tap configuration specifying what audio to capture. + description: Tap configuration — specifies what audio to capture. Calling.TapDevice: type: object required: @@ -20127,57 +20964,127 @@ components: description: The type of tap device. examples: - rtp + discriminator: + propertyName: type + mapping: + ws: '#/components/schemas/Calling.TapDeviceWs' + description: Tap device configuration — specifies where to stream captured audio. + Calling.TapDeviceRtp: + type: object + required: + - type + - params + properties: + type: + type: string + enum: + - rtp params: allOf: - - $ref: '#/components/schemas/Calling.TapDeviceParams' - description: Device-specific connection parameters. + - $ref: '#/components/schemas/Calling.TapRtpParams' + description: RTP connection parameters. examples: - - addr: 192.168.1.100 + - addr: 198.51.100.42 port: 5060 - description: Tap device configuration specifying where to stream captured audio. - Calling.TapDeviceParams: + allOf: + - $ref: '#/components/schemas/Calling.TapDevice' + description: RTP tap device configuration. + Calling.TapDeviceType: + type: string + enum: + - rtp + - ws + description: The type of tap device to stream audio to. + Calling.TapDeviceWs: type: object + required: + - type + - params + properties: + type: + type: string + enum: + - ws + params: + allOf: + - $ref: '#/components/schemas/Calling.TapWsParams' + description: WebSocket connection parameters. + examples: + - uri: wss://example.com/tap + allOf: + - $ref: '#/components/schemas/Calling.TapDevice' + description: WebSocket tap device configuration. + Calling.TapPtime: + type: number + enum: + - 10 + - 20 + - 30 + - 40 + - 50 + - 60 + - 70 + - 80 + - 90 + - 100 + - 110 + - 120 + description: RTP packetization time in milliseconds. Must be a multiple of 10 between 10 and 120. + Calling.TapRtpParams: + type: object + required: + - addr + - port properties: addr: type: string - description: The IP address or hostname of the device (RTP). + description: Public IPv4 address of the RTP target. Private/reserved ranges are rejected. examples: - - 192.168.1.100 + - 198.51.100.42 port: type: integer format: int32 - description: The port number of the device (RTP). + minimum: 1 + maximum: 65535 + description: UDP port of the RTP target (1-65535). examples: - 5060 codec: - type: string - description: The audio codec to use. + allOf: + - $ref: '#/components/schemas/Calling.TapCodec' + description: Audio codec to request. Defaults to the call's negotiated codec. examples: - PCMU ptime: - type: integer - format: int32 - description: The packetization time in milliseconds. + allOf: + - $ref: '#/components/schemas/Calling.TapPtime' + description: Packetization time in milliseconds. Defaults to the call's negotiated ptime. examples: - 20 + description: RTP tap target parameters. + Calling.TapWsParams: + type: object + required: + - uri + properties: uri: type: string - description: The WebSocket URI to stream audio to (WS). + description: WebSocket URI of the tap target. Must start with `ws://` or `wss://`. examples: - wss://example.com/tap - rate: - type: integer - format: int32 - description: The audio sample rate in Hz. + codec: + allOf: + - $ref: '#/components/schemas/Calling.TapCodec' + description: Audio codec to request. Defaults to the call's negotiated codec. examples: - - 8000 - description: Parameters for the tap device connection. - Calling.TapDeviceType: + - PCMU + description: WebSocket tap target parameters. + Calling.TtsGender: type: string enum: - - rtp - - ws - description: The type of tap device to stream audio to. + - male + - female + description: Text-to-speech voice gender. Campaign: type: object required: diff --git a/specs/signalwire-rest/calling-api/calls/models/examples.tsp b/specs/signalwire-rest/calling-api/calls/models/examples.tsp index 183a374b1..1ed9c330c 100644 --- a/specs/signalwire-rest/calling-api/calls/models/examples.tsp +++ b/specs/signalwire-rest/calling-api/calls/models/examples.tsp @@ -19,6 +19,8 @@ const dialCallExample = #{ status_url: "https://example.com/status_callback", status_events: #["answered", "ended"], codecs: #["PCMU", "PCMA"], + timeout: 30, + max_price_per_minute: 0.05, }, }, }; @@ -38,16 +40,24 @@ const hangupCallExample = #{ request: #{ command: "calling.end", id: callId, - params: #{ reason: HangupReason.hangup }, + params: #{ reason: HangupReason.hangup, async: false }, }, }; const holdCallExample = #{ - request: #{ command: "calling.ai_hold", id: callId, params: #{} }, + request: #{ + command: "calling.ai_hold", + id: callId, + params: #{ timeout: "300", async: false }, + }, }; const unholdCallExample = #{ - request: #{ command: "calling.ai_unhold", id: callId, params: #{} }, + request: #{ + command: "calling.ai_unhold", + id: callId, + params: #{ async: false }, + }, }; const aiMessageExample = #{ @@ -57,6 +67,7 @@ const aiMessageExample = #{ params: #{ role: "system", message_text: "You are now in expert mode. Provide detailed technical responses and use industry terminology.", + async: false, }, }, }; @@ -178,7 +189,7 @@ const disconnectCallExample = #{ request: #{ command: "calling.disconnect", id: callId, - params: #{}, + params: #{ async: false }, }, }; @@ -189,9 +200,16 @@ const playCallExample = #{ id: callId, params: #{ control_id: "play-control-1", - play: #[#{ type: PlayMediaType.audio, params: #{ url: "https://example.com/audio.mp3" } }], + play: #[ + #{ + type: PlayMediaType.audio, + params: #{ url: "https://example.com/audio.mp3" }, + } + ], volume: 0, - direction: PlayDirection.both, + direction: PlayDirection.listen, + loop: 1, + async: false, }, }, }; @@ -200,7 +218,7 @@ const playPauseCallExample = #{ request: #{ command: "calling.play.pause", id: callId, - params: #{ control_id: "play-control-1" }, + params: #{ control_id: "play-control-1", async: false }, }, }; @@ -208,7 +226,7 @@ const playResumeCallExample = #{ request: #{ command: "calling.play.resume", id: callId, - params: #{ control_id: "play-control-1" }, + params: #{ control_id: "play-control-1", async: false }, }, }; @@ -216,7 +234,7 @@ const playStopCallExample = #{ request: #{ command: "calling.play.stop", id: callId, - params: #{ control_id: "play-control-1" }, + params: #{ control_id: "play-control-1", async: false }, }, }; @@ -224,7 +242,7 @@ const playVolumeCallExample = #{ request: #{ command: "calling.play.volume", id: callId, - params: #{ control_id: "play-control-1", volume: 5 }, + params: #{ control_id: "play-control-1", volume: 5, async: false }, }, }; @@ -235,7 +253,9 @@ const recordCallExample = #{ id: callId, params: #{ control_id: "record-control-1", - audio: #{ format: RecordFormat.mp3, direction: PlayDirection.both, stereo: false }, + record: #{ + audio: #{ format: "mp3", direction: PlayDirection.speak, stereo: false }, + }, }, }, }; @@ -273,6 +293,12 @@ const collectCallExample = #{ control_id: "collect-control-1", initial_timeout: 5, digits: #{ max: 4, terminators: "#" }, + continuous: false, + partial_results: false, + send_start_of_input: false, + start_input_timers: false, + status_url: "https://example.com/collect_callback", + async: false, }, }, }; @@ -281,7 +307,7 @@ const collectStopCallExample = #{ request: #{ command: "calling.collect.stop", id: callId, - params: #{ control_id: "collect-control-1" }, + params: #{ control_id: "collect-control-1", async: false }, }, }; @@ -289,7 +315,7 @@ const collectStartInputTimersCallExample = #{ request: #{ command: "calling.collect.start_input_timers", id: callId, - params: #{ control_id: "collect-control-1" }, + params: #{ control_id: "collect-control-1", async: false }, }, }; @@ -300,8 +326,12 @@ const detectCallExample = #{ id: callId, params: #{ control_id: "detect-control-1", - detect: #{ type: DetectType.machine }, + detect: #{ + type: DetectType.machine, + params: #{ initial_timeout: 4.5, end_silence_timeout: 1.0 }, + }, timeout: 30, + async: false, }, }, }; @@ -310,7 +340,7 @@ const detectStopCallExample = #{ request: #{ command: "calling.detect.stop", id: callId, - params: #{ control_id: "detect-control-1" }, + params: #{ control_id: "detect-control-1", async: false }, }, }; @@ -322,7 +352,11 @@ const tapCallExample = #{ params: #{ control_id: "tap-control-1", tap: #{ type: "audio", params: #{ direction: PlayDirection.both } }, - device: #{ type: TapDeviceType.rtp, params: #{ addr: "192.168.1.100", port: 5060 } }, + device: #{ + type: TapDeviceType.rtp, + params: #{ addr: "198.51.100.42", port: 5060 }, + }, + async: false, }, }, }; @@ -331,7 +365,7 @@ const tapStopCallExample = #{ request: #{ command: "calling.tap.stop", id: callId, - params: #{ control_id: "tap-control-1" }, + params: #{ control_id: "tap-control-1", async: false }, }, }; @@ -343,7 +377,8 @@ const streamCallExample = #{ params: #{ control_id: "stream-control-1", url: "wss://example.com/stream", - track: StreamTrack.both_tracks, + track: StreamTrack.inbound_track, + async: false, }, }, }; @@ -352,7 +387,7 @@ const streamStopCallExample = #{ request: #{ command: "calling.stream.stop", id: callId, - params: #{ control_id: "stream-control-1" }, + params: #{ control_id: "stream-control-1", async: false }, }, }; @@ -361,7 +396,7 @@ const denoiseCallExample = #{ request: #{ command: "calling.denoise", id: callId, - params: #{}, + params: #{ async: false }, }, }; @@ -369,7 +404,7 @@ const denoiseStopCallExample = #{ request: #{ command: "calling.denoise.stop", id: callId, - params: #{}, + params: #{ async: false }, }, }; @@ -378,7 +413,7 @@ const aiStopCallExample = #{ request: #{ command: "calling.ai.stop", id: callId, - params: #{ control_id: "ai-control-1" }, + params: #{ control_id: "ai-control-1", async: false }, }, }; @@ -387,7 +422,7 @@ const sendFaxStopCallExample = #{ request: #{ command: "calling.send_fax.stop", id: callId, - params: #{ control_id: "fax-send-control-1" }, + params: #{ control_id: "fax-send-control-1", async: false }, }, }; @@ -395,7 +430,7 @@ const receiveFaxStopCallExample = #{ request: #{ command: "calling.receive_fax.stop", id: callId, - params: #{ control_id: "fax-receive-control-1" }, + params: #{ control_id: "fax-receive-control-1", async: false }, }, }; @@ -406,6 +441,7 @@ const referCallExample = #{ id: callId, params: #{ device: #{ type: "sip", params: #{ to: "sip:destination@example.com" } }, + async: false, }, }, }; @@ -415,7 +451,7 @@ const transferCallExample = #{ request: #{ command: "calling.transfer", id: callId, - params: #{ dest: "sip:destination@example.com" }, + params: #{ dest: "sip:destination@example.com", async: false }, }, }; @@ -424,6 +460,9 @@ const userEventCallExample = #{ request: #{ command: "calling.user_event", id: callId, - params: #{ event: #{ action: "custom_action", data: "example" } }, + params: #{ + event: #{ action: "custom_action", data: "example" }, + async: false, + }, }, }; diff --git a/specs/signalwire-rest/calling-api/calls/models/requests.tsp b/specs/signalwire-rest/calling-api/calls/models/requests.tsp index 01f052103..fb4876706 100644 --- a/specs/signalwire-rest/calling-api/calls/models/requests.tsp +++ b/specs/signalwire-rest/calling-api/calls/models/requests.tsp @@ -62,6 +62,10 @@ model CallHangupRequest { @doc("Set the reason why the call was hung up.") @example(HangupReason.hangup) reason?: HangupReason; + + @doc("If `true`, the HTTP response returns immediately without waiting for the hangup to complete.") + @example(false) + async?: boolean = false; }; } @summary("calling.ai_hold") @@ -76,18 +80,20 @@ model CallHoldRequest { @doc(paramsDescription) params: { - @doc("The duration to hold the caller in seconds.") - @example(300) - @minValue(1) - @maxValue(300) - timeout?: int32 = 300; + @doc("Hold timeout, expressed as a numeric string of seconds. Note: must be sent as a string — integer payloads are rejected.") + @example("300") + timeout?: string; @doc(""" A system message added to the AI conversation before placing the caller on hold. The AI will speak this message to the caller before hold music begins. """) @example("Please hold while I transfer you to a specialist.") - prompt?: string = "Tell the user you are putting them on hold."; + prompt?: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the hold to take effect.") + @example(false) + async?: boolean = false; }; } @@ -103,12 +109,9 @@ model CallUnholdRequest { @doc(paramsDescription) params: { - @doc(""" - A system message added to the AI conversation when taking the caller off hold. - The AI will use this context when resuming the conversation. - """) - @example("The user has been connected to a specialist.") - prompt?: string = "The user has been taken off hold."; + @doc("If `true`, the HTTP response returns immediately without waiting for the unhold to take effect.") + @example(false) + async?: boolean = false; }; } @@ -140,21 +143,19 @@ model CallAIMessageRequest { @doc(paramsDescription) params: { @doc(""" - The role that the message is from. Required when `reset` is not provided. Each role type has a different purpose and will influence how the AI will interpret the message. - - `system`: Inject instructions or context that modify the AI's behavior mid-conversation without the caller hearing it. This could change the AI's personality, add new constraints, provide context about the conversation, or give the AI information it should know going forward. - - `user`: Inject a message as if the caller said it. This would appear in the conversation history as coming from the caller, and the AI would respond to it as if the caller just spoke it. - - `assistant`: Inject a message as if the AI said it. This would appear as an AI response in the conversation history. The AI would treat this as its own previous response when generating future replies. + The role that the message is from. By convention pair with `message_text` (the validator itself does not enforce this). + - `system`: Inject instructions or context that modify the AI's behavior mid-conversation without the caller hearing it. + - `user`: Inject a message as if the caller said it. The AI will respond as if the caller spoke it. + - `assistant`: Inject a message as if the AI said it. Appears as an AI response in the conversation history. """) @example("system") role?: "system" | "user" | "assistant"; - @doc(""" - The text content that will be sent to the AI. Required when `reset` is not provided. - """) + @doc("The text content sent to the AI. Typically required unless `reset` is provided.") @example("You are now in expert mode. Provide detailed technical responses.") message_text?: string; - @doc("Parameters for resetting the AI conversation state. When provided, `role` and `message_text` are optional.") + @doc("Parameters for resetting the AI conversation state.") @example(#{ full_reset: true, system_prompt: "You are a helpful assistant.", @@ -164,6 +165,10 @@ model CallAIMessageRequest { @doc("Arbitrary JSON data to merge into the AI session's global data store.") @example(#{ customer_tier: "premium", language: "en" }) global_data?: TypeSpec.Record; + + @doc("If `true`, the HTTP response returns immediately without waiting for the message to be delivered.") + @example(false) + async?: boolean = false; }; } @@ -262,6 +267,10 @@ model CallLiveTranscribeRequest { params: { @doc("The transcription action to perform: start, stop, or summarize.") action: LiveTranscribeAction; + + @doc("If `true`, the HTTP response returns immediately without waiting for the action to take effect.") + @example(false) + async?: boolean = false; }; } @@ -399,9 +408,13 @@ model CallLiveTranslateRequest { @doc("The translation action to perform: start, stop, summarize, or inject.") action: LiveTranslateAction; - @doc("A URL to receive status update callbacks for the translation session.") + @doc("HTTP or HTTPS URL that receives translation-session webhooks.") @example("https://example.com/status_callback") status_url?: url; + + @doc("If `true`, the HTTP response returns immediately without waiting for the action to take effect.") + @example(false) + async?: boolean = false; }; } @@ -416,43 +429,66 @@ model CallCreateRequest { } model CallCreateParamsBase { - @doc("The address that initiated the call. Can be either a E.164 formatted number (`+xxxxxxxxxxx`), or a SIP endpoint (`sip:xxx@yyy.zzz`).") + @doc("The address that initiates the call. For PSTN destinations, must be an E.164 number; for SIP/Verto destinations may also be a SIP URI (`sip:user@host`) or a short caller-id token.") @example("sip:from-sip@example-112233445566.sip.signalwire.com") from: string; - @doc("The address that received the call. Can be either a E.164 formatted number (`+xxxxxxxxxxx`), or a SIP endpoint (`sip:xxx@yyy.zzz`).") + @doc("Destination address. Accepts E.164 (`+xxxxxxxxxxx`), SIP URI (`sip:` / `sips:`), Verto URI (`verto:`), client address (`client:`), or a fabric address. Required unless `to_script` is provided.") @example("sip:from-sip@example-112233445567.sip.signalwire.com") - to: string; + to?: string; - @doc("The number, in E.164 format, or identifier of the caller.") + @doc("Inline SWML document (JSON or YAML string), or an `http(s)://` URL that returns one, executed at the destination end. Useful for directing the call to a RelayBin / external SWML handler. When present, `to` may be omitted.") + @example("https://example.com/destination.swml.json") + to_script?: string | SWMLObject; + + @doc("Caller ID displayed to the destination. E.164 for PSTN; short caller-id token or SIP URI for SIP/Verto.") @example("+1234567890") caller_id?: string; - @doc("The Fallback URL to handle the call. This parameter allows you to specify a backup webhook or different route in your code containing SWML instructions for handling the call.") + @doc("Fallback URL that returns SWML if the primary `url` fails.") @example(CallFallbackURLExample) fallback_url?: string; - @doc("A URL that will recieve status updates of the current call. Any call events defined in `status_events` will be delivered to the defined URL.") + @doc("HTTP or HTTPS URL that receives call lifecycle webhooks for events listed in `status_events`.") @example("https://example.com/status_callback") status_url?: url; - @doc("The call events that will be monitored and sent to the `status_url` when active.") + @doc("Call lifecycle events that will be delivered to `status_url`.") @example(#["answered", "ended"]) status_events?: ( - | "answered" | "queued" | "initiated" | "ringing" + | "answered" | "ending" | "ended")[] = #["ended"]; - @doc("The HTTP method to use when requesting the URL.") + @doc("HTTP method used when requesting the `url`. Defaults to `POST`.") @example("POST") - url_method?: string = "POST"; + url_method?: "GET" | "POST" = "POST"; - @doc("A list of codecs to use for the call. Can be an array of codec strings or a comma-separated string. Valid codecs are: `PCMU`, `PCMA`, `G722`, `G729`, `OPUS`, `VP8`, `H264`. For PSTN calls, `PCMA` and `PCMU` are recommended as many other codecs are not supported by PSTN gateways. If a SIP URI with included codecs is passed in the `to` field along with this parameter, the SIP URI codecs will be prioritized.") + @doc("Codecs to offer on the outbound call. May be provided as an array or a comma-separated string. Allowed values: `PCMU`, `PCMA`, `G722`, `G729`, `OPUS`, `AMR-WB`, `VP8`, `H264`. For PSTN, `PCMU`/`PCMA` are widely supported. If the `to` value is a SIP URI containing `codecs=...`, those take precedence.") @example(#["OPUS", "G729", "VP8", "PCMA"]) codecs?: string[] | string; + + @doc("Ring timeout in seconds. Must be between 1 and 600.") + @example(30) + @minValue(1) + @maxValue(600) + timeout?: int32; + + @doc("Maximum per-minute price (in dollars). If the computed billing route exceeds this value, the call is rejected.") + @example(0.05) + @minValue(0) + max_price_per_minute?: float64; + + @doc("DTMF digits to send after the call is answered. Allowed characters: `0-9`, `A-D`, `*`, `#`, `w` (wait), `,` (pause).") + @example("1234#") + send_digits?: string; + + @doc("Preferred FreeSWITCH region(s) for call routing. Must be drawn from the project's available regions. Accepts a single region or a priority-ordered array.") + @example(#["us-east-1", "us-west-2"]) + region?: string | string[]; } @summary("dial (URL)") @@ -509,6 +545,15 @@ model CallUpdateParamsURL is CallUpdateParamsBase { url: string; } +/** + * Update a call in progress — cancel, complete, or redirect the SWML flow. + * + * State-transition rules: + * - `status: canceled` is only valid while the leg is `queued` or `ringing`. + * - `status: completed` is only valid while the leg is `answered` (or in-progress). + * - Supplying `url` or `swml` (redirect) is only valid while the leg is `answered`. + * - Calls in terminal states (`busy`, `failed`, `no-answer`, `canceled`, `completed`) cannot be updated. + */ @summary("update") model CallUpdateCurrentCallRequest { @doc(updateCommandDescription) @@ -534,13 +579,18 @@ model CallDisconnectRequest { command: "calling.disconnect"; @doc(paramsDescription) - params: {}; + params: { + @doc("If `true`, the HTTP response returns immediately without waiting for the disconnect to take effect.") + @example(false) + async?: boolean = false; + }; } // ============================================ // Play Commands // ============================================ + @doc("The type of media to play.") enum PlayMediaType { @doc("Play an audio file from a URL.") @@ -552,8 +602,8 @@ enum PlayMediaType { @doc("Play silence for a specified duration.") silence, - @doc("Play a ringing tone.") - ring, + @doc("Play a ringtone by country code.") + ringtone, } @doc("The direction of audio playback relative to the call participants.") @@ -568,17 +618,162 @@ enum PlayDirection { both, } -@doc("A media item to play on the call.") +@doc("Text-to-speech voice gender.") +enum TtsGender { + male, + female, +} + +@doc("Ringtone name. Two-letter country code selects a country-specific ringtone cadence.") +enum PlayRingtoneName { + au, + be, + ca, + cn, + cy, + cz, + de, + dk, + dz, + eg, + es, + fi, + fr, + hu, + il, + `in`, + jp, + ko, + pk, + pl, + ro, + rs, + ru, + sa, + tr, + uk, + us, + at, + bg, + br, + ch, + cl, + ee, + gr, + it, + lt, + mx, + my, + nl, + no, + nz, + ph, + pt, + se, + sg, + th, + za, + tw, + ve, + bong, +} + +@doc("Audio file playback parameters.") +model PlayAudioParams { + @doc("HTTP or HTTPS URL of the audio file to play.") + @example("https://example.com/audio.mp3") + url: url; +} + +@doc("Text-to-speech playback parameters.") +model PlayTtsParams { + @doc("The text to speak.") + @example("Hello from SignalWire.") + text: string; + + @doc("BCP-47 language tag. Falls back to the request-level `language`, then `en-US`.") + @example("en-US") + language?: string; + + @doc("Voice gender. Falls back to the request-level `gender`, then `female`.") + @example(TtsGender.female) + gender?: TtsGender; + + @doc("Specific voice name (provider-dependent, 1-60 chars, no special characters except `.` and `-`). Falls back to the request-level `voice`, then to `gender`.") + @example("en-US-Wavenet-C") + voice?: string; +} + +@doc("Silence playback parameters.") +model PlaySilenceParams { + @doc("Duration of silence in seconds (must be positive).") + @example(2.0) + duration: float64; +} + +@doc("Ringtone playback parameters.") +model PlayRingtoneParams { + @doc("Country code identifying the ringtone cadence.") + @example(PlayRingtoneName.us) + name: PlayRingtoneName; + + @doc("Maximum ringtone duration in seconds. If omitted, the ringtone plays until stopped.") + @example(10.0) + duration?: float64; +} + +@doc("A media item to play on the call. The shape of `params` is determined by `type`.") +@discriminator("type") model PlayMediaItem { @doc("The type of media to play.") @example(PlayMediaType.audio) type: PlayMediaType; +} - @doc("Type-specific parameters for the media item.") +@doc("Play an audio file from a URL.") +model PlayAudioItem extends PlayMediaItem { + type: PlayMediaType.audio; + + @doc("Audio playback parameters.") @example(#{ url: "https://example.com/audio.mp3" }) - params?: TypeSpec.Record; + params: PlayAudioParams; +} + +@doc("Play text-to-speech. Per-item `language`/`voice`/`gender` override the request-level fallbacks.") +model PlayTtsItem extends PlayMediaItem { + type: PlayMediaType.tts; + + @doc("TTS parameters.") + @example(#{ text: "Hello from SignalWire.", language: "en-US", gender: TtsGender.female }) + params: PlayTtsParams; +} + +@doc("Play silence for a fixed duration.") +model PlaySilenceItem extends PlayMediaItem { + type: PlayMediaType.silence; + + @doc("Silence parameters.") + @example(#{ duration: 2.0 }) + params: PlaySilenceParams; +} + +@doc("Play a country-coded ringtone cadence.") +model PlayRingtoneItem extends PlayMediaItem { + type: PlayMediaType.ringtone; + + @doc("Ringtone parameters.") + @example(#{ name: PlayRingtoneName.us, duration: 10.0 }) + params: PlayRingtoneParams; } +/** + * Play media (audio files, text-to-speech, silence, or ringtones) on an active call. + * + * The HTTP response confirms the command was accepted. Playback lifecycle + * is delivered asynchronously via the `status_url` webhook, with payloads + * of the form `{control_id, call_id, node_id, state}` where `state` is one + * of `playing`, `paused`, `finished`, or `error`. + */ @summary("calling.play") model CallPlayRequest { @doc(uuidDescription) @@ -591,31 +786,48 @@ model CallPlayRequest { @doc(paramsDescription) params: { - @doc("Unique identifier for this play operation, used to control it later.") + @doc("Unique identifier for this play operation, used to control it later. Must be unique per active play on this call.") @example("play-control-1") - control_id?: string; + control_id: string; - @doc("Array of media objects to play.") + @doc("Ordered list of media items to play. Items play sequentially.") @example(#[#{ type: PlayMediaType.audio, params: #{ url: "https://example.com/audio.mp3" } }]) - play: PlayMediaItem[]; + play: (PlayAudioItem | PlayTtsItem | PlaySilenceItem | PlayRingtoneItem)[]; - @doc("Volume adjustment in dB (-40 to 40).") + @doc("Volume adjustment in dB. Must be between -40 and 40.") @example(0) @minValue(-40) @maxValue(40) volume?: float64 = 0; - @doc("The direction of audio playback.") - @example(PlayDirection.both) - direction?: PlayDirection = PlayDirection.both; + @doc("The direction of audio playback relative to the call participants.") + @example(PlayDirection.listen) + direction?: PlayDirection = PlayDirection.listen; - @doc("Number of times to loop playback. 0 for infinite loop.") + @doc("Number of times the full `play` sequence is repeated. `0` loops forever; `N > 0` plays a total of N times.") @example(1) - loop?: int32; + @minValue(0) + loop?: int32 = 1; + + @doc("Default BCP-47 language tag applied to any TTS item that does not set its own `language`.") + @example("en-US") + language?: string = "en-US"; - @doc("A URL to receive status update callbacks for the play operation.") + @doc("Default voice applied to any TTS item that does not set its own `voice`. Defaults to the request-level `gender` when unset.") + @example("en-US-Wavenet-C") + voice?: string; + + @doc("Default voice gender applied to any TTS item that does not set its own `gender`.") + @example(TtsGender.female) + gender?: TtsGender = TtsGender.female; + + @doc("HTTP or HTTPS URL that receives playback lifecycle webhooks (`playing`, `paused`, `finished`, `error`).") @example("https://example.com/status_callback") status_url?: url; + + @doc("If `true`, the HTTP response returns immediately without waiting for playback to start.") + @example(false) + async?: boolean = false; }; } @@ -634,6 +846,10 @@ model CallPlayPauseRequest { @doc("The control ID of the play operation to pause.") @example("play-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the pause to take effect.") + @example(false) + async?: boolean = false; }; } @@ -652,6 +868,10 @@ model CallPlayResumeRequest { @doc("The control ID of the play operation to resume.") @example("play-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the resume to take effect.") + @example(false) + async?: boolean = false; }; } @@ -670,6 +890,10 @@ model CallPlayStopRequest { @doc("The control ID of the play operation to stop.") @example("play-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stop to take effect.") + @example(false) + async?: boolean = false; }; } @@ -689,11 +913,15 @@ model CallPlayVolumeRequest { @example("play-control-1") control_id: string; - @doc("Volume adjustment in dB (-40 to 40).") + @doc("Volume adjustment in dB. Must be between -40 and 40.") @example(5) @minValue(-40) @maxValue(40) volume: float64; + + @doc("If `true`, the HTTP response returns immediately without waiting for the volume change to take effect.") + @example(false) + async?: boolean = false; }; } @@ -701,15 +929,6 @@ model CallPlayVolumeRequest { // Record Commands // ============================================ -@doc("The audio format for recording.") -enum RecordFormat { - @doc("MP3 audio format.") - mp3, - - @doc("WAV audio format.") - wav, -} - @doc("Audio recording parameters.") model RecordAudioParams { @doc("Whether to play a beep before recording starts.") @@ -717,37 +936,56 @@ model RecordAudioParams { beep?: boolean = false; @doc("The audio format for the recording.") - @example(RecordFormat.mp3) - format?: RecordFormat = RecordFormat.mp3; + @example("mp3") + format?: "mp3" | "wav" | "mp4" = "mp3"; @doc("Whether to record in stereo (separate channels for each direction).") @example(false) stereo?: boolean = false; @doc("The direction of audio to record.") - @example(PlayDirection.both) - direction?: PlayDirection = PlayDirection.both; + @example(PlayDirection.speak) + direction?: PlayDirection = PlayDirection.speak; - @doc("Maximum time in seconds to wait for speech before stopping.") + @doc("Maximum time in seconds to wait for initial speech before stopping.") @example(5) - initial_timeout?: float64; + @minValue(0) + initial_timeout?: float64 = 4.0; @doc("Time in seconds of silence after speech to stop recording.") @example(3) - end_silence_timeout?: float64; + @minValue(0) + end_silence_timeout?: float64 = 0.5; - @doc("DTMF digits that will stop the recording when pressed.") - @example("#*") - terminators?: string; + @doc("Maximum recording duration in seconds. Set to `0` for no limit.") + @example(0) + @minValue(0) + max_length?: int32 = 0; + + @doc("DTMF digits that terminate the recording when pressed. Accepts `0-9`, `A-D` (case insensitive), `*`, and `#`.") + @example("#") + terminators?: string = "#"; - @doc("Input sensitivity for voice detection (0-100).") + @doc("Input sensitivity for voice detection (0.0-100.0).") @example(50) @minValue(0) @maxValue(100) - input_sensitivity?: float64; + input_sensitivity?: float64 = 44.0; +} + +@doc("Recording configuration wrapper. Currently only audio recording is supported.") +model RecordParams { + @doc("Audio recording configuration parameters.") + @example(#{ format: "mp3", direction: PlayDirection.speak, stereo: false }) + audio: RecordAudioParams; } @summary("calling.record") +@doc(""" + Starts recording an active call. The HTTP response returns the call leg — the recording URL + is not included. Recording runs asynchronously; provide `status_url` to receive a webhook when + the recording finishes (with the final URL), or query the call's events endpoint. + """) model CallRecordRequest { @doc(uuidDescription) @example(CallIdExample) @@ -759,15 +997,19 @@ model CallRecordRequest { @doc(paramsDescription) params: { - @doc("Unique identifier for this record operation, used to control it later.") + @doc("Unique identifier for this record operation, used to control it later. Must be unique among active recordings on the call.") @example("record-control-1") - control_id?: string; + control_id: string; - @doc("Audio recording configuration parameters.") - @example(#{ format: RecordFormat.mp3, direction: PlayDirection.both, stereo: false }) - audio?: RecordAudioParams; + @doc("Recording configuration. Wraps the media-type-specific parameters (currently only `audio`).") + @example(#{ audio: #{ format: "mp3", direction: PlayDirection.speak, stereo: false } }) + record: RecordParams; - @doc("A URL to receive status update callbacks for the record operation.") + @doc("If `true`, the request returns immediately without waiting for the recording to start. Defaults to `false`.") + @example(true) + async?: boolean = false; + + @doc("Webhook URL invoked with recording events — including a `finished` event that contains the final recording URL. Must begin with `http://` or `https://`.") @example("https://example.com/status_callback") status_url?: url; }; @@ -788,6 +1030,14 @@ model CallRecordPauseRequest { @doc("The control ID of the recording to pause.") @example("record-control-1") control_id: string; + + @doc("How the paused audio is handled. `skip` omits paused audio from the output file; `silence` replaces it with silence, preserving timing.") + @example("skip") + behavior?: "skip" | "silence" = "skip"; + + @doc("If `true`, the request returns immediately. Defaults to `false`.") + @example(true) + async?: boolean = false; }; } @@ -806,6 +1056,10 @@ model CallRecordResumeRequest { @doc("The control ID of the recording to resume.") @example("record-control-1") control_id: string; + + @doc("If `true`, the request returns immediately. Defaults to `false`.") + @example(true) + async?: boolean = false; }; } @@ -824,6 +1078,10 @@ model CallRecordStopRequest { @doc("The control ID of the recording to stop.") @example("record-control-1") control_id: string; + + @doc("If `true`, the request returns immediately. Defaults to `false`.") + @example(true) + async?: boolean = false; }; } @@ -831,32 +1089,39 @@ model CallRecordStopRequest { // Collect Commands // ============================================ +@doc("Speech recognition engine for `calling.collect`. Note: values are case-sensitive and differ from the SWML engine names.") +enum CollectSpeechEngine { + Google: "Google", + `Google.V2`: "Google.V2", + Deepgram: "Deepgram", +} + @doc("Parameters for collecting DTMF digit input.") model CollectDigitsParams { - @doc("Maximum number of digits to collect.") + @doc("Maximum number of digits to collect. Must be positive.") @example(4) - max?: int32; + max: int32; - @doc("DTMF digits that signal the end of input.") + @doc("DTMF digits that terminate input when pressed. Allowed: `0-9`, `A-D` (case insensitive), `*`, `#`. Empty string disables terminators.") @example("#") terminators?: string; - @doc("Time in seconds to wait between digit presses.") + @doc("Time in seconds to wait between digit presses. Must be positive. Defaults to the server-configured digit timeout when omitted.") @example(5) digit_timeout?: float64; } @doc("Parameters for collecting speech input.") model CollectSpeechParams { - @doc("Time in seconds of silence after speech to consider input complete.") + @doc("Time in seconds of silence after speech to consider input complete. Must be positive.") @example(3) end_silence_timeout?: float64; - @doc("Maximum time in seconds to wait for speech input.") + @doc("Maximum time in seconds to wait for speech input. Must be positive.") @example(30) speech_timeout?: float64; - @doc("The language for speech recognition (e.g., 'en-US').") + @doc("Speech recognition language. Accepts a BCP-47 tag (e.g. `en-US`) or an `engine:tag` override (e.g. `Deepgram:en-US`) to pick a specific engine. Defaults to the server-configured ASR language when omitted.") @example("en-US") language?: string; @@ -864,11 +1129,27 @@ model CollectSpeechParams { @example(#["yes", "no", "maybe"]) hints?: string[]; - @doc("The speech recognition engine to use.") - @example("default") - engine?: string; -} - + @doc("Provider-specific ASR model name (e.g. Deepgram `nova-3`). Freeform string; validation is performed by the selected engine.") + @example("nova-3") + `model`?: string; + + @doc("Speech recognition engine to use.") + @example(CollectSpeechEngine.Deepgram) + engine?: CollectSpeechEngine; +} + +/** + * Collect user input (DTMF digits, speech, or both) on an active call. + * + * At least one of `digits` or `speech` must be provided; requests missing + * both return 400. Results are delivered asynchronously via the `status_url` + * webhook. Digit events have the shape `{control_id, call_id, node_id, result: {type:"digit", params: {digits, terminator}}}` + * and speech events `{..., result: {type:"speech", params: {text, confidence}}}`. + * + * When `start_input_timers` is `false`, the `initial_timeout` clock does not + * start until you send `calling.collect.start_input_timers` for the same + * `control_id`. + */ @summary("calling.collect") model CallCollectRequest { @doc(uuidDescription) @@ -881,29 +1162,45 @@ model CallCollectRequest { @doc(paramsDescription) params: { - @doc("Unique identifier for this collect operation, used to control it later.") + @doc("Unique identifier for this collect operation, used to control it later. Must be unique per active collect on this call.") @example("collect-control-1") - control_id?: string; + control_id: string; - @doc("Maximum time in seconds to wait for initial input.") + @doc("Maximum time in seconds to wait for initial input. Must be positive. Defaults to the server-configured no-input timeout when omitted.") @example(5) initial_timeout?: float64; - @doc("Configuration for collecting DTMF digit input.") + @doc("Configuration for collecting DTMF digit input. Provide `digits`, `speech`, or both.") @example(#{ max: 4, terminators: "#" }) digits?: CollectDigitsParams; - @doc("Configuration for collecting speech input.") + @doc("Configuration for collecting speech input. Provide `digits`, `speech`, or both.") @example(#{ end_silence_timeout: 3, language: "en-US" }) speech?: CollectSpeechParams; - @doc("Whether to continuously collect input (restart after each result).") + @doc("If `true`, the collect restarts after each result until `calling.collect.stop` is called. Continuous events include a `state` field indicating collect state.") + @example(false) + continuous?: boolean = false; + + @doc("If `true`, partial results are delivered as they are recognized, and events include a `final` field (`false` for partial, `true` for final).") + @example(false) + partial_results?: boolean = false; + + @doc("If `true`, a `start_of_input` webhook event is fired when input is first detected.") @example(false) - continuous?: boolean; + send_start_of_input?: boolean = false; - @doc("Whether to send partial results as speech is recognized.") + @doc("If `false`, the initial-timeout clock does not start until `calling.collect.start_input_timers` is called for this `control_id`.") @example(false) - partial_results?: boolean; + start_input_timers?: boolean = false; + + @doc("HTTP or HTTPS URL that receives collect result webhooks.") + @example("https://example.com/collect_callback") + status_url?: url; + + @doc("If `true`, the HTTP response returns immediately without waiting for the collect to be set up.") + @example(false) + async?: boolean = false; }; } @@ -922,6 +1219,10 @@ model CallCollectStopRequest { @doc("The control ID of the collect operation to stop.") @example("collect-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stop to take effect.") + @example(false) + async?: boolean = false; }; } @@ -940,6 +1241,10 @@ model CallCollectStartInputTimersRequest { @doc("The control ID of the collect operation to start input timers for.") @example("collect-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the timers to start.") + @example(false) + async?: boolean = false; }; } @@ -959,56 +1264,100 @@ enum DetectType { digit, } -@doc("Parameters for call detection configuration.") -model DetectParams { - @doc("Maximum time in seconds to wait for initial detection.") - @example(5) - initial_timeout?: float64; +@doc("Answering-machine detection parameters. Applies only when `detect.type` is `machine`.") +model DetectMachineParams { + @doc("Maximum time in seconds to wait for initial speech/voice.") + @example(4.5) + initial_timeout?: float64 = 4.5; - @doc("Time in seconds of silence after detection to finalize the result.") - @example(3) - end_silence_timeout?: float64; + @doc("Time in seconds of silence after voice ends to finalize the result.") + @example(1.0) + end_silence_timeout?: float64 = 1.0; - @doc("Time in seconds to wait for the machine to be ready (machine detection only).") - @example(5) + @doc("Time in seconds to wait for the machine greeting to be ready. Defaults to `end_silence_timeout`.") + @example(1.0) machine_ready_timeout?: float64; - @doc("Voice duration threshold in seconds for machine vs. human detection.") + @doc("Voice duration threshold in seconds distinguishing machine from human.") @example(1.25) - machine_voice_threshold?: float64; + machine_voice_threshold?: float64 = 1.25; - @doc("Number of words threshold for machine vs. human detection.") + @doc("Word-count threshold distinguishing machine greetings from human speech.") @example(6) - machine_words_threshold?: int32; + machine_words_threshold?: int32 = 6; - @doc("Whether to detect interruptions during machine greeting playback.") + @doc("If `true`, detect the caller interrupting during the machine greeting playback.") @example(false) - detect_interruptions?: boolean; + detect_interruptions?: boolean = false; - @doc("Whether to detect the end of a machine message.") - @example(false) - detect_message_end?: boolean; + @doc("If `true`, detect when a machine message has finished.") + @example(true) + detect_message_end?: boolean = true; +} - @doc("The DTMF tone to detect (digit detection only).") - @example("1") - tone?: string; +@doc("Fax tone to detect.") +enum DetectFaxTone { + CNG: "CNG", + CED: "CED", + cng: "cng", + ced: "ced", +} - @doc("The DTMF digits to detect (digit detection only).") +@doc("Fax-tone detection parameters. Applies only when `detect.type` is `fax`.") +model DetectFaxParams { + @doc("The fax tone to detect. Omitted means either tone matches.") + @example(DetectFaxTone.CNG) + tone?: DetectFaxTone; +} + +@doc("DTMF-digit detection parameters. Applies only when `detect.type` is `digit`.") +model DetectDigitParams { + @doc("Set of DTMF digits to match. Allowed: `0-9`, `A-D` (case insensitive), `*`, `#`. Empty string matches any digit.") @example("0123456789#*") digits?: string; } -@doc("Detection configuration specifying what to detect and how.") +@doc("Detection configuration. The shape of `params` depends on `type`.") +@discriminator("type") model DetectConfig { @doc("The type of detection to perform.") @example(DetectType.machine) type: DetectType; +} + +@doc("Answering-machine detection configuration.") +model DetectMachineConfig extends DetectConfig { + type: DetectType.machine; + + @doc("Machine-detection parameters.") + @example(#{ initial_timeout: 4.5, end_silence_timeout: 1.0 }) + params?: DetectMachineParams; +} - @doc("Type-specific detection parameters.") - @example(#{ initial_timeout: 5, end_silence_timeout: 3 }) - params?: DetectParams; +@doc("Fax-tone detection configuration.") +model DetectFaxConfig extends DetectConfig { + type: DetectType.fax; + + @doc("Fax-detection parameters.") + @example(#{ tone: DetectFaxTone.CNG }) + params?: DetectFaxParams; +} + +@doc("DTMF-digit detection configuration.") +model DetectDigitConfig extends DetectConfig { + type: DetectType.digit; + + @doc("Digit-detection parameters.") + @example(#{ digits: "0123456789#*" }) + params?: DetectDigitParams; } +/** + * Start detection (answering machine, fax tone, or DTMF digits) on an active call. + * + * Detection runs asynchronously up to `timeout` seconds. Results are delivered + * via the `status_url` webhook. + */ @summary("calling.detect") model CallDetectRequest { @doc(uuidDescription) @@ -1021,17 +1370,26 @@ model CallDetectRequest { @doc(paramsDescription) params: { - @doc("Unique identifier for this detect operation, used to control it later.") + @doc("Unique identifier for this detect operation, used to control it later. Must be unique per active detect on this call.") @example("detect-control-1") - control_id?: string; + control_id: string; @doc("Detection configuration specifying what to detect.") @example(#{ type: DetectType.machine }) - detect: DetectConfig; + detect: DetectMachineConfig | DetectFaxConfig | DetectDigitConfig; - @doc("Maximum time in seconds to run the detection.") + @doc("Maximum time in seconds the detection may run before timing out.") @example(30) - timeout?: float64; + @minValue(0) + timeout?: float64 = 30; + + @doc("HTTP or HTTPS URL that receives detection result webhooks.") + @example("https://example.com/detect_callback") + status_url?: url; + + @doc("If `true`, the HTTP response returns immediately without waiting for the detect to be set up.") + @example(false) + async?: boolean = false; }; } @@ -1050,6 +1408,10 @@ model CallDetectStopRequest { @doc("The control ID of the detect operation to stop.") @example("detect-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stop to take effect.") + @example(false) + async?: boolean = false; }; } @@ -1066,59 +1428,111 @@ enum TapDeviceType { ws, } -@doc("Tap configuration specifying what audio to capture.") +@doc("RTP/WebSocket audio codec. Case-sensitive; accepted in both upper and lower case.") +enum TapCodec { + PCMA: "PCMA", + PCMU: "PCMU", + pcma: "pcma", + pcmu: "pcmu", + OPUS: "OPUS", + opus: "opus", +} + +@doc("RTP packetization time in milliseconds. Must be a multiple of 10 between 10 and 120.") +enum TapPtime { + `10`: 10, + `20`: 20, + `30`: 30, + `40`: 40, + `50`: 50, + `60`: 60, + `70`: 70, + `80`: 80, + `90`: 90, + `100`: 100, + `110`: 110, + `120`: 120, +} + +@doc("Tap configuration — specifies what audio to capture.") model TapConfig { - @doc("The type of media to tap. Currently only 'audio' is supported.") + @doc("Currently only `audio` is supported.") @example("audio") type: "audio"; - @doc("Tap parameters including audio direction.") + @doc("Audio tap parameters.") @example(#{ direction: PlayDirection.both }) - params?: { + params: { @doc("The direction of audio to tap.") @example(PlayDirection.both) - direction?: PlayDirection; + direction: PlayDirection; }; } -@doc("Parameters for the tap device connection.") -model TapDeviceParams { - @doc("The IP address or hostname of the device (RTP).") - @example("192.168.1.100") - addr?: string; +@doc("RTP tap target parameters.") +model TapRtpParams { + @doc("Public IPv4 address of the RTP target. Private/reserved ranges are rejected.") + @example("198.51.100.42") + addr: string; - @doc("The port number of the device (RTP).") + @doc("UDP port of the RTP target (1-65535).") @example(5060) - port?: int32; + @minValue(1) + @maxValue(65535) + port: int32; - @doc("The audio codec to use.") - @example("PCMU") - codec?: string; + @doc("Audio codec to request. Defaults to the call's negotiated codec.") + @example(TapCodec.PCMU) + codec?: TapCodec; - @doc("The packetization time in milliseconds.") - @example(20) - ptime?: int32; + @doc("Packetization time in milliseconds. Defaults to the call's negotiated ptime.") + @example(TapPtime.`20`) + ptime?: TapPtime; +} - @doc("The WebSocket URI to stream audio to (WS).") +@doc("WebSocket tap target parameters.") +model TapWsParams { + @doc("WebSocket URI of the tap target. Must start with `ws://` or `wss://`.") @example("wss://example.com/tap") - uri?: string; + uri: string; - @doc("The audio sample rate in Hz.") - @example(8000) - rate?: int32; + @doc("Audio codec to request. Defaults to the call's negotiated codec.") + @example(TapCodec.PCMU) + codec?: TapCodec; } -@doc("Tap device configuration specifying where to stream captured audio.") +@doc("Tap device configuration — specifies where to stream captured audio.") +@discriminator("type") model TapDevice { @doc("The type of tap device.") @example(TapDeviceType.rtp) type: TapDeviceType; +} - @doc("Device-specific connection parameters.") - @example(#{ addr: "192.168.1.100", port: 5060 }) - params?: TapDeviceParams; +@doc("RTP tap device configuration.") +model TapDeviceRtp extends TapDevice { + type: TapDeviceType.rtp; + + @doc("RTP connection parameters.") + @example(#{ addr: "198.51.100.42", port: 5060 }) + params: TapRtpParams; } +@doc("WebSocket tap device configuration.") +model TapDeviceWs extends TapDevice { + type: TapDeviceType.ws; + + @doc("WebSocket connection parameters.") + @example(#{ uri: "wss://example.com/tap" }) + params: TapWsParams; +} + +/** + * Capture audio from an active call and stream it to an external destination. + * + * Audio is streamed via RTP (to a public IP/port) or WebSocket (to a `ws://`/`wss://` URI). + * Stop the tap with `calling.tap.stop` using the same `control_id`. + */ @summary("calling.tap") model CallTapRequest { @doc(uuidDescription) @@ -1131,17 +1545,25 @@ model CallTapRequest { @doc(paramsDescription) params: { - @doc("Unique identifier for this tap operation, used to control it later.") + @doc("Unique identifier for this tap operation, used to control it later. Must be unique per active tap on this call.") @example("tap-control-1") - control_id?: string; + control_id: string; @doc("Tap configuration specifying what audio to capture.") @example(#{ type: "audio", params: #{ direction: PlayDirection.both } }) tap: TapConfig; @doc("Device configuration specifying where to stream captured audio.") - @example(#{ type: TapDeviceType.rtp, params: #{ addr: "192.168.1.100", port: 5060 } }) - device: TapDevice; + @example(#{ type: TapDeviceType.rtp, params: #{ addr: "198.51.100.42", port: 5060 } }) + device: TapDeviceRtp | TapDeviceWs; + + @doc("HTTP or HTTPS URL that receives tap lifecycle webhooks.") + @example("https://example.com/tap_callback") + status_url?: url; + + @doc("If `true`, the HTTP response returns immediately without waiting for the tap to be set up.") + @example(false) + async?: boolean = false; }; } @@ -1160,6 +1582,10 @@ model CallTapStopRequest { @doc("The control ID of the tap operation to stop.") @example("tap-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stop to take effect.") + @example(false) + async?: boolean = false; }; } @@ -1179,6 +1605,20 @@ enum StreamTrack { both_tracks, } +@doc("HTTP method used when invoking the `status_url` webhook.") +enum StreamStatusUrlMethod { + GET, + POST, +} + +/** + * Stream call audio to an external WebSocket endpoint. + * + * Audio is sent to a `wss://` URL; `custom_parameters` pass through to the + * endpoint as connection metadata. Stream lifecycle webhooks are delivered to + * `status_url` (default method `POST`). Stop the stream with + * `calling.stream.stop` using the same `control_id`. + */ @summary("calling.stream") model CallStreamRequest { @doc(uuidDescription) @@ -1191,30 +1631,46 @@ model CallStreamRequest { @doc(paramsDescription) params: { - @doc("Unique identifier for this stream operation, used to control it later.") + @doc("Unique identifier for this stream operation, used to control it later. Must be unique per active stream on this call.") @example("stream-control-1") - control_id?: string; + control_id: string; - @doc("The WebSocket URL to stream audio to.") + @doc("WebSocket URL to stream audio to. Must start with `wss://` (TLS is required; plain `ws://` is rejected).") @example("wss://example.com/stream") @format("uri") url: string; - @doc("The audio codec to use for streaming.") + @doc("Optional human-readable name to identify the stream at the endpoint.") + @example("customer-support-recording") + name?: string; + + @doc("Audio codec to request. Freeform; endpoint-specific. Common values include `PCMU`, `PCMA`, `OPUS`.") @example("PCMU") codec?: string; @doc("The audio track to stream.") - @example(StreamTrack.both_tracks) - track?: StreamTrack; + @example(StreamTrack.inbound_track) + track?: StreamTrack = StreamTrack.inbound_track; - @doc("Bearer token for WebSocket authentication.") + @doc("Bearer token included as `Authorization: Bearer ` when establishing the WebSocket connection.") @example("my-secret-token") authorization_bearer_token?: string; - @doc("Custom parameters to include in the WebSocket connection.") + @doc("Arbitrary JSON object passed through to the WebSocket endpoint as connection metadata.") @example(#{ session_id: "abc123" }) custom_parameters?: TypeSpec.Record; + + @doc("HTTP or HTTPS URL that receives stream lifecycle webhooks.") + @example("https://example.com/stream_callback") + status_url?: url; + + @doc("HTTP method used for the `status_url` webhook.") + @example(StreamStatusUrlMethod.POST) + status_url_method?: StreamStatusUrlMethod = StreamStatusUrlMethod.POST; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stream to be set up.") + @example(false) + async?: boolean = false; }; } @@ -1233,6 +1689,10 @@ model CallStreamStopRequest { @doc("The control ID of the stream operation to stop.") @example("stream-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stop to take effect.") + @example(false) + async?: boolean = false; }; } @@ -1240,6 +1700,11 @@ model CallStreamStopRequest { // Denoise Commands // ============================================ +/** + * Enable noise reduction on an active call. Denoise is per-call (no + * `control_id`); a call has at most one active denoise filter. Use + * `calling.denoise.stop` to disable it. + */ @summary("calling.denoise") model CallDenoiseRequest { @doc(uuidDescription) @@ -1251,7 +1716,11 @@ model CallDenoiseRequest { command: "calling.denoise"; @doc(paramsDescription) - params: {}; + params: { + @doc("If `true`, the HTTP response returns immediately without waiting for the filter to be set up.") + @example(false) + async?: boolean = false; + }; } @summary("calling.denoise.stop") @@ -1265,7 +1734,11 @@ model CallDenoiseStopRequest { command: "calling.denoise.stop"; @doc(paramsDescription) - params: {}; + params: { + @doc("If `true`, the HTTP response returns immediately without waiting for the filter to be torn down.") + @example(false) + async?: boolean = false; + }; } // ============================================ @@ -1287,6 +1760,10 @@ model CallAIStopRequest { @doc("The control ID of the AI session to stop.") @example("ai-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stop to take effect.") + @example(false) + async?: boolean = false; }; } @@ -1309,6 +1786,10 @@ model CallSendFaxStopRequest { @doc("The control ID of the fax send operation to stop.") @example("fax-send-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stop to take effect.") + @example(false) + async?: boolean = false; }; } @@ -1327,6 +1808,10 @@ model CallReceiveFaxStopRequest { @doc("The control ID of the fax receive operation to stop.") @example("fax-receive-control-1") control_id: string; + + @doc("If `true`, the HTTP response returns immediately without waiting for the stop to take effect.") + @example(false) + async?: boolean = false; }; } @@ -1336,10 +1821,14 @@ model CallReceiveFaxStopRequest { @doc("SIP REFER device parameters.") model ReferSipParams { - @doc("The SIP URI to refer the call to.") + @doc("SIP URI to refer the call to (must start with `sip:`).") @example("sip:destination@example.com") to: string; + @doc("Optional SIP From URI (must start with `sip:` when provided).") + @example("sip:operator@example.com") + from?: string; + @doc("Optional SIP authentication username.") @example("user") username?: string; @@ -1376,9 +1865,13 @@ model CallReferRequest { @example(#{ type: "sip", params: #{ to: "sip:destination@example.com" } }) device: ReferDevice; - @doc("A URL to receive status update callbacks for the refer operation.") + @doc("HTTP or HTTPS URL that receives refer lifecycle webhooks.") @example("https://example.com/status_callback") status_url?: url; + + @doc("If `true`, the HTTP response returns immediately without waiting for the refer to be sent.") + @example(false) + async?: boolean = false; }; } @@ -1398,9 +1891,13 @@ model CallTransferRequest { @doc(paramsDescription) params: { - @doc("The destination to transfer the call to. Can be a SIP URI, phone number, or an inline SWML object.") + @doc("The destination to transfer the call to. Can be a SIP URI, phone number, SWML URL, or an inline SWML object.") @example("sip:destination@example.com") dest: string | SWMLObject; + + @doc("If `true`, the HTTP response returns immediately without waiting for the transfer to complete.") + @example(false) + async?: boolean = false; }; } @@ -1419,6 +1916,10 @@ model CallUserEventRequest { @doc("Arbitrary JSON event data to fire on the call.") @example(#{ action: "custom_action", data: "example" }) event: TypeSpec.Record; + + @doc("If `true`, the HTTP response returns immediately without waiting for the event to fire.") + @example(false) + async?: boolean = false; }; }