Skip to main content

Telnyx-webrtc-ios

Enable Telnyx real-time communication services on iOS.

Project Structure

  • SDK project: Enable Telnyx WebRTC communications.
  • SDK Tests project.
  • Demo app project.

Project Setup:

  1. Clone the repository
  2. Run the command pod install to install the dependencies inside the project root folder.
  3. Open the Workspace : TelnyxRTC.xcworkspace
  4. Configure the Demo App (Optional):
    • The Config.xcconfig file is included in the repository with default values
    • To use the Pre-call Diagnosis feature, edit Config.xcconfig and set a valid phone number:
    • If you don’t need Pre-call Diagnosis, you can leave PHONE_NUMBER empty
  5. You will find 3 targets to build:
    • The SDK
    • The SDK Tests
    • The Demo App

Screen Shot 2021-05-04 at 18 34 45

  1. Select the target TelnyxRTC (TelnyxRTC Project) to build the SDK

Screen Shot 2021-05-04 at 18 35 18

  1. Select the target TelnyxRTCTests to run the tests. You will need to long press over the Run button and select Build for testing

Screen Shot 2021-03-03 at 10 04 05

  1. Select target TelnyxWebRTCDemo to run the demo app. The SDK should be manually built in order to get the app running (Step 5)

SIP Credentials

In order to start making and receiving calls using the TelnyxRTC SDK you will need to get SIP Credentials:
  1. Access to https://portal.telnyx.com/
  2. Sign up for a Telnyx Account.
  3. Create a Credential Connection to configure how you connect your calls.
  4. Create an Outbound Voice Profile to configure your outbound call settings and assign it to your Credential Connection.
For more information on how to generate SIP credentials check the Telnyx WebRTC quickstart guide.

Region Selection

The TelnyxRTC SDK supports connecting to different geographic regions to optimize call quality and reduce latency. The demo app includes a region selection feature that allows users to choose their preferred region.

Available Regions

  • Auto (Default): Automatically selects the best region based on network conditions
  • US East: East coast United States servers
  • US Central: Central United States servers
  • US West: West coast United States servers
  • Canada Central: Central Canada servers
  • Europe: European servers
  • Asia Pacific: Asia Pacific servers

Using Region Selection

  1. In the Demo App: Use the overflow menu (⋯) to access region selection. The current region is displayed as “Region: [current-region]”.
  2. In Your App: Configure the region when creating a TxServerConfiguration:

Region Selection Behavior

  • During Active Calls: Region selection is automatically disabled during active calls to prevent connection disruption
  • When Connected: Region selection is disabled when the client is connected to prevent disrupting the established connection
  • Fallback Logic: If a regional server is unavailable, the SDK automatically falls back to the auto region
  • Persistence: The selected region persists across app sessions until manually changed

Best Practices

  • Use Auto region for the best overall experience unless you have specific latency requirements
  • Select a region geographically close to your users for optimal call quality
  • Test different regions in your target deployment areas to determine the best performance

Adding Telnyx SDK to your iOS Client Application:

Currently the iOS SDK is supported using cocoapods.

Cocoapods

If your xcode project is not using cocoapods yet, you will need to configure it.
  1. Open your podfile and add the TelnyxRTC.
  1. Install your pods. You can add the flag —repo-update to ensure your cocoapods has the specs updated.
  1. Open your .xcworkspace
  2. Import TelnyxRTC at the top level of your class:
  1. Disable BITCODE (The GoogleWebRTC dependency has BITCODE disabled): Go to the Build Settings tab of your app target, search for “bitcode” and set it to “NO”

Screen Shot 2021-05-07 at 17 46 08

  1. Enable VoIP and Audio background modes: Go to Signing & Capabilities tab, press the +Capability button and add those background modes:

Screen Shot 2021-05-07 at 17 46 54

  1. Go to your Info.plist file and add the “Privacy - Microphone Usage Description” key with a description that your app requires microphone access in order to make VoIP calls.

Screen Shot 2021-05-07 at 17 48 17

  1. You are all set!

Swift Package Manager

Xcode has a built-in support for Swift package manager. To add a package :
  1. Select Files > Add Packages
  2. On the Swift Package Manager Screen, Search for the https://github.com/team-telnyx/telnyx-webrtc-ios.git package.
  3. Select the main brach and click Add Package

Screen Shot 2021-05-07 at 17 48 17

NB: if Add Package is stuck downloading try File > Packages > Reset Package Caches or Run the command rm -rf ~/Library/Caches/org.swift.swiftpm/ in terminal Read more in Apple documentation Hint: Use either Cocoapods or Swift Package Manager for Individual Packages to avoid Duplicate binaries

