Reviewers (PMD-3932):

User Story

As a Communication Service Provider, I want PortaSwitch to connect calls to AI and call protection services that support only WebSocket (not SIP) by sending the live call audio to the service and playing the service’s audio into the call, so that my business customers can use the service they choose on the phone lines they have with me, and don’t move those lines to a provider that supports these services.


Example of Use

Example 1. Nordwind Logistics GmbH, receives about 40 calls each day on 4930555010, and most callers ask only where their parcel is. Each call occupies an employee for about 3 minutes. Nordwind selected an AI agent service that answers this question, but the service supports WebSocket and has no SIP interface, so their CSP, Rheinmark, who owns PortaSwitch, cannot deliver a call to it. With this feature, a caller types parcel number 7741203, the AI agent answers that the parcel is in Hamburg and arrives on Thursday, and the call takes 19 seconds and occupies no employee.

Example 2. About 1 delivery in 10 fails because nobody is at home, and each failure costs Nordwind a second journey. Nordwind wants the same AI agent service to call each recipient the day before. With this feature, the AI agent calls the recipient of parcel 7741203, confirms the window of nine to eleven, and the call takes 37 seconds.

Example 3. When an employee answers a call, the same service listens to the caller and to the employee separately and shows the answer on the employee’s screen.

Example 4. A subscriber receives a call from a person who says he calls from the subscriber’s bank. After 4 minutes, the caller asks for the card number. A call protection service warns only the subscriber, and ends the call when the subscriber starts to read the number. The caller never hears the warning. The subscriber keeps the number, the handset and the service.


Business Model

  • Problem to solve: PortaSwitch can deliver a call to an AI platform over SIP. Most AI agent services support only WebSocket, and PortaSwitch cannot deliver a call to them at all.
  • Money flow: Rheinmark resells the service that the customer selects, and pays the supplier for each minute of audio. Rheinmark charges the customer with the existing charging functions of PortaBilling. This document adds no charging function. The xDR of each call shows the use of the stream, so Rheinmark can compare its revenue with the supplier invoice.
  • Example of a price model: 25.00 EUR each month for each phone line that uses an AI agent service. Nordwind uses 7 such lines, so the monthly revenue is 7 × 25.00 = 175.00 EUR.
  • Value at risk: Nordwind pays Rheinmark for 7 phone lines and moves them to a competitor.

Technology

  • New integration. The audio of a call passes between PortaSwitch and an AI agent service over a WebSocket connection, protected with TLS. The service has an address, for example wss://api.voiceagents.example/v1/agents/parcel-status.
  • PortaSwitch sends the following to the service:
    • The data that identifies the call: the calling number, the called number, the original called number (after a forward or a hunt group), the display name of the caller, the call direction, the customer, the extension, the audio format, the identifier that the Call Control API uses for the call, a token that is valid only for this call, and the parameters of the line.
    • The audio of each party, separately, with the party identified. The audio is continuous and includes the periods of silence.
    • The events of the call: the keys the caller presses, hold, unhold, and a party that joins or leaves.
    • A confirmation when audio that the service sent has been played. When the service drops its audio, PortaSwitch tells it how much of that audio was played.
    • When the stream stops, the reason: the call ended, was transferred, was put on hold, an error occurred, or an application stopped the stream.
  • The service sends the following to PortaSwitch:
    • Audio, to all parties or to one party.
    • A request to drop the audio that PortaSwitch has received but not yet played.
    • A request to confirm when the audio sent before a named point has been played.
  • An application can start a stream on one call, with its own parameters, and stop it, with the Call Control API.
  • The service can act on its own call with the Call Control API (transfer, end), with the call token, without the credentials of the customer. With the same token, the service can also start a new call from the same line, and join that call with its own call.
  • Audio formats: G.711 A-law and G.711 µ-law at 8 kHz, and 16-bit linear audio at 16 kHz for wideband calls.
  • Message format: the stream uses the format that the main AI voice platforms already accept (the Twilio Media Streams format), so these platforms work without an adapter on either side.

Current Solution

  • Static SIP contact with TLS delivers the calls of a phone line to an external platform over SIP. An AI agent service that supports only WebSocket cannot receive a call this way.
  • The Call Control API is available over WebSocket. An application can answer, redirect, transfer, end and list calls, and can subscribe to call state notifications. The API carries no audio. It cannot give the audio of a call to an external service, and it cannot put audio into a call.
  • The record function writes the audio to a file and converts it after the call ends. Nothing can use the audio while the call continues.

