Video for iOS


The Sinch SDK is a product that makes adding voice/video calling and/or instant messaging to mobile apps easy. It handles the complexity of signaling and audio & video management while providing you the freedom to create a stunning user interface.

This document provides an overview for developers integrating with Sinch SDK for the first time. It outlines the prerequisites and guides you through the process of setting up and answering calls as well as sending and receiving instant messages.

Please see the Reference Documentation for a comprehensive description of all the classes.

First time setup

This is a step-by-step guide about setting up the Sinch SDK for the first time.

Register an Application

  1. Register a Sinch Developer account here.
  2. Setup a new Application using the Dashboard where you can then obtain an Application Key and an Application Secret.


The Sinch SDK can be downloaded here. It contains: the library binary, this user guide, reference documentation, and sample apps for calling and instant messaging.

Sinch is available as a CocoaPod

If you are using CocoaPods, add the following to your Podfile:

target '<your xcode project>' do
  pod 'SinchRTC'

Tip: Using the pod allows you to skip the manual steps in the next section.

Add the Sinch.framework

Drag the Sinch.framework bundle from the SDK distribution package folder into the Frameworks section in the Xcode Project Navigator.

The Sinch SDK depends on the following frameworks which must be linked with the application target:

libc++.dylib (libc++.tbd), libz.tbd, Security.framework, AVFoundation.framework, AudioToolbox.framework, VideoToolbox.framework, CoreMedia.framework, CoreVideo.framework, CoreImage.framework, GLKit.framework, OpenGLES.framework, QuartzCore.framework


If only the instant messaging functionality will be used, then no changes to the Info.plist are necessary.

If voice calling functionality will be enabled and used, add the following to your Info.plist:

  • Required background modes (UIBackgroundModes):

    • Application plays audio (audio)
    • Application provides Voice over IP services (voip)
  • Privacy - Microphone Usage Description (NSMicrophoneUsageDescription):

    NSMicrophoneUsageDescription describes the reason your app accesses the microphone. When the system prompts the user to allow access, this string is displayed as part of the alert, and it cannot be left empty.

In addition to the keys above, if video calling functionality will be enabled and used, add the following to your Info.plist:

Sinch client

The SINClient is the Sinch SDK entry point. It is used to configure the user’s and device’s capabilities, as well as providing access to feature classes such as the SINCallClient, SINMessageClient and SINAudioController.

Creating the SINClient

Set up the client and its delegate (SINClientDelegate, see Reference documentation).

#import <Sinch/Sinch.h>

// Instantiate a Sinch client object
id<SINClient> sinchClient = [Sinch clientWithApplicationKey:@"<application key>"
                                          applicationSecret:@"<application secret>"
                                                     userId:@"<user id>"];

The Application Key and Application Secret are obtained from the Sinch Developer Dashboard. See [Production and Sandbox Environments][] for valid values for environmentHost. The User ID should uniquely identify the user on the particular device.

Specifying capabilities

The SINClient can be configured to enable / disable certain functionality. Please see the Reference for details.

The following example shows how to setup the client with both voice calling and instant messaging enabled, and using push notifications.

// Specify the client capabilities.
// (At least one of the messaging or calling capabilities should be enabled.)
[sinchClient setSupportCalling:YES];
[sinchClient setSupportMessaging:YES];

[sinchClient enableManagedPushNotifications];

Starting the Sinch client

Before starting the client, make sure you assign a SINClientDelegate.

// Assign as SINClientDelegate
sinchClient.delegate = ... ;

// Start the Sinch Client
[sinchClient start];

// Start listening for incoming calls and messages
[sinchClient startListeningOnActiveConnection];

Note: If the application is meant to only make outgoing calls but not receive incoming calls, don’t call the startListeningOnActiveConnection. Outgoing calls can be made after calling the start method, and after the delegate has received the callback clientDidStart:.

For applications that want to receive incoming calls while not running in the foreground, push notifications are required.

Life cycle management of a SINClient-instance

We recommend that you initiate the Sinch client, start it, but not terminate it, during the lifetime of the running application. That also implies that the SINClient-instance should be retained by the application code.

If incoming events are not needed, stop listening for incoming events by invoking -[SINClient stopListeningOnActiveConnection]), but do not invoke -[SINClient terminateGracefully] or -[SINClient terminate]. The reason is initializing and starting the client is relatively resource-intensive in terms of CPU.

It is best to keep the client instance alive and started unless there are reasons specific to your application. It should not be necessary to dispose of the client instance if memory warnings are received from iOS, because once the client is started it does not use much memory in comparison to view layers, view controllers etc. For the same reasons, if support for push notifications is enabled, the preferred method of temporarily stopping incoming events is to [Unregister a push device token][].

The Sinch client can of course be completely stopped and also disposed. To do so, call one of the terminate methods on the client before the application code releases its last reference to the client object.

The following example shows how to dispose the Sinch client:

[sinchClient stopListeningOnActiveConnection];
[sinchClient terminateGracefully]; // or invoke -[SINClient terminate]
sinchClient = nil;


The Sinch SDK supports four types of calls: app-to-app (audio or video), app-to-phone, app-to-sip and conference calls. The SINCallClient is the entry point for the calling functionality of the Sinch SDK.

