# Voice Calling Set up voice calling with the Sinch Voice & Video SDK. The SDK supports four types of calls: *App-to-App* (audio or video), *App-to-Phone*, *App-to-SIP* and *Conference* calls. 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 using `SINCallClient` and events are received via `SINCallClientDelegate`. The call client (`SINCallClient`) is owned by the *Sinch client* (`SINClient`) and accessed using `-[SINClient callClient]`. ## Setting Up an *App-to-App* Call Use the call client to start the call using the method `callUserWithId:`, passing the user identifier of the callee (the destination user) as an argument. ```objectivec id callClient = [sinchClient callClient]; id call = [callClient callUserWithId:@""]; call.delegate = self; // Assign delegate to observe call state changes ``` A call object is returned, containing details about the participants in the call, call details such as start time, call state, and possible errors. Assuming the callee's device is available and responsive, the delegate method `callDidProgress:` will be called. It notifies the application that the outbound 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](/docs/in-app-calling/ios/playing-ringtones). When the other party answers, the delegate method `callDidEstablish:` method will be called. Now, the users can start talking. If a progress tone has previously been initiated, it should be stopped now, in the delegate callback method. Also see [Handling Incoming Calls](/docs/in-app-calling/ios/calling#handling-incoming-calls). ## Setting Up an *App-to-Phone* Call An *App-to-Phone* call is a call that's 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. Initiate a call to a phone number by calling the method `-[SINCallClient callPhoneNumber:]`. The phone number should be specified according to the [E.164 number formatting standard](https://community.sinch.com/t5/Glossary/E-164/ta-p/7537) and should be prefixed with a ‘+’. ```objectivec id callClient = [sinchClient callClient]; id call = [callClient callUserWithId:@""]; // Set the call delegate that handles all the call state changes call.delegate= ... ``` **Example**: 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. ### Presenting a number to the destination you are calling Mandatory step! You must provide a CLI (Calling Line Identifier) or your call will fail. You need a number from Sinch so you can provide a valid CLI to the handset you are calling. If you have a trial account, you can use the [test number](https://community.sinch.com/t5/Virtual-Numbers/How-can-I-activate-my-free-number-for-testing/ta-p/8578) that is available for free. If you have already upgraded your account, you can purchase a number to use on the [dashboard](https://dashboard.sinch.com/numbers/your-numbers). Note: When your account is in trial mode, you can only call your [verified numbers](https://dashboard.sinch.com/numbers/verified-numbers). If you want to call any number, you need to upgrade your account! Credits Required Remember, placing an *App-to-Phone* call requires that your Sinch account has sufficient credits. Add credits on your [Account](https://dashboard.sinch.com/account) page. Credits are used each time an *App-to-Phone* call is placed and your account balance is updated after each call. When instantiating the SinchClient you must add the `.callerIdentifier` with a number from your account. ```objectivec (void)createClientWithUserId:(NSString *)userId completion:(void (^)(NSError *))completion { if (self.client == nil) { NSError *error; self.client = [Sinch clientWithApplicationKey:APPLICATION_KEY environmentHost:ENVIRONMENT_HOST userId:userId cli:@"" error:&error]; if (!self.client && completion) { completion(error); return; } ``` Testing DTMF In an *App-to-Phone* scenario, it's possible to issue DTMF sequences using the Sinch SDK. Note that if the receiving end of the call is an iOS device, you might have to disable *VoLTE* ("Voice over LTE") option in the settings of the phone at the receiving end of the call in order to be able to hear DTMF tones. ## Setting Up an *App-to-SIP* Call An *App-to-SIP* call is a call that's made to a [SIP](https://en.wikipedia.org/wiki/Session_Initiation_Protocol) server. Use the method `-[SINCallClient callSIP:]` or `-[SINCallClient callSIP:headers:]` to initiate a *SIP* call. The destination *SIP* identity follows the form of email addresses ([user@domain](mailto:user@domain)), for example [alice@sip.your-sip-provider.com](mailto:alice@sip.your-sip-provider.com). ```objectivec id sinchClient = ...; // Sinch client setup since before. id callClient = [sinchClient callClient]; id call = [callClient callSIP:@""]; ``` When custom *SIP* headers are passed as using `-[SINCallClient callSIP:headers:]`, the headers should be prefixed with ‘x-’. ## 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. ```objectivec id callClient = [sinchClient callClient]; id call = [callClient callConferenceWithId:@""]; ``` It's also possible to connect users to a conference call via the [Sinch REST API](/docs/voice/api-reference/voice/callouts). Note: The identifier for a conference room may not be longer than 64 characters. ## 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 of new incoming calls via the delegate method `didReceiveIncomingCall:`. To get events related to the call, assign a call delegate. The call object contains details about participants, start time, potential error codes, and error messages. See `-[SINCall details]` and [SINCallDetails](https://sinch.github.io/docs/voice/voice-ios-cloud/reference/html/protocols/sincalldetails.html). If you using *VoIP Push Notifications* and [CallKit](https://developer.apple.com/documentation/callkit), use `didReceiveIncomingCall:` primarily to associate the `SINCall` with the *CallKit*-call. example this may be implemented by keeping a mapping between *CallKit* calls and `SINCall`. Example: ```objectivec - (void)client:(id)client didReceiveIncomingCall:(id)call { // Assign delegate call.delegate = self; // Store in a NSDictionary for later, to be able to act on CXCallAction (CallKit action). [self.calls setObject:call forKey: [[NSUUID alloc] initWithUUIDString:call.callId]]; } ``` See our CallKit sample apps In the *Sinch SDK* download, there is a sample app `SinchCallKit.xcodeproj` with a detailed example on how to associate `SINCall` with *CallKit* calls. If you are **not** using *VoIP Push Notifications* and [CallKit](https://developer.apple.com/documentation/callkit), then use `didReceiveIncomingCall:` to assign a delegate, and present a call UI. If the application is in foreground, you may also want to [play a ringtone](/docs/in-app-calling/ios/playing-ringtones). ```objectivec - (void)client:(id)client didReceiveIncomingCall:(id)call { // Assign delegate call.delegate = self; // Play ringtone // Present UI for call (UIViewController / segue) } ``` ### Incoming Video Call A video call will just like a voice-only call trigger the delegate method `didReceiveIncomingCall:`. To determine whether an incoming call contains a video stream, the property `SINCallDetails.isVideoOffered` can be used. Also see [Video Calling](/docs/in-app-calling/ios/video-calling) for details on how to add video views. ### Answering an Incoming Call To answer a call, use the method `-[SINCall answer]`. If a ringtone was previously played, it should be stopped now. User presses the answer button: ```objectivec // User answers the call [call answer]; // Stop playing ringing tone (unless using CallKit) ``` Now, the clients on both ends will 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 shouldn't be answered, use the method `-[SINCall hangup]` to decline the call. The caller will be notified that the incoming call was denied (via `-[SINCallDelegate callDidEnd:]`). If a ringtone was previously played, it should be stopped now. User presses the hangup button: ```objectivec // User declines the call [call hangup]; // Stop playing ringing tone ``` ## Disconnecting a Call When the user wants to disconnect an ongoing call, use the method `-[SINCall hangup]`. Either user taking part in a call can disconnect it. Hanging up a call: ```objectivec [call hangup]; ``` When either party disconnects a call, the application is notified using the call delegate method `-[SINCallDelegate 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: ```objectivec // Starting a call id call = [client callUserWithId:@""]; // User changed his/her mind, let's hangup. [call hangup]; ``` Handling a call that ends: ```objectivec // SINCallDelegate implementation - (void)callDidEnd:(id) call { // Update user interface, example hide the call screen. ``` ## Request User Permission for Using the Microphone Recording audio always requires explicit permission from the user. Your app must provide a description for its use of the microphone in terms of the *Info.plist* key [NSMicrophoneUsageDescription](https://developer.apple.com/documentation/bundleresources/information_property_list/nsmicrophoneusagedescription). See Apple documentation on [`+[AVCaptureDevice requestAccessForMediaType:completionHandler:]`](https://developer.apple.com/documentation/avfoundation/avcapturedevice/1624584-requestaccessformediatype) for details on how to request user permission. Note: Unless the application has explicitly requested permission to use the microphone, the user is shown a dialog the first time the microphone is activated. This may not provide the best user experience, so we advice to consider explicitly requesting microphone permission in advance.