Usage

Telnyx client setup

Telnyx client delegate

You will need to instantiate the client and set the delegate.
Then you will receive the following events:

Calls

Outboud call

This is a general example: In order to fully support outbound calls you will need to implement CallKit to properly handle audio states. For more information check Audio Session Handling WebRTC + CallKit section.

Inbound call

How to answer an incoming call:
This is a general example: In order to fully support inbound calls you will need to implement PushKit + CallKit. For more information check Setting up VoIP push notifications section.

AI Agent Integration

The Telnyx iOS WebRTC SDK provides comprehensive support for AI Agent functionality, enabling intelligent voice applications with real-time conversation capabilities.

Key Features

  • Anonymous Authentication: Connect to AI assistants without SIP credentials
  • Real-time Transcripts: Live conversation transcripts with role identification
  • Mixed Communication: Send text messages during voice calls
  • Widget Settings: Customizable AI assistant interface

Quick Start

Implementation Steps

  1. Anonymous Login - Authenticate with AI assistants without SIP credentials
  2. Starting Conversations - Initiate calls with AI agents
  3. Transcript Updates - Handle real-time conversation transcripts
  4. Text Messaging - Send text messages during voice calls

Complete Documentation

For comprehensive AI Agent integration documentation, see:

Preferred Audio Codecs

The SDK allows you to configure preferred audio codecs for your WebRTC calls. This feature enables you to prioritize specific codecs based on your application’s requirements for audio quality, bandwidth usage, or network conditions.

Getting Supported Codecs

Query the list of audio codecs supported by the device and WebRTC framework:

Setting Preferred Codecs

For Outbound Calls:
For Inbound Calls:

Common Codec Configurations

High Quality Audio (VoIP apps):
Traditional Telephony Compatibility:
Low Bandwidth Optimization:
For detailed documentation on codec selection, configuration options, and best practices, see the Preferred Audio Codecs Guide.

Call Termination Reasons

When a call ends, the SDK provides detailed information about why the call was terminated through the CallTerminationReason structure. This information is available in the DONE state of the call.

CallTerminationReason Structure

The CallTerminationReason structure contains the following fields:
  • cause: A string describing the general cause of the call termination (e.g., “CALL_REJECTED”, “USER_BUSY”)
  • causeCode: A numerical code corresponding to the cause
  • sipCode: The SIP response code (e.g., 403, 404)
  • sipReason: The SIP reason phrase (e.g., “Dialed number is not included in whitelisted countries”)

Accessing Call Termination Reasons

You can access the termination reason in the onCallStateUpdated delegate method:

Common Termination Causes

The SDK provides various termination causes, including:
  • NORMAL_CLEARING: Call ended normally
  • USER_BUSY: The called party is busy
  • CALL_REJECTED: The call was rejected
  • UNALLOCATED_NUMBER: The dialed number is invalid
  • INCOMPATIBLE_DESTINATION: The destination cannot handle the call type

WebRTC Statistics

The SDK provides WebRTC statistics functionality to assist with troubleshooting and monitoring call quality. This feature is controlled through the debug flag in the TxClient configuration.

Enabling WebRTC Statistics

To enable WebRTC statistics logging:

Understanding WebRTC Statistics

When debug: true is configured:
  • WebRTC statistics logs are automatically collected during calls
  • Logs are sent to the Telnyx portal and are accessible in the Object Storage section
  • Statistics are linked to the SIP credential used for testing
  • The logs help the Telnyx support team diagnose issues and optimize call quality

Real-time Call Quality Monitoring

The SDK provides real-time call quality metrics through the onCallQualityChange callback on the Call object. This allows you to monitor call quality in real-time and provide feedback to users.

Using onCallQualityChanged

CallQualityMetrics Properties

The CallQualityMetrics object provides the following properties:

CallQuality Enum

Best Practices for Call Quality Monitoring

  1. User Feedback:
    • Consider showing a visual indicator of call quality to users
    • For poor quality calls, provide suggestions (e.g., “Try moving to an area with better connectivity”)
  2. Logging:
    • Log quality metrics for later analysis
    • Track quality trends over time to identify patterns
  3. Adaptive Behavior:
    • Implement adaptive behaviors based on call quality
    • For example, suggest switching to audio-only if video quality is poor
  4. Performance Considerations:
    • The callback is triggered periodically (approximately every 2 seconds)