Stakeholders and Their Benefits

StakeholderBenefit
CSPRe-sells the AI agent of any supplier that supports WebSocket, keeps the numbers, and sees the use of each stream in the xDR
Enterprise customerSelects its AI supplier from the whole market, and keeps its extensions and one invoice
Employee of the customer
  • Gets an answer or a fraud warning during the call, without leaving the call
  • Is warned during a scam call, and keeps the number, the handset and the service
AI agent service supplierReaches the customers of the CSP without building a SIP and RTP stack
End callerIs answered at once, and reaches a person when the AI agent is not available


Use Cases

Use Case #1 — PortaSwitch streams the media of a call to a WebSocket service

Roles: Administrator (Rheinmark), End caller, Employee of Nordwind, Application of Nordwind, AI agent service.

Preconditions:

  • Customer "Nordwind Logistics GmbH", status open
  • Phone line 4930555010: inbound number for parcel questions.
  • Phone line 4930555011: outbound number for delivery notices.
  • Phone line 4930555012: inbound number answered by employee Jana Becker (extension 102).
  • Hunt group “Nordwind Dispatch” (extension 200), with Jana Becker as a member.
  • The AI agent service that Nordwind selected is available at wss://api.voiceagents.example, with a valid TLS certificate. It supports WebSocket and has no SIP interface
  • The service holds a parcel-status agent at the path /v1/agents/parcel-status, a delivery-notice agent at the path /v1/agents/delivery-notice, and a call assistant at /v1/agents/agent-assist
  • The audio of the calls of Nordwind goes through PortaSwitch, and PortaSwitch can read it. The codec is G.711 A-law.

Use Scenario #1.1 — A caller asks about a parcel

  • On 2026-09-07 09:00:00, the Administrator sets the stream of line 4930555010:
  • On 2026-09-07 10:05:00, an end caller at 4915199988877 calls 4930555010.
  • The service accepts the stream. PortaSwitch answers the call at 10:05:01.
  • The service receives the calling number 4915199988877, the called number 4930555010, the direction inbound, the customer Nordwind Logistics GmbH, the parameters language = de and agent = parcel-status, the audio format G.711 A-law, the call identifier, and the call token.
  • The service receives the audio of the caller, identified as the caller, continuously, including the periods of silence.
  • The AI agent says “Nordwind Logistics. Please say or type your parcel number.” The caller hears it.
  • From 10:05:06 to 10:05:09, the caller types 7 7 4 1 2 0 3 on the keypad. The service receives the 7 digits.
  • The AI agent says “Parcel 7741203 is in Hamburg and arrives on Thursday. Goodbye.”
  • At 10:05:19, the service receives the confirmation that the caller has heard the complete sentence.
  • At 10:05:19, the service ends the call with the call token. The stream stops.
  • The xDR of the call shows: stream used yes, stream duration 00:00:18, address wss://api.voiceagents.example/v1/agents/parcel-status, end reason service ended the call.

Use Scenario #1.2 — Continues #1.1: the caller interrupts the AI agent

State carried forward: Line 4930555010 has the stream settings from #1.1.

  • On 2026-09-07 11:20:00, an end caller at 4915199988877 makes a call to 4930555010. PortaSwitch answers at 11:20:01
  • From 11:20:30 the AI agent says "Your parcel is in Hamburg and arrives on Thursday." The sentence is 9000 ms long. By 11:20:31, the service has sent all of the sentence to PortaSwitch.
  • At 11:20:33 the caller starts to speak. The caller has heard only "Your parcel is in Ham"
  • At 11:20:33, the service tells PortaSwitch to drop the audio that is not yet played.
  • PortaSwitch tells the service that the caller heard 3000 ms of the sentence.
  • The caller hears no more of the AI agent. The caller hears their own words without the AI agent over them
  • The service knows that the caller heard only up to “Ham” and not the delivery date, and says the delivery date again.

Use Scenario #1.3 — Continues #1.2: the AI agent makes an outbound call