Calls are placed through the SINCallClient and events are received using the SINCallClientDelegate. The call client is owned by the SinchClient and accessed using [sinchClient callClient]. Calling is not enabled by default.

Enable calling with the following method before starting the SINCallClient:

[sinchClient setSupportCalling:YES];

Setting up an app-to-app call

Use the call client to start the call using the callUserWithId: method by passing the user identifier of the callee (the user receiving a call) as an argument.

id<SINCallClient> callClient = [sinchClient callClient];
id<SINCall> call = [callClient callUserWithId:@"<remote user id>"];
// Or for video call: id<SINCall> call = [callClient callUserVideoWithId:@"<remote user id>"];

A call object is returned, containing details about the participants in the call, call details such as start time, call state, possible errors, and so on.

Assuming the callee’s device is available and responsive, the delegate method callDidProgress: is called. It notifies the application that the outgoing call is progressing. If a progress tone should be played, this is where it should be started. We recommend that you use the available functionality provided by the Sinch SDK to play sounds such as ringtones (SINAudioController). See [Playing Ringtones][] for details.

When the other party answers, the callDidEstablish: call delegate method is called. Now, the users can start talking. If a progress tone has been initiated, it should be stopped now, in the delegate callback method.

Setting up an app-to-phone call

An app-to-phone call is a call that is made to a phone on the regular telephone network. Setting up an app-to-phone call is not much different from setting up an app-to-app call.