Important Notes

  1. Log Access:
    • If you run the app using SIP credential A with debug: true, the WebRTC logs will be available in the Telnyx portal account associated with credential A
    • Logs are stored in the Object Storage section of your Telnyx portal
  2. Troubleshooting Support:
    • WebRTC statistics are primarily intended to assist the Telnyx support team
    • When requesting support, enable debug: true in TxClient for all instances
    • Provide the debug ID or callId when contacting support
    • Statistics logging is disabled by default to optimize performance
  3. Best Practices:
    • Enable debug: true only when troubleshooting is needed
    • Remember to provide the debug ID or callId in support requests
    • Consider disabling debug mode in production unless actively investigating issues

Custom Logging

The SDK provides a flexible logging system that allows you to implement your own custom logger. This feature enables you to route SDK logs to your preferred logging framework or format.

Implementing a Custom Logger

To create a custom logger, implement the TxLogger protocol:

Using a Custom Logger

To use your custom logger, pass it to the TxConfig when initializing the client:

Default Logger

If no custom logger is provided, the SDK uses TxDefaultLogger which prints logs to the console with appropriate formatting and emojis for different log levels.

Important Notes

  1. Log Levels:
    • The logLevel parameter in TxConfig still controls which logs are processed
    • Custom loggers only receive logs that match the configured verbosity level
  2. Thread Safety:
    • Ensure your custom logger implementation is thread-safe
    • Log callbacks may come from different threads
  3. Performance:
    • Keep logging operations lightweight to avoid impacting call quality
    • Consider asynchronous logging for heavy operations
  4. Best Practices:
    • Handle all log levels appropriately
    • Include timestamps for proper log sequencing
    • Consider log persistence for debugging
    • Handle errors gracefully within the logger

Push Notifications Setup

In order to receive incoming calls while the app is running in background or closed, you will need to perform a set of configurations over your Mission Control Portal Account and your application. For detailed documentation on setting up push notifications, see:
  • App Setup - Configure your iOS app to receive VoIP push notifications
  • Portal Setup - Set up your Telnyx Portal account with VoIP push credentials
  • Troubleshooting - Debug common push notification issues

Trickle ICE

The SDK supports Trickle ICE, which enables faster call setup by sending ICE candidates incrementally as they are discovered, rather than waiting for all candidates before establishing the connection.

Key Features

  • Faster Call Establishment: Candidates are sent immediately as discovered, reducing connection time
  • Automatic Management: No configuration required - the SDK handles Trickle ICE automatically
  • Smart Queuing: Answering side queues candidates until ANSWER is sent to prevent race conditions
  • Candidate Cleaning: WebRTC extensions are removed for maximum server compatibility

How It Works

Outbound Calls: Candidates are sent immediately as they are generated Inbound Calls: Candidates are queued until the call is answered, then flushed all at once followed by real-time sending of new candidates This approach prevents race conditions where candidates might arrive before the answer, ensuring reliable call setup. For comprehensive documentation on Trickle ICE implementation, troubleshooting, and technical details, see the Trickle ICE Guide.

Testing VoIP Push Notifications

The repository includes a dedicated testing tool to help validate your VoIP push notification setup. This tool allows you to send test push notifications directly to your device using your own certificates and configuration. Location: push-notification-tool/ in the repository root

Quick Setup

What the Tool Does

  • Validates Configuration: Tests your certificate files, bundle ID, and device token
  • Sends Test Pushes: Generates VoIP notifications with SDK-compatible payload structure
  • Provides Detailed Errors: Clear error messages to help identify configuration issues
  • Supports Continuous Testing: Send multiple pushes, switch configurations, test different scenarios
  • Smart Configuration Management: Saves settings between sessions for faster iteration

Perfect for Testing

  • Certificate and environment validation
  • Device token verification
  • Payload structure compatibility
  • Multi-device testing
  • Troubleshooting push delivery issues
For complete setup instructions and usage examples, see the tool’s README or the Troubleshooting Guide.

VoIP Push - Portal setup

During this process you will learn how to create a VoIP push credential and assign the credential to a SIP Connection. This process requires:
  • A Mission Control Portal Account.
  • A SIP Connection.
  • Your Apple VoIP push certificate.
For complete instructions on how to setup Push Notifications got to this link.

VoIP Push - App Setup

The following setup is required in your application to receive Telnyx VoIP push notifications:

a. Add Push Notifications capability to your Xcode project

  1. Open the xcode workspace associated with your app.
  2. In the Project Navigator (the left-hand menu), select the project icon that represents your mobile app.
  3. In the top-left corner of the right-hand pane in Xcode, select your app’s target.
  4. Press the +Capabilities button.

Screen Shot 2021-11-26 at 13 34 12

  1. Enable Push Notifications