New in this scenario: On 2026-09-08 09:00:00, the Administrator sets the stream of line 4930555011: address wss://api.voiceagents.example/v1/agents/delivery-notice, direction outbound, parameter agent = delivery-notice. The service knows that parcel 7741203 belongs to the recipient at 4915199988877.

  • On 2026-09-08 09:15:00, the application of Nordwind starts a call from 4930555011 to the recipient at 4915199988877, to confirm the delivery window. The recipient answers at 09:15:08.
  • The delivery-notice agent receives the calling number 4930555011, the called number 4915199988877, the direction outbound, the parameter agent = delivery-notice, the audio format, the call identifier, and the call token
  • The AI agent says "This is Nordwind Logistics. Your parcel 7741203 arrives tomorrow between nine and eleven. Is that convenient?" The recipient hears it
  • The recipient says "Yes, that is fine."
  • The AI agent says "Thank you. We will deliver tomorrow between nine and eleven."
  • At 09:15:45 the recipient ends the call. The stream stops
  • An inbound call to 4930555011 on the same day starts no stream, because the direction is outbound.

Use Scenario #1.4 — Error alternative to #1.1: the service is not available

State carried forward: Line 4930555010 has the stream settings from #1.1.

New in this scenario: The service is out of operation and does not accept any stream

  • On 2026-09-09 11:10:00, an end caller at 4915177766655 calls 4930555010.
  • The service does not accept the stream. No stream starts.
  • At 11:10:03, PortaSwitch forwards the call to hunt group “Nordwind Dispatch” (extension 200). The caller hears the ring tone.
  • At 11:10:09, Jana Becker answers. The call continues without a stream.
  • The xDR of the call shows: stream used no, end reason connection failed.

Use Scenario #1.5 — Error alternative to #1.1: the connection drops during the call

State carried forward: Line 4930555010 has the stream settings from #1.1. The service is in operation again.

  • On 2026-09-09 13:02:00, an end caller at 4915199988877 calls 4930555010. PortaSwitch answers at 13:02:01.
  • At 13:02:20, while the AI agent speaks, the connection to the service drops.
  • At 13:02:20, PortaSwitch forwards the call to hunt group “Nordwind Dispatch”. The caller hears the ring tone.
  • At 13:02:27, Jana Becker answers. The call continues without a stream.
  • The xDR of the call shows: stream used yes, stream duration 00:00:19, end reason connection dropped.

Use Scenario #1.6 — An employee answers, and the service listens and helps

New in this scenario: On 2026-09-10 09:00:00, the Administrator sets the stream of line 4930555012: address wss://api.voiceagents.example/v1/agents/agent-assist, direction inbound, PortaSwitch answers the call no, if the service is not available continue the call without the stream.

  • On 2026-09-10 14:20:00, an end caller at 4915177766655 calls 4930555012. Jana Becker answers at 14:20:04.
  • The service receives the calling number 4915177766655, the called number 4930555012, the direction inbound, the extension 102, the audio format, the call identifier, and the call token.
  • The service receives the audio of the caller and the audio of Jana Becker separately, and knows which audio is from which party.
  • At 14:21:10 the caller asks for the customs code of parcel 7741203. Jana Becker does not know it.
  • The service shows the answer to Jana Becker in the CRM. At 14:21:14, she says "The customs code is 4202 92."
  • From 14:22:00 to 14:22:30, Jana Becker puts the caller on hold. The service receives hold and unhold, and receives no music on hold.
  • The service sends no audio at any time
  • At 14:23:34 the caller ends the call. The stream stops.

Use Scenario #1.7 — The service warns only the employee

State carried forward: Line 4930555012 has the stream settings from #1.6.

  • On 2026-09-10 15:00:00, an end caller at 4917612345678 calls 4930555012. Jana Becker answers at 15:00:03.
  • At 15:00:40, the caller says “Pay 9,800 euros to our new bank account today.”
  • At 15:00:45, the service sends “Warning: this can be payment fraud. Do not pay before you check the request.” to Jana Becker only.
  • Jana Becker hears the warning. The caller does not hear it.
  • At 15:01:30, Jana Becker ends the call. The stream stops.
  • The recording of the call contains the caller, Jana Becker, and the warning.

Use Scenario #1.8 — The AI agent transfers the caller to an employee

State carried forward: Line 4930555010 has the stream settings from #1.1.

  • On 2026-09-11 10:00:00, an end caller at 4915199988877 calls 4930555010. PortaSwitch answers at 10:00:01.
  • At 10:00:15, the caller says “I want to speak to a person.”
  • The AI agent says “I will connect you now.” At 10:00:18, the service receives the confirmation that the caller has heard it.
  • At 10:00:18, the service transfers the call to extension 102 with the call token. The stream stops.
  • The caller hears the ring tone. Jana Becker answers at 10:00:24.
  • The xDR of the call shows: stream used yes, stream duration 00:00:17, end reason call transferred