Instead of invoking the callUserWithId: method, invoke the callPhoneNumber: method on the SINCallClient object. Sufficient funds must be available on the Sinch account and a valid phone number specified for the call to connect successfully. The phone number should be specified according to the E.164 number formatting ( recommendation and should be prefixed with a ‘+’. E.g. to call the US phone number 415 555 0101, the phone number should be specified as “+14155550101”. The ‘+’ is the required prefix and the US country code ‘1’ prepended to the local subscriber number.

Placing an app-to-phone call requires an account with credits; topping up credits can be done on the Account page. Credits are used each time an app-to-phone call is placed and the balance history is updated after each call.

App-to-phone calls can be tested by calling the following test number: +46000000000. When placing a call to this number, you will hear a voice prompt stating that the call has been connected, and shortly after that the call will automatically be ended.

Setting up an app-to-sip call

An app-to-sip call is a call that is made to a SIP server. Setting up an app-to-sip call is not much different from setting up an app-to-app call. Instead of invoking the callUserWithId: method, invoke the callSIP: method on the SINCallClient object. The SIP identity follows the form of email addresses (user@domain), for example

id<SINCallClient> callClient = [sinchClient callClient];
id<SINCall> call = [callClient callSIP:@"<SIP Identity>"];

When customized SIP headers are passed as a parameter, the headers should be prefixed with ‘x-’. If the SIP server reported any errors, the SINCallDetails object will provide an error with SINErrorDomainSIP.

Setting up a conference call

A conference call can be made to connect a user to a conference room where multiple users can be connected at the same time. The identifier for a conference room may not be longer than 64 characters.

id<SINCallClient> callClient = [sinchClient callClient];
id<SINCall> call = [callClient callConferenceWithId:@"<conferenceId>"];

It is also possible to connect users to a conference call via the Sinch REST API.

Handling incoming calls

To act on the incoming calls, implement the protocol SINCallClientDelegate and assign a delegate to the call client. The call client delegate is notified using the delegate method didReceiveIncomingCall: as calls come in to the device.

When the delegate method is executed, the call can either be connected automatically without any user action, or it can wait for the user to press the answer or the hangup button. We recommend that ringtones are played from within the delegate callback method. See [Playing Ringtones][] for details.

- (void)client:(id<SINCallClient>)client didReceiveIncomingCall:(id<SINCall>)call {
    // Start playing ringing tone

    // Assign delegate
    call.delegate = self;

To get events related to the call, set the call delegate. The call object contains details about participants, start time, potential error codes, and error messages.

If VoIP push notifications is enabled, add logic for presenting a local notification if the app is in the background when receiving the call:

- (SINLocalNotification *)client:(id<SINClient>)client
  localNotificationForIncomingCall:(id<SINCall>)call {
    SINLocalNotification *notification = [[SINLocalNotification alloc] init];
    notification.alertAction = @"Answer";
    notification.alertBody = @"Incoming call";
    return notification;

IMPORTANT: See [Local and Remote Push Notifications][] for further details on how to present and handle a user notification for an incoming call when the application is in the background.

Incoming video call

When incoming call is a video call, the didReceiveIncomingCall delegate method will be executed, just like for the incoming audio call. The SINCallDetails object provides a isVideoOffered property to check whether the call offers a video track. See the [Video calling] section for details on how to add video views.

Answering an incoming call

To answer a call, use the answer method on the call to accept it. If a ringtone was previously played, it should be stopped now.

User presses the answer button:

// User answers the call
[call answer];

// Stop playing ringing tone

Now, the clients on both ends establish the connection. When the call is established and the voice streams are running in both directions, the callDidEstablish: delegate method is called.

Declining an incoming call

If the call should not be answered, use the hangup method on the call to decline. The caller is notified that the incoming call was denied. If a ringtone was previously played, it should be stopped now.

User presses the hangup button:

// User does not want to answer
[call hangup];

// Stop playing ringing tone

Disconnecting a call

When the user wants to disconnect an ongoing call, use the hangup method. Either user taking part in a call can disconnect it.

Hanging up a call:

[call hangup];

When either party disconnects a call, the application is notified using the call delegate method callDidEnd:. This allows the user interface to be updated, an alert tone to be played, or similar actions to occur.

A call can be disconnected before it has been completely established.

Hanging up a connecting call:

// Starting a call
id<SINCall> call = [client callUserWithId:@"<remote user id>"];

// User changed his/her mind, let’s hangup
[call hangup];

Handling a call that ends:

// SINCallDelegate implementation

- (void)callDidEnd:(id<SINCall>) call {
  // update user interface, e.g. hide the call screen.

Local and Remote Push Notifications

When an application is no longer in the foreground, the user must be notified of an incoming call or instant message by means of either a local notification or a remote push notification.

If the app is allowed to execute while in background then the Sinch SDK will primarily use local notifications to initially notify the user. Whether the app is allowed to execute while in background depends on whether you as a developer choose to enable VoIP push notifications and/or Active Connection in Background. If only regular remote push notifications are used then those will also be used to notify the user (as a regular remote push notification will be displayed to the user by the iOS without handing over any control to the application).

Remote Push Notifications

An application is considered offline in the following scenarios:

  • Application is not running at all
  • Application is not in the foreground, and the feature [Active Connection in Background][] is not enabled

For these scenarios, push notifications can be used to receive incoming calls and instant messages. The following sections cover how to enable receiving calls and messages using remote push notifications (both the VoIP type and regular.)

Enable push notifications on a Sinch client

When creating a Sinch client, managed push notifications must be enabled:

id<SINClient> client = [Sinch clientWithApplicationKey:@"<application key>"
                                     applicationSecret:@"<application secret>"
                                                userId:@"<user id>"];

[client enableManagedPushNotifications];

Forward incoming push notifications to a Sinch client

Implement the protocol SINManagedPushDelegate and forward any incoming push notifications to a Sinch client:

// SINManagedPushDelegate
- (void)managedPush:(id<SINManagedPush>)unused
    didReceiveIncomingPushWithPayload:(NSDictionary *)payload
                              forType:(NSString *)pushType {
    id<SINClient> client; // get previously created client
    [client relayRemotePushNotification:userInfo];

The purpose of SINManagedPushDelegate and the delegate method managedPush:didReceiveIncomingPushWithPayload:type: is that it provides a single unified code path for handling incoming push notifications, no matter whether it is a regular remote push notification or a VoIP push notification (which is received via PushKit and PKPushRegistry). In the case of a regular remote push; independently of whether it is arriving via -[UIApplicationDelegate didReceiveRemoteNotification: or as a launch option via -[UIApplication applicationDidFinishLaunching:didFinishLaunchingWithOptions:.

Unregister a push device token

If the user of the application logs out or performs a similar action, the push notification device token can be unregistered via -[SINClient unregisterPushNotificationDeviceToken] to prevent further notifications to be sent to the particular device.

Supporting regular remote push notifications (i.e. non-VoIP type push notifications)

Because of differences in the iOS SDK API with respect to regular and VoIP push notifications, incoming push notifications have different code paths through an application. SINManagedPush unifies this to the extent possible, but for regular remote notifications which are traditionally received via methods on UIApplicationDelegate, the following methods should be forwarded from the application delegate:

- (void)application:(UIApplication *)application
    didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        [self.push application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];

- (void)application:(UIApplication *)application
    didReceiveRemoteNotification:(NSDictionary *)userInfo {
        [self.push application:application didReceiveRemoteNotification:userInfo];

Sinch localization strings for push notification alerts

When the Sinch dashboard sends a remote push notification for an incoming call or message it will by default use one of the localization strings shown below. You will need to add these to your Localizable.strings file.

SIN_INCOMING_CALL = "Incoming call";
SIN_INCOMING_CALL_DISPLAY_NAME = "Incoming call from %@";
SIN_INCOMING_IM = "Incoming message";
SIN_INCOMING_IM_DISPLAY_NAME = "Incoming message from %@";
SIN_INCOMING_VIDEO_CALL = "Incoming video call";
SIN_INCOMING_VIDEO_CALL_DISPLAY_NAME = "Incoming video call from %@";

SIN_INCOMING_CALL_DISPLAY_NAME (or SIN_INCOMING_IM_DISPLAY_NAME) will be used if display name have been set by the caller via -[SINManagedPush setDisplayName: or -[SINClient setPushNotificationDisplayName:]. Display name is included in a push notification on a best-effort basis. For example, if the target device has very limited push payload size constraints (e.g. iOS 7 can only handle 255 byte push notification payload), then the display name may not be included.

(Note: This is not applicable to VoIP type push notifications because in that case the Sinch SDK will present a local notification (see -[SINCallClientDelegate client:localNotificationForIncomingCall:) )

Please see Apple’s Local and Remote Notification Programming Guide on remote push notification and localization strings for more details.

Presenting local notifications for incoming calls

If the application is not in foreground when receiving an incoming call, the SINCallClient will ask it’s delegate SINCallClientDelegate to specify how a local notification should be presented. The delegate is responsible for composing a SINLocalNotification with content that is to be shown to the user when the local notification is presented to the user by iOS. The delegate can specify all things as available for a regular UILocalNotification, e.g. alert body, actions, a badge number, and the path to a sound file that is played when the notification is presented. Example:

// implementation of SINCallClientDelegate
- (SINLocalNotification *)client:(id<SINClient>)client
  localNotificationForIncomingCall:(id<SINCall>)call {
    SINLocalNotification *notification = [[SINLocalNotification alloc] init];
    notification.alertAction = @"Answer";
    notification.alertBody = @"Incoming call";
    return notification;

If the user taps the notification, iOS brings the app back into the foreground. The notification object contains information that is needed by the Sinch SDK to continue initiating the incoming call. To hand over the notification object to the Sinch client, use the method relayLocalNotification::

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {

    if ([notification sin_isSinchNotification]){

      // This will trigger -[SINClientDelegate didReceiveIncomingCall:] if the notification
      // represents a call (i.e. contrast to that it may represent an instant-message)
      id<SINNotificationResult> result = [client relayLocalNotification:notification];

The SINCallNotificationResult object provides details about the caller, whether the call timed out and whether the call offers video.

Answering a call received while in background

Once the Sinch SDK has processed the call information extracted from the notification, it calls the delegate method client:didReceiveIncomingCall:. Depending on the desired behavior for the app, the incoming call may either be treated as any other incoming call and let the user tap an additional button to answer it, or the call may be answered automatically when the user has acted on the local notification.

In the latter case, the app can determine whether the call originated from background mode or not by examining the applicationStateWhenReceived property of the call details object. If the application was active when it received the call, it means the app was in the foreground. This approach is also applicable to offline calls with Apple Push Notifications.

- (void)client:(id<SINClient>)client didReceiveIncomingCall:(id<SINCall>)call {
    call.delegate = self;

    if (call.details.applicationStateWhenReceived == UIApplicationStateActive) {
        // Show an answer button or similar in the UI
    } else {
        // Application was in not in the foreground when the call was initially received,
        // and the user has opened the application (e.g. via a Local Notification),
        // which we then interpret as that the user want to answer the call.
        [call answer];

Presenting local notifications for missed calls

When the push notification is enabled on a Sinch client, besides the incoming call notification, the Sinch SDK will also send a push notification for a canceled call when the caller cancels the call before it is answered. This gives developers a good opportunity to present local notifications for missed calls in their apps.

A SINNotificationResult will be returned when an incoming push notification is forwarded to a Sinch client. It could then be inspected to determine if the push notification is a canceled call, it also provides detailed information such as remoteUserId to construct a more informative local notification for a missed call.

// SINManagedPushDelegate
- (void)managedPush:(id<SINManagedPush>)unused
    didReceiveIncomingPushWithPayload:(NSDictionary *)payload
                              forType:(NSString *)pushType {
    id<SINClient> client; // get previously created client

    id<SINNotificationResult> result = [client relayRemotePushNotification:userInfo];
    if ([result isCall] && [[result callResult] isCallCanceled]) {
        // present a local notification for the missed call.

Enabling VoIP push notifications

In iOS 8 Apple introduced remote VoIP push notifications and a new framework PushKit.framework. VoIP push is more battery efficient than using an active VoIP socket, and still provides the possibility of background execution which allows for faster call setup time. The Sinch SDK supports both VoIP and regular remote push notifications.

The Sinch SDK will automatically use VoIP push if PushKit.framework is linked into your app, given that -[SINManagedPush:setDesiredPushTypeAutomatically] is used. Using setDesiredPushTypeAutomatically will fall back to using regular remote push notifications on devices that don’t support VoIP push (e.g. devices running on iOS < 8.0).

It is required to implement -[SINCallClientDelegate localNotificationForIncomingCall:] when using VoIP push.

To enable VoIP push on devices that are capable of it and also fall back on regular remote notifications for iOS 6 and 7, we recommended to weak link PushKit.framework. In the Xcode target settings, go to Build Phases and the section Link Binary With Libraries and in the Status field on the right-hand side, select Optional (instead of Required):


For more details on VoIP push notifications, see here

Sinch local notifications and the Notification Center

The following details explain how the Sinch SDK handles local notifications and how it affects what is presented in the Notification Center.

  • A notification that is passed in to the method -[SINClient relayLocalNotification:notification:] is removed from the Notification Center after it has been handled.
  • A local notification representing an incoming call is removed if the call times out or the call is canceled.
  • Invoking -[SINCall hangup] from -[SINClient client:localNotificationForIncomingCall] is a valid operation and can be used to dismiss a call while the user is busy talking in the regular phone app. This effectively prevents the SDK from invoking the -[SINClientDelegate client:didReceiveIncomingCall:] method when the app returns to foreground.
  • Invoking -[SINCall answer] while being in the background is possible. The call is not immediately answered but the operation is considered pending and the call answered once the app returns to the foreground.

Sending and receiving custom headers via Sinch managed push

The Sinch SDK supports adding custom headers in push notification messages when initiating a call, so developers do not need to implement their own push mechanism if they only need to deliver small pieces of information along the Sinch managed push between their app instances. The Sinch SDK allows up to 1024 bytes of custom headers.

Setting headers on the sender side when initiating a call:

// Enable push notification on Sinch client before making the call
// Set headers
NSDictionary *headers = @{
                          @"id" : @"0429",
                          @"message" : @"Greetings from Alice."
id<SINCall> call = [self.callClient callUserWithId:@"Bob"

On the receiver side, the headers are received and encoded in the push payload, and can be queried by [SINPushHelper queryPushNotificationPayload:payload]. The helper will return a SINNotificationResult which contains headers inside callResult.

+ (void)managedPush:(id<SINManagedPush>)unused
didReceiveIncomingPushWithPayload:(NSDictionary *)payload
            forType:(NSString *)pushType {

  id<SINNotificationResult> result = [SINPushHelper queryPushNotificationPayload:payload];
  if ([result isCall]) {
    NSLog(@"%@", result.callResult.headers);

    // You can then invoke relayRemotePushNotification:userInfo
    // on a SINClient instance to further process the incoming call.

Apple Push Notification Certificates

Sending and receiving push notifications via Sinch requires you to create Apple Push Certificates and upload them to the Sinch Dashboard. For each application, Sinch allows you to upload up to three certificates corresponding, one for each type: Development, Production and VoIP Services.

Generating Apple Push Certificates

Apple Push Certificates are generated from the Apple Developer Member Center which requires a valid Apple ID to login. If you do not have this information, find out who manages the Apple Developer Program for your organization.

Setting up your Apple Push Certificates with Sinch

  • Login to the Dashboard
  • Open the Apps tab, select the application of your choice and click on the Push Notification icon on the left-most side.
  • Drag and drop the certificates associated to your application
  • If your certificate has a password, enter it and hit Enter

Your push notification certificates are now uploaded and ready for use.

Certificates configured with Sinch can be replaced or renewed by uploading new ones. New certificates will automatically replace the previous ones for their respective type (Development, Production and VoIP Services).

Apple Push Service environments and provisioning

When an iOS application is code signed, it is the embedded Provisioning Profile that will specify which Apple Push Notification Service Environment (APS Environment) the acquired push notification device token will be bound to. Depending on how an application is provisioned it has an effect on what should be passed to [Sinch managedPushWithAPSEnvironment:]. For example if your application is signed with a Development provisioning profile it will be bound to the APS Development environment. If it’s code signed with a Distribution provisioning profile (also referred to as Universal) it will be bound to the APS Production environment.

Typically a Debug build will be code signed with a Development provisioning profile and thus SINAPSEnvironmentDevelopment should be used. And typically a Release build will be code signed with a Distribution provisioning profile and thus SINAPSEnvironmentProduction should be used. Instead of changing this manually for each build, the macro SINAPSEnvironmentAutomatic is available which automatically expands to Development for Debug builds and Production for Release builds.

Audio handling

If the application plays audio that does not originate from the Sinch SDK, certain guidelines should be followed. Additional information on audio session-related topics is available in the Audio Session Programming Guide.

Audio sessions

When a call is established, the Sinch client activates the shared audio session. When the call is disconnected, the Sinch client deactivates the shared audio session. If the application wants to play audio in any other context, it needs to reactivate the shared audio session. This applies after each finished call.

When started, the Sinch SDK client sets itself as the audio session delegate. If the application wishes to override this behavior, the application needs to reset the delegate after the client has started but before any call has been started. (Doing this is not recommended.)

Audio session categories

When the Sinch client is started, it sets the audio session category to PlayAndRecord. The reason the Sinch client only sets the audio category once, is to avoid interfering with what the hosting application may want to do with the audio session.

If the application changes the audio session category, it is responsible for changing the category back to PlayAndRecord after the application has performed its audio task so that the category is correctly setup for calls.

The Sinch SDK applies the audio session category mode AVAudioSessionModeVoiceChat for improved voice quality. Please see Apple’s AVAudioSession documentation for further details.

Audio session interruptions

When the users are in the midst of a Sinch SDK call, someone might call users using the PSTN network, thus interrupting the application and make iOS play the regular native ringtone. If the native phone call ends within 30 seconds, the application will start running again. If not, the Sinch SDK call will be terminated.

Playing ringtones

The SINAudioController object provides a convenience method startPlayingSoundFile:loop: for playing sounds that are related to a call, such as ringtones and busy tones. Details on how to use it can be found in the Reference documentation.

The sound file must be a mono (1 channel), 16-bit, uncompressed (PCM) .wav file with a sample rate of 8kHz, 16kHz, or 32kHz.

- (void)callReceivedOnRemoteEnd:(id<SINCall>)call {
    NSString* soundFilePath = [[NSBundle mainBundle] pathForResource:@"progresstone" ofType:@"wav"];
    // get audio controller from SINClient
    id<SINAudioController> audioController = [self.client audioController];
    [audioController startPlayingSoundFile:soundFilePath loop:NO];

Applications that prefer to use their own code for playing sounds are free to do so, but they should follow the guidelines for Audio Sessions and Audio Session Categories above.

Application authentication

A user identity must be provided when initiating a Sinch client. The first time the application instance and the Sinch client are running on behalf of a particular user, they are required to register against the Sinch service. This is mostly handled transparently by the Sinch SDK, but it works slightly differently depending on which authentication scheme you choose to use.

The step of registering a user identity against the Sinch service requires the application instance to be authenticated and authorized to perform the user registration. Once the application instance has successfully registered the user identity, it will also have obtained the necessary credentials to perform further authorized requests for that specific user, for example, calling.

Two different authentication schemes are available: authentication by client access to application secret and authentication supported by application server.

Authentication by client access to Application Secret

This application authentication scheme is based on giving the application direct access to the Application Secret, which enables the Sinch Client SDK in the application to self-sign an authorized request to perform user registration. Choosing this authentication scheme corresponds to initiating the Sinch client by using the factory method that takes both an Application Key and an Application Secret.

Using this authentication scheme is the quickest way to get started as the client application instances can directly perform authorized requests against the Sinch service.

Caution: It is not recommended to have the application secret in plain text in the source code in the release version of the application.

Authentication supported by application server

This application authentication scheme is based on the client application instance not having direct access to the Application Secret. Instead, when the Sinch client needs to perform an authorized request to register a user identity against the Sinch service, it needs to be provided with an authentication signature and a registration sequence to perform the registration. This should be provided by the application’s backend service, for example, by using a HTTP request over an SSL connection.

This scheme has the benefit of the application secret never being directly accessible by the client applications and provides a better level of security as well as flexibility.

Note: The need for the Sinch client to request an authentication signature and registration sequence is only required once per user and device–not on every application launch.

Authentication Supported by Application Server

Generating the signature

The Application Server is responsible for generating a valid signature for each registration request that it accepts as a valid user registration. The sequence is a cryptographic nonce, and must be a monotonically increasing value. The signature is then generated as as follows (pseudogrammar):

string userId;
string applicationKey; // E.g. "196087a1-e815-4bc4-8984-60d8d8a43f1d"
string applicationSecret; // E.g. "oYdgGRXoxEuJhGDY2KQ/HQ=="
uint64 sequence = previous_sequence + 1; // E.g. previous_sequence = 0

string stringToSign = userId + applicationKey + sequence + applicationSecret;

// Use a Base64-encoder that don't introduce line-breaks,
// or trim the output signature afterwards.
string signature = Base64.encode(SHA1.digest(stringToSign));

For example, in Java:

// Generating the Signature - Java
// import;
// import org.apache.commons.codec.binary.Base64;

String userId;
String applicationKey; // E.g. "196087a1-e815-4bc4-8984-60d8d8a43f1d";
String applicationSecret; // E.g. "oYdgGRXoxEuJhGDY2KQ/HQ==";
long sequence; // fetch and increment last used sequence

String toSign = userId + applicationKey + sequence + applicationSecret;

MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
byte[] hash = messageDigest.digest(toSign.getBytes("UTF-8"));

String signature = Base64.encodeBase64String(hash).trim();

Starting the Client and Providing Authorization Credentials for User Registration

// Instantiate a client object using the client factory method.
id<SINClient> client = [Sinch clientWithApplicationKey:@"<application key>"
                                                    userId:@"<user id>"];

client.delegate = ...;

[client start];

// This will on the first run for this user, call
// -[SINClientDelegate client:requiresRegistrationCredentials:],
// which implementations could look something like this:

- (void)client:(id<SINClient>)client
requiresRegistrationCredentials:(id<SINClientRegistration>) registrationCallback {

  // Perform API request to server which keeps the Application Secret
  [myAPIService getAuthorizedSignatureForUser:[client userId]
  onSuccess:^(NSString* signature, long long sequence){

    // Forward the signature and sequence back into Sinch SDK
    [registrationCallback registerWithSignature:signature sequence:sequence];
  onFailure:^(NSError* error) {

    // Forward potential network request error to Sinch SDK,
    // e.g. failure due to no internet connection.
    [registrationCallback registerDidFail:error];


Minimum requirements

iOS 6.0 is the minimum iOS version required for using the Sinch SDK (iOS Deployment Target).

Note: The Sinch SDK library uses Automatic Reference Counting (ARC). However, it can still be used in non-ARC projects.

Note on Sinch.framework file size vs. linked size

The Sinch.framework file includes a FAT-binary containing the architectures armv7, armv7s, arm64, i386 and x86_64. When linking an application target against the Sinch.framework targeting an iOS device, it will add a approximately 6.1Mb per armv7 slice, and 6.3Mb for the arm64 slice.

Example: Assuming linking armv7 and arm64 into the final application, it would add approximately 12.4Mb to the application.

(Even though armv7s is supported and included, we recommend to not build your application for armv7s to reduce the final application binary size)

Production and Sandbox environments

Sinch provides two environments:

  • Production - Used for applications deployed in production.
  • Sandbox - Used during development and testing.

The environment is passed as the parameter environmentHost when instantiating the Sinch client.

Environment EnvironmentHost parameter

Restrictions on User IDs

User IDs can only contain characters in the printable ASCII character set. That is:


User IDs must not be longer than 40 characters.

Encryption export regulations

Please check the Summary of U.S. Export Controls Applicable to Commercial Encryption Products and ensure that the application is registered for the Encryption Regulations, if applicable. It can be found under this link.


The Sinch SDK client uploads statistics to the Sinch servers at the end of a call, a call failure, or similar event. The statistics are used for monitoring of network status, call quality, and other aspects regarding the general quality of the service.

Some of the information is not anonymous and may be associated with the User ID call participants.

The statistics upload is done by the client in the background.

Linking against the C++ standard library

Since Sinch SDK version 3.4.0, it is required to link against libc++. Though if your application is also dependent on libstdc++ (which is now considered deprecated by Apple for use on iOS), you can actually link against both libc++ and libstdc++ by passing the following linker flags:

  • Other Linker Flags -> -ObjC -Xlinker -lc++ -Xlinker -lstdc++

Request the user’s permission for the microphone and the camera.

Request user permission for using the microphone

Since iOS 7, additional user privacy constraints are enforced which requires the application to be granted permission to use the device microphone. Unless the application has explicitly requested permission to use the microphone, the user is shown a dialog the first time the microphone is activated.

In the context of the Sinch SDK, this occurs once the first call is established unless the application has been granted permission earlier. We strongly recommend you explicitly request permission to use the microphone in your application at an appropriate time such as when the user first sets up Sinch. You should not rely on the permission dialog shown when the first Sinch call is established as this will create an awkward user experience.

By explicitly requesting permission using the methods available in the iOS SDK, the application has more control over when the dialog is shown to the user. This results in a better user experience.

Starting with iOS 10.0, apps that access any of the device’s microphones must declare their intent to do so. This is done by including the NSMicrophoneUsageDescription key and a corresponding purpose string in your app’s Info.plist. When the system prompts the user to allow access, the purpose string is displayed as part of the alert. If an application attempts to access any of the device’s microphones without a corresponding purpose string, the app will exit.

Please see the Apple iOS SDK documentation on the class AVAudioSession for details on how to request permission to use the microphone.

Request user permission for using the camera

The same rule applies to request user permission for using the camera. In iOS, the user must explicitly grant your app permission to access device cameras or microphones for photo, video, or audio capture. Your app must provide an explanation for its use of capture devices using the NSCameraUsageDescription and NSMicrophoneUsageDescription Info.plist keys; iOS displays this explanation when initially asking the user for permission, and thereafter in the Settings app.

Please see the Apple iOS SDK documentation on the class AVCaptureDevice for details on how to request permission to use the camera.

App Extensions

App Extensions is a feature introduced in iOS 8. App extensions are compiled into executables that are separate from the main application executable. The Sinch SDK are using parts of the iOS SDK APIs that are unavailable to app extensions, thus it’s not supported to use the Sinch SDK in an app extension.

Xcode and Bitcode intermediate representation

The Sinch SDK supports Bitcode intermediate representation.

Push Notifications sent via your application server

In general we strongly recommend using “managed push notifications”, i.e. when push notifications are sent directly from the Sinch cloud, which is described in the section [Local and Remote Push Notifications][]. The following section on the contrary describes integrating support for push notifications but given that your application server maintain the connection with Apple Push Notification Service.

An application is considered offline in the following scenarios:

  • When the application is not running
  • When background mode has been disabled for the Sinch client, and the application is not in the foreground

For these scenarios, push notifications can be used to be able to receive incoming calls and instant messages. The following sections cover how to support receiving calls and messages using push notifications.

When offline, the recipient of a call or message receives a push notification containing a Sinch-specific payload which enables the Sinch client to connect the incoming call or message. Acting on the push notification brings the application to the foreground which allows the user to answer the call or view the message.

Figure 2. Push notification sequence.

The figure above describes the following sequence of events: Both users start their applications and Sinch clients. When A (the caller) calls B (the callee), B’s application is in a state where it is not considered online (that is reachable using an active socket connection). Sinch notices that B is not online, and tells A to send a push notification to B so that B can answer the call.

When the Sinch client on the caller’s (or sender’s) side observes that the destination client is offline, it notifies the application to trigger the sending of a push notification to the callee’s device.

Push notification data

On startup, each instance of the application is expected to register a device identifier. The identifier is referred to as push notification data and should be provided to the Sinch client by the method registerPushNotificationData:.

Push notifications can be addressed to that identifier in the event that the application goes offline.

The push notification data can be any byte sequence; it is up to you to define its structure and what it contains. However, the push notification data must not exceed 1024 bytes. It should contain enough information to allow your application or application server to use a push service to send a push notification to a specific user of the application on a specific device. For example, an iOS exclusive application would likely use the Apple Push Notification Device Token as push notification data. Multi-platform applications may use a mix of different push services. The following sections assume that Apple Remote Notifications are used, but the use pattern for other push services is similar.

The push notification data can be unregistered by calling the unregisterPushNotificationData method. This disables incoming calls using push notifications addressed to the specific device.

Enable push notifications

Start by enabling support for push notifications when initiating the SINClient:

#import <Sinch/Sinch.h>

id<SINClient> client = [Sinch clientWithApplicationKey:@"<application key>"
                                         applicationSecret:@"<application secret>"
                                                    userId:@"<user id>"];

[client setSupportPushNotifications:YES];

client.delegate = ...;

[client start];

Supporting offline calls and/or messages requires that the application registers for remote push notifications, which in the example that follows is done in the method -[UIApplicationDelegate application:didFinishLaunchingWithOptions:].

- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    UIRemoteNotificationType types = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound;
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];

The next step is to register the push notification data with the SINClient, which in the example below is done by using the APNS device token as push notification data. Upon receiving the the device token from Apple Push Notification Service using the UIApplicationDelegate-method, it is registered with the SINClient.

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
    // get previously initiated Sinch client
    id<SINClient> client = [self sinchClient];

    [client registerPushNotificationData:deviceToken];

Please refer to Apple’s Local and Push Notification Programming Guide for more information on how to obtain the Apple Push Notification Device Token.

Sending and receiving Apple push notifications

To send push messages, you must have a server that is configured for sending push notifications to Apple Push Notification Service. Please see the Sinch REST API User Guide for details on how to handle feedback from Apple Push Notification Service.

Please also refer to Apple’s Local and Push Notification Programming Guide for further details on push notifications.

On the caller side

When the recipient’s application is offline and the app needs to notify the user using a push notification, the caller’s or sender’s application is notified using the delegate method call:shouldSendPushNotifications:.

Because there might be multiple registered devices for the recipient user (for example, the same user is using the application on both an iPhone and an iPad) the callback is passed an array of SINPushPairs. The pairs contain a payload that is Sinch- and call-specific. Moreover, the pairs contain a push data byte array. The Sinch-specific payload should be embedded in the push notification sent to the recipient’s device(s). The push data is the same push data that the recipient’s application registered earlier.

- (void)call:(id<SINCall>)call shouldSendPushNotifications:(NSArray *) pushPairs {
    // Send payload and push data to application server
    // which should communicate with Apple Push Notification Service
    // to send push notifications.

NOTE: This example shows the calling case. Messaging works the same way.

A push notification should be sent to each device, where each pushPair.pushData entry in the array corresponds to one device. The push notification should include the Sinch-specific payload so it can be forwarded to the Sinch client running on the destination device.

The Sinch-specific payload should be embedded as custom payload data in the Apple Push Notification Payload, see JSON example below.

    "aps" : {
        "alert" : "Incoming call from <user>",
        "sound" : "bingbong.aiff"
    "SIN" : <payload>,

The Sinch-specific payload will not exceed 100 bytes, meaning that there should be 156 bytes available in the push notification payload for application-specific purposes.

Please refer to Apple’s Local and Push Notification Programming Guide for further details.

On the callee side

As a prerequisite, offline calling and messaging must have been enabled on the receiver’s side (see [Push Notifications][]).

When the application receives a push notification from the Apple Push Notification Service, the application launches and extracts the Sinch-specific payload from the push notification. Once extracted the payload is forwarded to the Sinch client using the method relayRemotePushNotificationPayload:.

- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    NSDictionary* remotePush = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];

    if (remotePush) {

        // Extract the Sinch-specific payload from the Apple Remote Push Notification
        NSString* payload = [remotePush objectForKey:@"SIN"];

        // Get previously initiated Sinch client
        id<SINClient> client = [self sinchClient];

        id<SINNotificationResult> result = [client relayRemotePushNotificationPayload:payload];

        if (result.isCall && result.callResult.isTimedOut) {
            // Present alert notifying about missed call
        } else if (!result.isValid) {
            // Handle error

Note: You should have similar logic of relaying the push notification payload to the SINClient-instance in your implementation of -[UIApplicationDelegate application: didReceiveRemoteNotification:].


This glossary defines some of the domain specific terms used throughout this document.

Term Explanation
Application The mobile application running on iOS and/or Android. A partner can have more than one application.
Application Instance One installation of the application on a single device.
Application Key A key generated by Sinch. The key is unique to the application. A key looks like 196087a1-e815-4bc4-8984-60d8d8a 43f1d (lowercase hexadecimal formatted GUID).
Application Secret A string generated by Sinch. The secret is used to verify the application. A secret looks like oYdgGRXoxEuJhGDY2KQ/HQ== (Base64-encoded string representation).
Callee The person receiving a call.
Caller The person making a call.
User A user of the mobile application. The actual person holding the mobile device.
User Identity Identity of a user in the application domain. Can be any string, for instance a user name, user id, phone number or email address.
Active Connection A socket connection for signaling purposes where incoming calls are received.

Deprecated features and APIs

Active Connection in Background

Apple has since iOS 10 discontinued support for maintaining a VoIP control connection alive via -[UIApplication setKeepAliveTimeout:handler:]. Attempting to use this method on an iOS device running iOS 10 results in the following warning log: Legacy VoIP background mode is deprecated and no longer supported. The Sinch feature Active connection in background was using the keep alive handler API and is as a consequence no longer supported on iOS. It is recommended to use VoIP Push Notifications to achieve the equivalent functionality.