Screen Shot 2021-11-26 at 13 35 51

b. Configure PushKit into your app:

  1. Import pushkit
  1. Initialize PushKit:
  1. Implement PKPushRegistryDelegate
  1. If everything is correctly set-up when the app runs APNS should assign a Push Token.
  2. In order to receive VoIP push notifications. You will need to send your push token when connecting to the Telnyx Client.
For more information about Pushkit you can check the official Apple docs. Important:
  • You will need to login at least once to send your device token to Telnyx before start getting Push notifications.
  • You will need to provide pushMetaData to processVoIPNotification() to get Push calls to work.
  • You will need to implement ‘CallKit’ to report an incoming call when there’s a VoIP push notification. On iOS 13.0 and later, if you fail to report a call to CallKit, the system will terminate your app. More information on Apple docs

c. Configure CallKit into your App:

PushKit requires you to use CallKit when handling VoIP calls. CallKit ensures that apps providing call-related services on a user’s device work seamlessly together on the user’s device, and respect features like Do Not Disturb. CallKit also operates the system’s call-related UIs, including the incoming or outgoing call screens. Use CallKit to present these interfaces and manage interactions with them. For more information about CallKit you can check the official Apple docs. General Setup:
  1. Import CallKit:
  1. Initialize CallKit
  1. Implement CXProviderDelegate methods.
Audio Session Handling WebRTC + CallKit To get CallKit properly working with the TelnyxRTC SDK you need to set the audio device state based on the CallKit AudioSession state like follows:
Reporting calls with CallKit To properly report calls to callKit with right statuses, you need to invoke the following callKit methods at the right instances:
  1. Starting A New Call : When ever you start a call, report to callkit using the provider.reportCall() method.
  1. When user receives a Call : Use provider.reportNewIncomingCall(with: uuid, update: callUpdate) to report an incoming call. This sends a request to callKit the to provide the native call interface to the user.
  1. When callee answers an outgoing call : Use provider.reportOutgoingCall(with: callKitUUID, connectedAt:nil) to report a connected outgoing call. This provides the time when the outgoing call goes to active to callKit.
NB : This should be used only when the call is outgoing.

Best Practices when Using PushNotifications with Callkit.

  1. When receiving calls from push notifications, it is always required to wait for the connection to the WebSocket before fulfilling the call answer action. This can be achieved by implementing the CXProviderDelegate in the following way (SDK version >=0.1.11):
When the answerFromPush(answerAction: action) is called, Callkit sets the call state to connecting to alert the user that the call is being connected. Once the call is active, the timer starts. The previous SDK versions requires handling the websocket connection state on the client side. It can be done in the following way:
Likewise for ending calls, the endCallFromCallkit(endAction:action) method should be called from :
Calling this method solves the race condition, where call is ended before the client connects to the webserver. This way the call is ended on the callee side once a connection is established.
  1. Logs on the receiver’s end are essential for thorough debugging of issues related to push notifications. However, the debugger is not attached when the app is completely killed. To address this, you can simply put the app in the background. VOIP push notifications should then come through, and the debugger should capture all logs.
Handling Multiple Calls To handle multiples, we can rely on the CXProviderDelegate delegate which invokes functions corresponding to what action was performed on the callkit user interface.
  1. End and Accept or Decline : The end and accept button on the callkit user interface accepts the new call and ends the previous call. Callkit then invokes the CXAnswerCallAction and CXEndCallAction when the end and accept button is pressed. You can handle this scenario by
Subsequently, when the user clicks on the End and Accept or Decline Button, you will need to determine which of these buttons was clicked. You can do that as follows:
Note While handling multiple calls, you should report the call end to callkit properly with the right callUUID. This will keep your active calls with the callkit user interface until there are no more active sessions.
  1. Hold and Accept or Decline: The hold and accept button on the callkit user interface accepts the new call and holds the previous call. Callkit then invokes the CXSetHeldCallAction when the hold and accept button is pressed.
Also, you will need to un-hold the previous call when the current call gets ended on CXEndCallAction.
Note While handling multiple calls, you should report the call end to callkit properly with the right callUUID. This will keep your active calls with the callkit user interface until there are no more active sessions.

Disable Push Notification

Push notifications can be disabled for the current user by calling :
Note : Signing back in, using same credentials will re-enable push notifications.

Privacy Manifest

Support for privacy manifest is added from version 0.1.26

Documentation:

For more information you can:
  1. Clone the repository
  2. And check the exported documentation in: docs/index.html

Support

Find official documentation here Questions? Comments? Building something rad? Join our Slack channel and share.

License

MIT Licence © Telnyx