Use Scenario #1.9 — Continues #1.8: the application starts and stops a stream on one call

State carried forward: In #1.8, the AI agent transferred the call from 4915199988877 to extension 102, and Jana Becker answered at 10:00:24. The stream of line 4930555010 stopped at the transfer. The stream settings of line 4930555012 (#1.6) apply only to calls to 4930555012, so the transferred call has no stream.

New in this scenario: The application of Nordwind uses the Call Control API and receives the call state notifications of Nordwind.

  • At 10:00:24, the application receives the notification that Jana Becker answered the transferred call.
  • At 10:00:25, the application starts a stream on this call with the Call Control API:
  • The service receives the calling number 4915199988877, the called number 4930555010, the direction inbound, the extension 102, the parameters parcel = 7741203 and source = parcel-status, the audio format, the call identifier, and the call token.
  • The service receives the audio of the caller and the audio of Jana Becker separately, and knows which audio is from which party.
  • At 10:00:27, the service shows the status of parcel 7741203 to Jana Becker in the CRM. The caller does not repeat the parcel number.
  • At 10:01:40, the caller asks if the parcel can go to a parcel locker. The service shows the nearest locker, Packstation 128, to Jana Becker in the CRM, and she tells the caller.
  • At 10:03:00, the application stops the stream with the Call Control API. The service receives the stop, with the reason stopped by the application.
  • The call continues. Jana Becker and the caller hear no click, no gap, and no change of the sound level.
  • At 10:04:10, the caller ends the call.
  • The xDR of the call shows two streams:

Use Case #2 — A protection service listens to all calls of a subscriber

Roles: Administrator (Rheinmark), Subscriber, End caller, Call protection service.

Preconditions:

  • Rheinmark sells a call protection service to its private subscribers as an add-on.
  • Subscriber Helga Wagner, account 4917055501010, has the add-on.
  • The call protection service is available at wss://api.callguard.example/v1/protect, with a valid TLS certificate.
  • The audio of Helga Wagner’s calls goes through PortaSwitch, and PortaSwitch can read it. The codec is G.722.

Use Scenario #2.1 — The service warns the subscriber about a scam and ends the call

  • On 2026-09-12 09:00:00, the Administrator sets a stream for all calls of account 4917055501010:
  • On 2026-09-12 18:00:00, an end caller at 4915700900123 calls 4917055501010. Helga Wagner answers at 18:00:05.
  • The service receives the calling number 4915700900123, the called number 4917055501010, the direction inbound, the account, the flag number not hidden, the audio format 16 kHz linear audio, the call identifier, and the call token.
  • The service receives the audio of the caller and the audio of Helga Wagner separately, and knows which audio is from which party.
  • At 18:00:20, the caller says that he calls from Helga Wagner’s bank.
  • At 18:04:10, the caller asks Helga Wagner to read out her card number.
  • At 18:04:12, the service sends “This call shows signs of a scam. Do not share your card details.” to Helga Wagner only.
  • Helga Wagner hears the warning. The caller does not hear it.
  • At 18:04:30, Helga Wagner starts to read out the card number.
  • At 18:04:31, the service ends the call with the call token. The caller does not receive the complete card number. The stream stops.
  • The xDR of the call shows: stream used yes, stream duration 00:04:26, address wss://api.callguard.example/v1/protect, end reason service ended the call.

Use Scenario #2.2 — Error alternative to #2.1: the service is not available, and the call is not affected

State carried forward: Account 4917055501010 has the stream settings from #2.1.

New in this scenario: The service is out of operation and does not accept any stream.

  • On 2026-09-13 18:30:00, an end caller at 4915700900123 calls 4917055501010. The phone of Helga Wagner rings at once, as without the add-on.
  • Helga Wagner answers at 18:30:04.
  • The service does not accept the stream. No stream starts.
  • Helga Wagner and the caller hear no delay, no click and no announcement. The call continues as a normal call.
  • At 18:35:00, Helga Wagner ends the call.
  • The xDR of the call shows: stream used no, end reason connection failed.

Wireframes

  • Media stream settings of a phone line, of an account, and of a customer for all its extensions: address, direction (inbound, outbound, both), internal calls (yes/no), PortaSwitch answers the call (yes/no), action if the service is not available (continue the call, forward to a number, extension or hunt group, play an announcement), send hidden numbers to the service (yes/no), audio format (as the call, or a fixed format), and parameters (name and value).
  • The Admin UI and the CloudPBX portal are nice to have. It is acceptable to set the stream through the API only.

Non-Functional Requirements

  • The parties hear no click, no gap and no change of the sound level when the stream starts, when it stops, and when the audio of the service starts and stops.
  • The audio of the service stops within 200 ms after the service requests PortaSwitch to drop it.
  • The audio and the call data are protected with TLS 1.2 or a later version. PortaSwitch refuses a service address without TLS when the address is saved.
  • When the service does not accept the stream, the caller reaches the action for “service not available” no later than 3 seconds after the call arrives (#1.4). The time limit can be changed for each line.
  • PortaSwitch proves its identity to the service at each connection.
  • The call token is valid only for its own call, and for the calls that the service starts with it from the same line. The token expires when its own call ends.
  • When the action for “service not available” is “continue the call”, a failure of the service causes no delay of the call and no sound the parties can hear (#2.2).

Peculiarities

Assumptions:

  • The stream starts when the call is answered, or when an application starts it. It stops when the call ends, when the call leaves the streamed line, or when an application stops it.
  • When “Auto answer” is set, PortaSwitch answers only after the service accepts the stream. Otherwise, a person, a PBX feature, or an application with the Call Control API answers the call as it does today.
  • The service detects the speech of the caller on its own by implementing Voice Activity Detection (VAD). Each AI provider has its own method.
  • How the service shows information to a person outside the call is the business of the service and of the customer. This document covers only the audio.
  • The customer decides whether to tell callers that an AI agent takes part in the call.

Edge Cases:

  • Encrypted audio. PortaSwitch cannot use the media functions of a call if it only relays the encrypted audio.
  • Audio path. The audio must go through PortaSwitch, as for the call recording function.
  • Format conversion. The AI provider can require another format, for example PCM at 24 kHz, and PortaSwitch sends G.711 A-law or µ-law at 8 kHz, or linear audio at 16 kHz. The service converts the audio.
  • Recording: the recording contains the audio of the parties and the audio of the service in one file (#1.7).
  • Hold: the service receives no music on hold (#1.6).
  • Forward or hunt group: the service receives the original called number as well as the number that answers.
  • Transfer by an employee: when a call leaves a streamed line, its stream stops. When a call arrives at a streamed line, a new stream starts for that line.
  • Conference: the service receives the audio of each party in the conference separately.
  • Internal calls: a stream starts for an internal call only when the line setting allows internal calls.
  • Hidden number: the service always receives a flag that shows whether the caller hides the number. The service receives the number itself only when the line setting allows it.
  • Stream limit: when the installation has the maximum number of streams, PortaSwitch applies the action for “service not available” to a new stream. The call does not fail. The xDR shows the end reason capacity.
  • Capacity: CSPs expect a few hundreds of concurrent calls handled by AI agents after launch

Open Questions:

  • How many streams must one installation support at the same time?

Out of Scope:

  • The delivery of a call to an AI platform that supports SIP. Static SIP contact with TLS does this today
  • How an application starts an outbound call. The application uses the existing Call Control API.
  • The logic of the AI agent service, and speech detection in PortaSwitch
  • More than one service on one call at the same time
  • A stream on the second call of a warm transfer (the call to the employee before the parties are joined). The call token already allows the second call and the join, so a later phase can add the stream without a change to the token.
  • How the CSP packages and charges for the stream. The xDR gives the data.
  • An adapter in PortaSwitch for the protocol of one AI provider

Solution Considerations

All items are proposals for the Solution Design team to confirm or reject.

1. Message format (supports: Technology)

  • Use the Twilio Media Streams format: connected → start (metadata) → media (base64, 20 ms) ↔ media / mark / clear → stop, plus dtmf. Many AI agent services already accept this format, so no provider-specific adapter is necessary.
  • To verify: test with 2 or 3 services that they accept a connection that does not come from Twilio. Some services can check a Twilio handshake or signature.
  • One CSP offers to test a test build against ElevenLabs Conversational AI and at least one other platform, including the handshake and signature checks.

2. Audio of each party (supports: #1.6, #1.2)

  • Add track: caller|callee to each media message, or use 2-channel audio. The media proxy already records each side separately (start_recording_media with side).
  • Offer one mixed track as an option.

3. Audio to one party (supports: #1.7)

  • Add an optional track: caller|callee|both to the service’s media message. In the media proxy, this maps to join_conference with relayed_to, or to start_playing_prompt for each side.

4. Drop the audio not yet played (supports: #1.2, NFR 200 ms)

  • A clear message empties the playout buffer at once. This is necessary because services send text-to-speech faster than real time, so PortaSwitch must buffer the audio. On clear, PortaSwitch returns all pending marks at once (as Twilio does), and/or the number of milliseconds played, so the service knows what the caller heard.

5. Playback confirmation (supports: #1.1, #1.8)

  • The service sends mark {name}, and PortaSwitch sends it back when the audio before that mark has been played. The service then knows when it can hang up or transfer, and how much of a sentence the caller heard (for example, to truncate the conversation history of the language model).

6. Call token (supports: #1.1, #1.8, NFR call token)

  • Put a token in start that allows transfer_call and terminate_call for this call, originate_call from the same line, and join_calls between this call and the calls that the service originated with the token. The token expires when the call ends.

7. Call data (supports: Technology, #1.1, #1.6)

  • Add i_customer, i_account or account ID, extension, the original called number or Diversion header, the display name, a privacy/CLIR flag in every start (the number only when the line setting allows it), and free key/value custom_parameters for each line configuration. This works like Twilio <Parameter>.

8. Configuration (supports: Wireframes, #1.3)

  • Add direction (inbound|outbound|both), internal calls (yes/no) and parameters to the stream configuration. Allow it for each account and for each customer, for example through a service policy.

9. Answering (supports: #1.1)

  • answer_mode: auto: PortaSwitch answers as soon as the WebSocket is connected and start is acknowledged. No separate Call Control application is necessary for the simple case.

10. Failure handling (supports: #1.4, #1.5, NFR 3 seconds)

  • Use a WebSocket connect timeout of 2–3 seconds by default, with a configurable on_failure action: continue without the stream, forward to a number, voicemail or hunt group, or play an announcement.
  • The same action applies when the connection drops during the call.
  • Optional health checks of the service (for example, OPTIONS probing) let calls take the normal path at once when the service is down.

11. Audio format (supports: Technology)

  • Negotiate PCMA or PCMU at 8 kHz, or L16 at 16 kHz, in start. G.722 to L16 16 kHz gives better speech recognition.
  • The endpoint configuration can fix the audio format, for example “always L16 16 kHz”. PortaSwitch then converts the audio of each leg to that format. Without a fixed format, PortaSwitch uses the format from the negotiation in start.

12. Audio injection (supports: NFR “no click, no gap”)

  • Insert the service audio into the existing audio stream of each leg, so that the receiver sees one continuous stream (same RTP SSRC, continuous sequence numbers and timestamps). When the service audio was sent as a second stream, the callee heard no audio at all.
  • Resample to the codec of each leg. Mixed G.722/PCMA legs gave choppy, high-pitched audio.
  • Use pre-roll, and fill underruns with silence, to prevent clicks and gaps.
  • Add a sequence number or timestamp to each media message, so the service can detect gaps.

13. Events (supports: #1.1 keypad, #1.6 hold)

  • Send hold and unhold (and do not stream music on hold to the service), transfer, party joined or left, and DTMF. The media proxy already has start_dtmf_detection.

14. xDR (supports: Business Model, #1.1, #1.4, #1.5, #1.8)

  • Add: stream used (yes/no), stream duration, endpoint, and end reason (service closed, connect failure, WebSocket drop, call transferred, service ended the call, stopped by the application, capacity).

15. Authentication (supports: NFR identity, NFR call token)

  • PortaSwitch to service: a secret for each endpoint, sent as Authorization: Bearer on the WebSocket upgrade, and/or an HMAC signature over call_id and a timestamp (like X-Twilio-Signature). Always validate the certificate. mTLS is optional.
  • Service to PortaSwitch: the call token from item 6.
  • Allow a configurable header name and value for each endpoint, for services that use an API key header instead of Bearer.

16. Recording (supports: #1.7, Edge Case “Recording”)

  • Mix the service audio in before the recording point, for example by injecting it through the conference mixer of the media proxy. Then the existing recording contains both parties and the AI.

Performance / Clustering, Geo Redundancy/ Dual-Version, Porter / Call Control API / ESPF / Monitoring

The solution must be supported for the standalone mode and dual-version modes

PlantUML Diagram